digitalmars.D.learn - Iterating over thread local storage variables
- maik klein (56/56) Mar 11 2016 I want to create a logger in a multithreaded system. I wanted to
- Anonymouse (4/14) Mar 11 2016 As a drive-by comment, mind that there is a race there.
- sigod (5/19) Mar 11 2016 That's why inside of `synchronized` block you can see `if
- Anonymouse (5/24) Mar 11 2016 It does, yes, but it also calls instance_.tls.insertBack
- sigod (5/21) Mar 11 2016 Indeed. You're right. I didn't even look at `instance_.tls...`
I want to create a logger in a multithreaded system. I wanted to expose a global variable like logger.log("something"); I also wanted to reuse D's thread local global variables because that would make it easy to log in a multithreaded system. This is really easy to do, but the problem is that at one point I need to collect all `loggers` and merge them. So I thought about writing something like this: import std.stdio; class Singleton(T) { import std.container: Array; private this() {} // Cache instantiation flag in thread-local bool // Thread local private static bool instantiated_; // Thread global private __gshared Singleton!T instance_; static Singleton!T get() { if (!instantiated_) { synchronized(Singleton!T.classinfo){ if (!instance_){ instance_ = new Singleton!T(); } instantiated_ = true; instance_.tls.insertBack(&instance_.value); } } return instance_; } __gshared Array!(T*) tls; static T value; } unittest{ import std.concurrency; import core.thread; auto s = Singleton!int.get(); foreach(index; 0..10){ spawn((int a){ auto s = Singleton!int.get(); s.value = a; }, index); } Thread.sleep( dur!("seconds")( 1 ) ); writeln("--"); foreach(p; s.tls){ writeln(*p); } } Basically every time `instantiated_` is false, I know that I am on a new thread and then I push the reference of `value` into a global array. But how do I access `tls` in a thread safe manner? Is there another way of doing this?
Mar 11 2016
On Friday, 11 March 2016 at 15:21:38 UTC, maik klein wrote:static Singleton!T get() { if (!instantiated_) { synchronized(Singleton!T.classinfo){ if (!instance_){ instance_ = new Singleton!T(); } instantiated_ = true; instance_.tls.insertBack(&instance_.value);As a drive-by comment, mind that there is a race there. _instantiated may have been set after the if statement but before the synchronized block. You have to test it again inside.
Mar 11 2016
On Friday, 11 March 2016 at 17:03:38 UTC, Anonymouse wrote:On Friday, 11 March 2016 at 15:21:38 UTC, maik klein wrote:That's why inside of `synchronized` block you can see `if (!instance_)`. Watch this for details: https://www.youtube.com/watch?v=yMNMV9JlkcQ&t=27m54sstatic Singleton!T get() { if (!instantiated_) { synchronized(Singleton!T.classinfo){ if (!instance_){ instance_ = new Singleton!T(); } instantiated_ = true; instance_.tls.insertBack(&instance_.value);As a drive-by comment, mind that there is a race there. _instantiated may have been set after the if statement but before the synchronized block. You have to test it again inside.
Mar 11 2016
On Friday, 11 March 2016 at 17:33:43 UTC, sigod wrote:On Friday, 11 March 2016 at 17:03:38 UTC, Anonymouse wrote:It does, yes, but it also calls instance_.tls.insertBack unconditionally. To illustrate: http://dpaste.dzfl.pl/8f3e78f3265a7 Apologies for derailing.On Friday, 11 March 2016 at 15:21:38 UTC, maik klein wrote:That's why inside of `synchronized` block you can see `if (!instance_)`.static Singleton!T get() { if (!instantiated_) { synchronized(Singleton!T.classinfo){ if (!instance_){ instance_ = new Singleton!T(); } instantiated_ = true; instance_.tls.insertBack(&instance_.value);As a drive-by comment, mind that there is a race there. _instantiated may have been set after the if statement but before the synchronized block. You have to test it again inside.
Mar 11 2016
On Friday, 11 March 2016 at 18:45:13 UTC, Anonymouse wrote:On Friday, 11 March 2016 at 17:33:43 UTC, sigod wrote:Indeed. You're right. I didn't even look at `instance_.tls...` line. I guess `insertBack` just need to be moved inside of `if (!instance_)` scope.On Friday, 11 March 2016 at 17:03:38 UTC, Anonymouse wrote:It does, yes, but it also calls instance_.tls.insertBack unconditionally. To illustrate: http://dpaste.dzfl.pl/8f3e78f3265a7 Apologies for derailing.On Friday, 11 March 2016 at 15:21:38 UTC, maik klein wrote:That's why inside of `synchronized` block you can see `if (!instance_)`.[...]As a drive-by comment, mind that there is a race there. _instantiated may have been set after the if statement but before the synchronized block. You have to test it again inside.
Mar 11 2016