/**
 * Contains the implementation for object monitors.
 *
 * Copyright: Copyright Digital Mars 2000 - 2015.
 * License:   $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
 * Authors:   Walter Bright, Sean Kelly, Martin Nowak
 * Source: $(DRUNTIMESRC rt/_monitor_.d)
 */
module rt.monitor_;

import core.atomic;
import core.stdc.stdlib : calloc, free, realloc;
import core.stdc.string : memmove;

version (Windows)
{
    import core.sys.windows.winbase /+: CRITICAL_SECTION, DeleteCriticalSection,
        EnterCriticalSection, InitializeCriticalSection, LeaveCriticalSection+/;
}
else version (Posix)
{
    import core.sys.posix.pthread : pthread_mutex_destroy, pthread_mutex_init, pthread_mutex_lock,
        PTHREAD_MUTEX_RECURSIVE, 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(0, "Unsupported platform");
}

// NOTE: The dtor callback feature is only supported for monitors that are not
//       supplied by the user.  The assumption is that any object with a user-
//       supplied monitor may have special storage or lifetime requirements and
//       that as a result, storing references to local objects within Monitor
//       may not be safe or desirable.  Thus, devt is only valid if impl is
//       null.

extern (C) void _d_setSameMutex(shared Object ownee, shared Object owner) nothrow
in
{
    assert(ownee.__monitor is null);
}
do
{
    auto m = ensureMonitor(cast(Object) owner);
    if (m.impl is null)
    {
        atomicOp!"+="(m.refs, size_t(1));
    }
    // Assume the monitor is garbage collected and simply copy the reference.
    ownee.__monitor = owner.__monitor;
}

extern (C) void _d_monitordelete(Object h, bool det)
{
    auto m = getMonitor(h);
    if (m is null)
        return;

    if (m.impl)
    {
        // let the GC collect the monitor
        setMonitor(h, null);
    }
    else if (!atomicOp!"-="(m.refs, size_t(1)))
    {
        // refcount == 0 means unshared => no synchronization required
        disposeEvent(cast(Monitor*) m, h);
        deleteMonitor(cast(Monitor*) m);
        setMonitor(h, null);
    }
}

// does not call dispose events, for internal use only
extern (C) void _d_monitordelete_nogc(Object h) @nogc nothrow
{
    auto m = getMonitor(h);
    if (m is null)
        return;

    if (m.impl)
    {
        // let the GC collect the monitor
        setMonitor(h, null);
    }
    else if (!atomicOp!"-="(m.refs, size_t(1)))
    {
        // refcount == 0 means unshared => no synchronization required
        deleteMonitor(cast(Monitor*) m);
        setMonitor(h, null);
    }
}

extern (C) void _d_monitorenter(Object h)
in
{
    assert(h !is null, "Synchronized object must not be null.");
}
do
{
    auto m = cast(Monitor*) ensureMonitor(h);
    auto i = m.impl;
    if (i is null)
        lockMutex(&m.mtx);
    else
        i.lock();
}

extern (C) void _d_monitorexit(Object h)
{
    auto m = cast(Monitor*) getMonitor(h);
    auto i = m.impl;
    if (i is null)
        unlockMutex(&m.mtx);
    else
        i.unlock();
}

extern (C) void rt_attachDisposeEvent(Object h, DEvent e)
{
    synchronized (h)
    {
        auto m = cast(Monitor*) getMonitor(h);
        assert(m.impl is null);

        foreach (ref v; m.devt)
        {
            if (v is null || v == e)
            {
                v = e;
                return;
            }
        }

        auto len = m.devt.length + 4; // grow by 4 elements
        auto pos = m.devt.length; // insert position
        auto p = realloc(m.devt.ptr, DEvent.sizeof * len);
        import core.exception : onOutOfMemoryError;

        if (!p)
            onOutOfMemoryError();
        m.devt = (cast(DEvent*) p)[0 .. len];
        m.devt[pos + 1 .. len] = null;
        m.devt[pos] = e;
    }
}

extern (C) void rt_detachDisposeEvent(Object h, DEvent e)
{
    synchronized (h)
    {
        auto m = cast(Monitor*) getMonitor(h);
        assert(m.impl is null);

        foreach (p, v; m.devt)
        {
            if (v == e)
            {
                memmove(&m.devt[p], &m.devt[p + 1], (m.devt.length - p - 1) * DEvent.sizeof);
                m.devt[$ - 1] = null;
                return;
            }
        }
    }
}

nothrow:

extern (C) void _d_monitor_staticctor() @nogc nothrow
{
    version (Posix)
    {
        pthread_mutexattr_init(&gattr);
        pthread_mutexattr_settype(&gattr, PTHREAD_MUTEX_RECURSIVE);
    }
    initMutex(&gmtx);
}

extern (C) void _d_monitor_staticdtor() @nogc nothrow
{
    destroyMutex(&gmtx);
    version (Posix)
        pthread_mutexattr_destroy(&gattr);
}

package:

// This is what the monitor reference in Object points to
alias IMonitor = Object.Monitor;
alias DEvent = void delegate(Object);

version (Windows)
{
    alias Mutex = CRITICAL_SECTION;

    alias initMutex = InitializeCriticalSection;
    alias destroyMutex = DeleteCriticalSection;
    alias lockMutex = EnterCriticalSection;
    alias unlockMutex = LeaveCriticalSection;
}
else version (Posix)
{
@nogc:
    alias Mutex = pthread_mutex_t;
    __gshared pthread_mutexattr_t gattr;

    void initMutex(pthread_mutex_t* mtx)
    {
        pthread_mutex_init(mtx, &gattr) && assert(0);
    }

    void destroyMutex(pthread_mutex_t* mtx)
    {
        pthread_mutex_destroy(mtx) && assert(0);
    }

    void lockMutex(pthread_mutex_t* mtx)
    {
        pthread_mutex_lock(mtx) && assert(0);
    }

    void unlockMutex(pthread_mutex_t* mtx)
    {
        pthread_mutex_unlock(mtx) && assert(0);
    }
}

struct Monitor
{
    IMonitor impl; // for user-level monitors
    DEvent[] devt; // for internal monitors
    size_t refs; // reference count
    Mutex mtx;
}

private:

__gshared Mutex gmtx;

@property ref shared(Monitor*) monitor(return scope Object h) pure nothrow @nogc
{
    return *cast(shared Monitor**)&h.__monitor;
}

shared(Monitor)* getMonitor(Object h) pure @nogc
{
    return atomicLoad!(MemoryOrder.acq)(h.monitor);
}

void setMonitor(Object h, shared(Monitor)* m) pure @nogc
{
    atomicStore!(MemoryOrder.rel)(h.monitor, m);
}

shared(Monitor)* ensureMonitor(Object h)
{
    if (auto m = getMonitor(h))
        return m;

    auto m = cast(Monitor*) calloc(Monitor.sizeof, 1);
    assert(m);
    initMutex(&m.mtx);

    bool success;
    lockMutex(&gmtx);
    if (getMonitor(h) is null)
    {
        m.refs = 1;
        setMonitor(h, cast(shared) m);
        success = true;
    }
    unlockMutex(&gmtx);

    if (success)
    {
        // Set the finalize bit so that the monitor gets collected (Bugzilla 14573)
        import core.memory : GC;

        if (!(typeid(h).m_flags & TypeInfo_Class.ClassFlags.hasDtor))
            GC.setAttr(cast(void*) h, GC.BlkAttr.FINALIZE);
        return cast(shared(Monitor)*) m;
    }
    else // another thread succeeded instead
    {
        deleteMonitor(m);
        return getMonitor(h);
    }
}

void deleteMonitor(Monitor* m) @nogc
{
    destroyMutex(&m.mtx);
    free(m);
}

void disposeEvent(Monitor* m, Object h)
{
    foreach (v; m.devt)
    {
        if (v)
            v(h);
    }
    if (m.devt.ptr)
        free(m.devt.ptr);
}

// Bugzilla 14573
unittest
{
    import core.memory : GC;

    auto obj = new Object;
    assert(!(GC.getAttr(cast(void*) obj) & GC.BlkAttr.FINALIZE));
    ensureMonitor(obj);
    assert(getMonitor(obj) !is null);
    assert(GC.getAttr(cast(void*) obj) & GC.BlkAttr.FINALIZE);
}
