/**
 * The mutex module provides a primitive for maintaining mutually exclusive
 * access.
 *
 * Copyright: Copyright Sean Kelly 2005 - 2009.
 * License:   $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
 * Authors:   Sean Kelly
 * Source:    $(DRUNTIMESRC core/sync/_mutex.d)
 */

/*          Copyright Sean Kelly 2005 - 2009.
 * Distributed under the Boost Software License, Version 1.0.
 *    (See accompanying file LICENSE or copy at
 *          http://www.boost.org/LICENSE_1_0.txt)
 */
module core.sync.mutex;


public import core.sync.exception;

version (Windows)
{
    import core.sys.windows.winbase /+: CRITICAL_SECTION, DeleteCriticalSection,
        EnterCriticalSection, InitializeCriticalSection, LeaveCriticalSection,
        TryEnterCriticalSection+/;
}
else version (Posix)
{
    import core.sys.posix.pthread : pthread_mutex_destroy, pthread_mutex_init, pthread_mutex_lock,
        PTHREAD_MUTEX_RECURSIVE, pthread_mutex_trylock, pthread_mutex_unlock, pthread_mutexattr_destroy,
        pthread_mutexattr_init, pthread_mutexattr_settype;
    import core.sys.posix.sys.types : pthread_mutex_t, pthread_mutexattr_t;
}
else
{
    static assert(false, "Platform not supported");
}

////////////////////////////////////////////////////////////////////////////////
// Mutex
//
// void lock();
// void unlock();
// bool tryLock();
////////////////////////////////////////////////////////////////////////////////


/**
 * This class represents a general purpose, recursive mutex.
 *
 * Implemented using `pthread_mutex` on Posix and `CRITICAL_SECTION`
 * on Windows.
 */
class Mutex :
    Object.Monitor
{
    ////////////////////////////////////////////////////////////////////////////
    // Initialization
    ////////////////////////////////////////////////////////////////////////////


    /**
     * Initializes a mutex object.
     *
     */
    this() @trusted nothrow @nogc
    {
        this(true);
    }

    /// ditto
    this() shared @trusted nothrow @nogc
    {
        this(true);
    }

    // Undocumented, useful only in Mutex.this().
    private this(this Q)(bool _unused_) @trusted nothrow @nogc
        if (is(Q == Mutex) || is(Q == shared Mutex))
    {
        version (Windows)
        {
            InitializeCriticalSection(cast(CRITICAL_SECTION*) &m_hndl);
        }
        else version (Posix)
        {
            import core.internal.abort : abort;
            pthread_mutexattr_t attr = void;

            !pthread_mutexattr_init(&attr) ||
                abort("Error: pthread_mutexattr_init failed.");

            scope (exit) !pthread_mutexattr_destroy(&attr) ||
                abort("Error: pthread_mutexattr_destroy failed.");

            !pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) ||
                abort("Error: pthread_mutexattr_settype failed.");

            !pthread_mutex_init(cast(pthread_mutex_t*) &m_hndl, &attr) ||
                abort("Error: pthread_mutex_init failed.");
        }

        auto self = cast(Mutex) this;
        self.m_proxy.link = self;
        this.__monitor = cast(void*) &m_proxy;
    }


    /**
     * Initializes a mutex object and sets it as the monitor for `obj`.
     *
     * In:
     *  `obj` must not already have a monitor.
     */
    this(Object obj) @trusted nothrow @nogc
    {
        this(obj, true);
    }

    /// ditto
    this(Object obj) shared @trusted nothrow @nogc
    {
        this(obj, true);
    }

    // Undocumented, useful only in Mutex.this(Object).
    private this(this Q)(Object obj, bool _unused_) @trusted nothrow @nogc
        if (is(Q == Mutex) || is(Q == shared Mutex))
    in
    {
        assert(obj !is null,
            "The provided object must not be null.");
        assert(obj.__monitor is null,
            "The provided object has a monitor already set!");
    }
    do
    {
        this();
        obj.__monitor = cast(void*) &m_proxy;
    }


    ~this() @trusted nothrow @nogc
    {
        version (Windows)
        {
            DeleteCriticalSection(&m_hndl);
        }
        else version (Posix)
        {
            import core.internal.abort : abort;
            !pthread_mutex_destroy(&m_hndl) ||
                abort("Error: pthread_mutex_destroy failed.");
        }
        this.__monitor = null;
    }


    ////////////////////////////////////////////////////////////////////////////
    // General Actions
    ////////////////////////////////////////////////////////////////////////////


    /**
     * If this lock is not already held by the caller, the lock is acquired,
     * then the internal counter is incremented by one.
     *
     * Note:
     *    `Mutex.lock` does not throw, but a class derived from Mutex can throw.
     *    Use `lock_nothrow` in `nothrow @nogc` code.
     */
    @trusted void lock()
    {
        lock_nothrow();
    }

    /// ditto
    @trusted void lock() shared
    {
        lock_nothrow();
    }

    /// ditto
    final void lock_nothrow(this Q)() nothrow @trusted @nogc
        if (is(Q == Mutex) || is(Q == shared Mutex))
    {
        auto self = cast(Mutex) this;
        version (Windows)
        {
            EnterCriticalSection(&self.m_hndl);
        }
        else version (Posix)
        {
            if (pthread_mutex_lock(&self.m_hndl) == 0)
                return;

            SyncError syncErr = cast(SyncError) __traits(initSymbol, SyncError).ptr;
            syncErr.msg = "Unable to lock mutex.";
            throw syncErr;
        }
    }

    /**
     * Decrements the internal lock count by one.  If this brings the count to
     * zero, the lock is released.
     *
     * Note:
     *    `Mutex.unlock` does not throw, but a class derived from Mutex can throw.
     *    Use `unlock_nothrow` in `nothrow @nogc` code.
     */
    @trusted void unlock()
    {
        unlock_nothrow();
    }

    /// ditto
    @trusted void unlock() shared
    {
        unlock_nothrow();
    }

    /// ditto
    final void unlock_nothrow(this Q)() nothrow @trusted @nogc
        if (is(Q == Mutex) || is(Q == shared Mutex))
    {
        auto self = cast(Mutex) this;
        version (Windows)
        {
            LeaveCriticalSection(&self.m_hndl);
        }
        else version (Posix)
        {
            if (pthread_mutex_unlock(&self.m_hndl) == 0)
                return;

            SyncError syncErr = cast(SyncError) __traits(initSymbol, SyncError).ptr;
            syncErr.msg = "Unable to unlock mutex.";
            throw syncErr;
        }
    }

    /**
     * If the lock is held by another caller, the method returns.  Otherwise,
     * the lock is acquired if it is not already held, and then the internal
     * counter is incremented by one.
     *
     * Returns:
     *  true if the lock was acquired and false if not.
     *
     * Note:
     *    `Mutex.tryLock` does not throw, but a class derived from Mutex can throw.
     *    Use `tryLock_nothrow` in `nothrow @nogc` code.
     */
    bool tryLock() @trusted
    {
        return tryLock_nothrow();
    }

    /// ditto
    bool tryLock() shared @trusted
    {
        return tryLock_nothrow();
    }

    /// ditto
    final bool tryLock_nothrow(this Q)() nothrow @trusted @nogc
        if (is(Q == Mutex) || is(Q == shared Mutex))
    {
        auto self = cast(Mutex) this;
        version (Windows)
        {
            return TryEnterCriticalSection(&self.m_hndl) != 0;
        }
        else version (Posix)
        {
            return pthread_mutex_trylock(&self.m_hndl) == 0;
        }
    }


private:
    version (Windows)
    {
        CRITICAL_SECTION    m_hndl;
    }
    else version (Posix)
    {
        pthread_mutex_t     m_hndl;
    }

    struct MonitorProxy
    {
        Object.Monitor link;
    }

    MonitorProxy            m_proxy;


package:
    version (Posix)
    {
        pthread_mutex_t* handleAddr() @nogc
        {
            return &m_hndl;
        }
    }
}

///
/* @safe nothrow -> see druntime PR 1726 */
// Test regular usage.
unittest
{
    import core.thread : Thread;

    class Resource
    {
        Mutex mtx;
        int cargo;

        this() shared @safe nothrow
        {
            mtx = new shared Mutex();
            cargo = 42;
        }

        void useResource() shared @trusted nothrow @nogc
        {
            mtx.lock_nothrow();
            (cast() cargo) += 1;
            mtx.unlock_nothrow();
        }
    }

    shared Resource res = new shared Resource();

    auto otherThread = new Thread(
    {
        foreach (i; 0 .. 10000)
            res.useResource();
    }).start();

    foreach (i; 0 .. 10000)
        res.useResource();

    otherThread.join();

    assert (res.cargo == 20042);
}

// Test @nogc usage.
@system @nogc nothrow unittest
{
    import core.lifetime : emplace;
    import core.stdc.stdlib : free, malloc;

    auto mtx = cast(shared Mutex) malloc(__traits(classInstanceSize, Mutex));
    emplace(mtx);

    mtx.lock_nothrow();

    { // test recursive locking
        mtx.tryLock_nothrow();
        mtx.unlock_nothrow();
    }

    mtx.unlock_nothrow();

    // In general destorying classes like this is not
    // safe, but since we know that the only base class
    // of Mutex is Object and it doesn't have a dtor
    // we can simply call the non-virtual __dtor() here.

    // Ok to cast away shared because destruction
    // should happen only from a single thread.
    (cast(Mutex) mtx).__dtor();

    // Verify that the underlying implementation has been destroyed by checking
    // that locking is not possible. This assumes that the underlying
    // implementation is well behaved and makes the object non-lockable upon
    // destruction. The Bionic, DragonFly, Musl, and Solaris C runtimes don't
    // appear to do so, so skip this test.
    version (CRuntime_Bionic) {} else
    version (CRuntime_Musl) {} else
    version (DragonFlyBSD) {} else
    version (Solaris) {} else
    assert(!mtx.tryLock_nothrow());

    free(cast(void*) mtx);
}

// Test single-thread (non-shared) use.
unittest
{
    Mutex m = new Mutex();

    m.lock();

    m.tryLock();
    m.unlock();

    m.unlock();
}

unittest
{
    import core.thread;

    auto mutex      = new Mutex;
    int  numThreads = 10;
    int  numTries   = 1000;
    int  lockCount  = 0;

    void testFn()
    {
        for (int i = 0; i < numTries; ++i)
        {
            synchronized (mutex)
            {
                ++lockCount;
            }
        }
    }

    auto group = new ThreadGroup;

    for (int i = 0; i < numThreads; ++i)
        group.create(&testFn);

    group.joinAll();
    assert(lockCount == numThreads * numTries);
}
