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?

Reply via email to