[ create a new paste ] login | about

Link: http://codepad.org/gvm3A88k    [ raw code | fork ]

D, pasted on Jan 31:
module singleton;

import std.concurrency;
import core.atomic;
import core.thread;

class LockSingleton
{
    static LockSingleton get()
    {
        __gshared LockSingleton _instance;

        synchronized
        {
            if (_instance is null) {
                _instance = new LockSingleton;
            }
        }

        return _instance;
    }

private:
    this() { }
}

class SyncSingleton
{
    static SyncSingleton get()
    {
        static bool _instantiated;  // tls
        __gshared SyncSingleton _instance;

        if (!_instantiated)
        {
            synchronized
            {
                if (_instance is null) {
                    _instance = new SyncSingleton;
                }

                _instantiated = true;
            }
        }

        return _instance;
    }

private:
    this() { }
}

class AtomicSingleton
{
    static AtomicSingleton get()
    {
        shared static bool _instantiated = false;
        __gshared AtomicSingleton _instance;

        // only enter synchronized block if not instantiated
        if (!atomicLoad!(MemoryOrder.acq)(_instantiated))
        {
            synchronized
            {
                if (_instance is null) {
                    _instance = new AtomicSingleton;
                }
                atomicStore!(MemoryOrder.rel)(_instantiated, true);                
            }
        }

        return _instance;
    }
}

version (unittest)
{
    ulong _thread_call_count;  // TLS
}

unittest
{
    import std.datetime;
    import std.stdio;
    import std.string;
    import std.typetuple;
    import std.exception;
    import core.atomic;

    foreach (TestClass; TypeTuple!(LockSingleton, SyncSingleton, AtomicSingleton))
    {
        // mixin to avoid multiple definition errors
        mixin(q{
        shared ulong msecs = 0;
        static void test_%1$s(shared ulong* counter)
        {
            auto sw = StopWatch(AutoStart.yes);
            foreach (i; 0 .. 1024_000)
            {
                // just trying to avoid the compiler from doing dead-code optimization
                _thread_call_count += enforce(TestClass.get() !is null);
            }
            sw.stop();
            atomicOp!"+="(*counter, sw.peek.msecs);
        }

        enum threadCount = 4;
        foreach (i; 0 .. threadCount)
            spawn(&test_%1$s, &msecs);
        thread_joinAll();

        }.format(TestClass.stringof));

        writefln("Test time for %s: %s msecs.", TestClass.stringof, cast(double)msecs/threadCount);
    }
}

void main() { }


Create a new paste based on this one


Comments: