Thread overview | |||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
June 30, 2014 Thread-safety and lazy-initialization of libraries | ||||
---|---|---|---|---|
| ||||
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. |
June 30, 2014 Re: Thread-safety and lazy-initialization of libraries | ||||
---|---|---|---|---|
| ||||
Posted in reply to Sergey Protko | 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
|
June 30, 2014 Re: Thread-safety and lazy-initialization of libraries | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | On Monday, 30 June 2014 at 21:05:32 UTC, bearophile wrote:
> 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
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.
|
June 30, 2014 Re: Thread-safety and lazy-initialization of libraries | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | On 06/30/2014 11:05 PM, bearophile wrote: > 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 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 Wey |
June 30, 2014 Re: Thread-safety and lazy-initialization of libraries | ||||
---|---|---|---|---|
| ||||
Posted in reply to Sergey Protko | 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:
>> 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
>
> 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.
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();
}
|
June 30, 2014 Re: Thread-safety and lazy-initialization of libraries | ||||
---|---|---|---|---|
| ||||
Posted in reply to Mike Wey | 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: > >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 > > 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. [...] 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) |
June 30, 2014 Re: Thread-safety and lazy-initialization of libraries | ||||
---|---|---|---|---|
| ||||
Posted in reply to Rene Zwanenburg | 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:
>> On Monday, 30 June 2014 at 21:05:32 UTC, bearophile wrote:
>>> 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
>>
>> 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.
>
> 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();
> }
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?
|
June 30, 2014 Re: Thread-safety and lazy-initialization of libraries | ||||
---|---|---|---|---|
| ||||
Posted in reply to H. S. Teoh | 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:
>> On 06/30/2014 11:05 PM, bearophile wrote:
>> >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
>>
>> 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.
> [...]
>
> 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
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.
|
June 30, 2014 Re: Thread-safety and lazy-initialization of libraries | ||||
---|---|---|---|---|
| ||||
Posted in reply to Sergey Protko | 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 |
June 30, 2014 Re: Thread-safety and lazy-initialization of libraries | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | 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 |
Copyright © 1999-2021 by the D Language Foundation