[ create a new paste ] login | about

Link: http://codepad.org/ghZdjvUE    [ 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;
    }

    version (unittest) static void nullify() { _instance = null; }

private:
    this() { }
    __gshared LockSingleton _instance;
}

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;
    }

    version (unittest) static void nullify() { _instance = null; }

private:
    this() { }
    __gshared SyncSingleton _instance;
}

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) static void nullify() { _instance = null; _instantiated = false; }
private:
    shared static bool _instantiated = false;
    __gshared AtomicSingleton _instance;
}

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

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

    enum numRuns = 10;
    enum threadCount = 1024;

    foreach(immutable _; 0 .. numRuns) {
    foreach (TestClass; TypeTuple!(/*LockSingleton, */SyncSingleton, AtomicSingleton))
    {
        // mixin to avoid multiple definition errors
        mixin(q{
        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();
            atomicStore(*counter, sw.peek.msecs);
        }

        // Not shared because dmd's Phobos won't allow to reduce() it later
        ulong[threadCount] timers;
        foreach (i; 0 .. threadCount)
            spawn(&test_%1$s, cast(shared(ulong*))&timers[i]);
        thread_joinAll();
        auto grandTotal = timers.reduce!"a+b";
        TestClass.nullify();

        }.format(TestClass.stringof));

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

void main() { }


Create a new paste based on this one


Comments: