Open Search
    Locks & Synchronization Manual

    About

    Locks are used to guard access to resources that are shared across multiple threads.

    Note
    Locks should be used to avoid crashes when seldom used resources are accessed and to protect single threaded operations. Locks should not be used to fix problems of ill-designed code.
    Warning
    Make sure that a thread releases a lock after it has finished or a deadlock will be the result.

    Spinlock

    maxon::Spinlock implements a mutex that will loop on a pause/idle instruction when it is already locked.

    // This example shows how a global spin lock is used to protect the access to a global function.
    static maxon::Result<void> UpdateWithSpinlock()
    {
    // example global instance; typically a member variable would be used
    static maxon::Spinlock g_spinlock;
    // lock
    g_spinlock.Lock();
    // handle shared resource
    const maxon::Result<void> res = UpdateGlobalData();
    // unlock
    g_spinlock.Unlock();
    return res;
    }
    Py_UCS4 * res
    Definition: unicodeobject.h:1113
    Definition: spinlock.h:59
    void Lock()
    Definition: spinlock.h:86
    void Unlock()
    Definition: spinlock.h:97

    ScopedLock

    A maxon::ScopedLock acquires a lock when created and releases upon destruction (at the end of the scope).

    Warning
    ScopedLock should only be used for a short block of code. It will block all other threads.
    // This example uses a maxon::ScopedLock to protect access to a global function.
    static maxon::Result<void> UpdateWithScopedLock(maxon::Spinlock& lock)
    {
    // lock on creation
    maxon::ScopedLock scopedLock(lock);
    // handle shared resource
    return UpdateGlobalData();
    }
    Definition: spinlock.h:255
    #define iferr_scope
    Definition: resultbase.h:1389

    RWSpinlock

    The maxon::RWSpinlock allows access for multiple readers and only one exclusive writer.

    // This example shows how a global RW spin lock is used to protect the access to global functions.
    // example global instance; typically a member variable would be used
    static maxon::RWSpinlock g_rwSpinlock;
    static maxon::Result<void> UpdateWithRWLock()
    {
    // write lock
    g_rwSpinlock.WriteLock();
    // handle shared resource
    const maxon::Result<void> res = UpdateGlobalData();
    // write unlock
    g_rwSpinlock.WriteUnlock();
    return res;
    }
    static maxon::Int ReadWithRWLock(maxon::Int i)
    {
    // read lock
    g_rwSpinlock.ReadLock();
    // access shared resource
    const maxon::Int res = AccessData(i);
    // read unlock
    g_rwSpinlock.ReadUnlock();
    return res;
    }
    Py_ssize_t i
    Definition: abstract.h:645
    Int64 Int
    signed 32/64 bit int, size depends on the platform
    Definition: apibase.h:213
    Definition: spinlock.h:186

    ARWLock

    The maxon::ARWLock is an asymmetric read write lock which prefers the readers.

    // This example shows how a global asymmetric read write lock is used to protect the access to a global function.
    // example global instance; typically a member variable would be used
    static maxon::ARWLock* g_arwlock = nullptr;
    static maxon::Result<void> Init()
    {
    return maxon::OK;
    }
    static void Clear()
    {
    DeleteObj(g_arwlock);
    }
    MAXON_INITIALIZATION(Init, Clear);
    static maxon::Result<void> UpdateWithARWLock()
    {
    g_arwlock->WriteLock();
    const maxon::Result<void> res = UpdateGlobalData();
    g_arwlock->WriteUnlock();
    return res;
    }
    Definition: arwlock.h:28
    void WriteLock()
    Definition: arwlock.h:69
    void WriteUnlock()
    Definition: arwlock.h:79
    return OK
    Definition: apibase.h:2746
    #define MAXON_INITIALIZATION(...)
    Definition: module.h:879
    #define DeleteObj(obj)
    Definition: newobj.h:159
    #define NewObj(T,...)
    Definition: newobj.h:108
    #define iferr_return
    Definition: resultbase.h:1524

    Synchronized

    The maxon::Synchronized template is used to guarantee safe access to a given variable. It allows access to the variable only after a lock has been acquired. For asymmetric read-write access there is also maxon::RWSynchronized based on maxon::ARWLock.

    // This example shows an example class that uses
    // maxon::Synchronized to lock access to a member variable.
    class SimpleStringClass
    {
    public:
    // return stored String
    maxon::String GetString() const
    {
    return *_string.Read();
    }
    // add to stored String
    maxon::Result<void> AddString(const maxon::String& string)
    {
    return _string.Write()->Append(string);
    }
    // adds multiple strings to the stored String
    {
    // get locked pointer to get write access
    auto lockedPtr = _string.Write();
    for (maxon::String& str : strings)
    {
    lockedPtr->Append(str) iferr_return;
    }
    // lock on _string is released when the function scope is left
    return maxon::OK;
    }
    private:
    };
    Definition: string.h:1235
    Definition: synchronized.h:48
    void * str
    Definition: bytesobject.h:77

    Serializer

    The maxon::Serializer guarantees mutually exclusive access to a shared resource. The given lambdas are enqueued and executed.

    Note
    maxon::Serializer is low level and does not support error handling.
    // This example uses the given Serializer to manage access to a shared resource.
    g_serializer.EnqueueAndWait([]()
    {
    iferr (UpdateGlobalData())
    {
    DiagnosticOutput("Error in UpdateGlobalData()");
    }
    });
    #define DiagnosticOutput(formatString,...)
    Definition: debugdiagnostics.h:170
    #define iferr(...)
    Definition: errorbase.h:388

    Further Reading