digitalmars.D.learn - Thread-safety and lazy-initialization of libraries
- Sergey Protko (13/13) Jun 30 2014 For some research i decided to write small high-level binding for
- bearophile (6/11) Jun 30 2014 I think module "static this" is thread-local, so in theory you
- Sergey Protko (5/16) Jun 30 2014 I thought about this. But static constructors doesn't solve
- Rene Zwanenburg (12/31) Jun 30 2014 Use a shared module constructor? It's called only once, not
- Sergey Protko (8/40) Jun 30 2014 Oh, sorry. I doesn't thought about module constructors. But how
- Mike Wey (6/16) Jun 30 2014 You'll need to use a `shared static this` if those functions can be
- H. S. Teoh via Digitalmars-d-learn (11/29) Jun 30 2014 [...]
- Sergey Protko (20/60) Jun 30 2014 Something like this?
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (7/8) Jun 30 2014 David Simcha's DConf 2013 presentation covers this question. At around
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (5/7) Jun 30 2014 Here is the information about an article he wrote on the topic:
- Sean Kelly (2/6) Jul 01 2014 pthread_once comes to mind.
For some research i decided to write small high-level binding for libmpg123. The question is how to write thread-safe lazy-initialization of library. libmpg123 has mpg123_init and mpg123_exit functions, which are not thread-safe, so we should to call them only once per process. Most of useful libraries also has such stuff. But manual initialization is killing all beauty of high-level bindings. Is there any proper way to do on-demand lazy-initialization of used library, which will be also thread-safe? How do i need to handle cases where some methods, which requires library to be initialized, called from different threads at the same time? Thanks for your answers.
Jun 30 2014
Sergey Protko:libmpg123 has mpg123_init and mpg123_exit functions, which are not thread-safe, so we should to call them only once per process. Most of useful libraries also has such stuff. But manual initialization is killing all beauty of high-level bindings.I think module "static this" is thread-local, so in theory you can use that. But I don't know if it's a good idea to perform heavy computations inside those module static this. Bye, bearophile
Jun 30 2014
On Monday, 30 June 2014 at 21:05:32 UTC, bearophile wrote:Sergey Protko:I thought about this. But static constructors doesn't solve problem with on-demand initialization in case, where there is several classes. For example Decoder and Encoder both requires library to be initialized before they are actually be used.libmpg123 has mpg123_init and mpg123_exit functions, which are not thread-safe, so we should to call them only once per process. Most of useful libraries also has such stuff. But manual initialization is killing all beauty of high-level bindings.I think module "static this" is thread-local, so in theory you can use that. But I don't know if it's a good idea to perform heavy computations inside those module static this. Bye, bearophile
Jun 30 2014
On Monday, 30 June 2014 at 21:32:34 UTC, Sergey Protko wrote:On Monday, 30 June 2014 at 21:05:32 UTC, bearophile wrote:Use a shared module constructor? It's called only once, not per-thread. module mpg123; shared static this() { mpg123_init(); } shared static ~this() { mpg123_exit(); }Sergey Protko:I thought about this. But static constructors doesn't solve problem with on-demand initialization in case, where there is several classes. For example Decoder and Encoder both requires library to be initialized before they are actually be used.libmpg123 has mpg123_init and mpg123_exit functions, which are not thread-safe, so we should to call them only once per process. Most of useful libraries also has such stuff. But manual initialization is killing all beauty of high-level bindings.I think module "static this" is thread-local, so in theory you can use that. But I don't know if it's a good idea to perform heavy computations inside those module static this. Bye, bearophile
Jun 30 2014
On Monday, 30 June 2014 at 21:36:10 UTC, Rene Zwanenburg wrote:On Monday, 30 June 2014 at 21:32:34 UTC, Sergey Protko wrote:Oh, sorry. I doesn't thought about module constructors. But how we should handle errors on initialization? I can't just throw an exception from module constructor. Also this way isn't lazy at all) I could write something like thread-safe singleton with lazy initialization, which returns status of library (OK or error code), but i not sure about that. Is it reasonable way?On Monday, 30 June 2014 at 21:05:32 UTC, bearophile wrote:Use a shared module constructor? It's called only once, not per-thread. module mpg123; shared static this() { mpg123_init(); } shared static ~this() { mpg123_exit(); }Sergey Protko:I thought about this. But static constructors doesn't solve problem with on-demand initialization in case, where there is several classes. For example Decoder and Encoder both requires library to be initialized before they are actually be used.libmpg123 has mpg123_init and mpg123_exit functions, which are not thread-safe, so we should to call them only once per process. Most of useful libraries also has such stuff. But manual initialization is killing all beauty of high-level bindings.I think module "static this" is thread-local, so in theory you can use that. But I don't know if it's a good idea to perform heavy computations inside those module static this. Bye, bearophile
Jun 30 2014
On 06/30/2014 11:05 PM, bearophile wrote:Sergey Protko:You'll need to use a `shared static this` if those functions can be called only once per process. A regular static this is executed once per Thread. -- Mike Weylibmpg123 has mpg123_init and mpg123_exit functions, which are not thread-safe, so we should to call them only once per process. Most of useful libraries also has such stuff. But manual initialization is killing all beauty of high-level bindings.I think module "static this" is thread-local, so in theory you can use that. But I don't know if it's a good idea to perform heavy computations inside those module static this. Bye, bearophile
Jun 30 2014
On Mon, Jun 30, 2014 at 11:36:21PM +0200, Mike Wey via Digitalmars-d-learn wrote:On 06/30/2014 11:05 PM, bearophile wrote:[...] Depending on how lazy you want initialization to be, you might want to consider using __gshared (for process-global state) with appropriate synchronization locks to make sure threads don't stomp over each other. Then you can check if component X has been initialized (per process) each time a thread calls some function that depends on X, and if it is, initialize it, if not, just do nothing (or return the global instance). T -- Verbing weirds language. -- Calvin (& Hobbes)Sergey Protko:You'll need to use a `shared static this` if those functions can be called only once per process. A regular static this is executed once per Thread.libmpg123 has mpg123_init and mpg123_exit functions, which are not thread-safe, so we should to call them only once per process. Most of useful libraries also has such stuff. But manual initialization is killing all beauty of high-level bindings.I think module "static this" is thread-local, so in theory you can use that. But I don't know if it's a good idea to perform heavy computations inside those module static this. Bye, bearophile
Jun 30 2014
On Monday, 30 June 2014 at 21:55:56 UTC, H. S. Teoh via Digitalmars-d-learn wrote:On Mon, Jun 30, 2014 at 11:36:21PM +0200, Mike Wey via Digitalmars-d-learn wrote:Something like this? module libmpg123; __gshared bool initialized_; static bool initializedTLS; void init_requires() { if (!initializedTLS) { synchronized { if (!initialized_) { // todo: handle errors? mpg123_init(); initialized_ = true; } initializedTLS = initialized_; } } } Well, i'll try... Thank you.On 06/30/2014 11:05 PM, bearophile wrote:[...] Depending on how lazy you want initialization to be, you might want to consider using __gshared (for process-global state) with appropriate synchronization locks to make sure threads don't stomp over each other. Then you can check if component X has been initialized (per process) each time a thread calls some function that depends on X, and if it is, initialize it, if not, just do nothing (or return the global instance). TSergey Protko:You'll need to use a `shared static this` if those functions can be called only once per process. A regular static this is executed once per Thread.libmpg123 has mpg123_init and mpg123_exit functions, which are not thread-safe, so we should to call them only once per process. Most of useful libraries also has such stuff. But manual initialization is killing all beauty of high-level bindings.I think module "static this" is thread-local, so in theory you can use that. But I don't know if it's a good idea to perform heavy computations inside those module static this. Bye, bearophile
Jun 30 2014
On 06/30/2014 01:53 PM, Sergey Protko wrote:The question is how to write thread-safe lazy-initialization of library.David Simcha's DConf 2013 presentation covers this question. At around minute 28: https://www.youtube.com/watch?feature=player_detailpage&v=yMNMV9JlkcQ#t=1690 Unfortunately, he never published his slides. Ali
Jun 30 2014
On 06/30/2014 03:46 PM, Ali Çehreli wrote:https://www.youtube.com/watch?feature=player_detailpage&v=yMNMV9JlkcQ#t=1690 Unfortunately, he never published his slides.Here is the information about an article he wrote on the topic: http://forum.dlang.org/thread/pelhvaxwjzhehdjtpsav forum.dlang.org#post-pelhvaxwjzhehdjtpsav:40forum.dlang.org Ali
Jun 30 2014
On Monday, 30 June 2014 at 20:53:25 UTC, Sergey Protko wrote:Is there any proper way to do on-demand lazy-initialization of used library, which will be also thread-safe? How do i need to handle cases where some methods, which requires library to be initialized, called from different threads at the same time?pthread_once comes to mind.
Jul 01 2014