diff --git a/lib/core/rlocks.nim b/lib/core/rlocks.nim new file mode 100644 index 000000000..3316ffcd4 --- /dev/null +++ b/lib/core/rlocks.nim @@ -0,0 +1,50 @@ +# +# +# Nim's Runtime Library +# (c) Copyright 2015 Andreas Rumpf +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +## This module contains Nim's support for reentrant locks + +include "system/syslocks" + +type + RLock* = SysLock ## Nim lock, re-entrant + +proc initRLock*(lock: var RLock) {.inline.} = + ## Initializes the given lock. + when defined(posix): + var a: SysLockAttr + initSysLockAttr(a) + setSysLockType(a, SysLockType_Reentrant()) + initSysLock(lock, a.addr) + else: + initSysLock(lock) + +proc deinitRLock*(lock: var RLock) {.inline.} = + ## Frees the resources associated with the lock. + deinitSys(lock) + +proc tryAcquire*(lock: var RLock): bool = + ## Tries to acquire the given lock. Returns `true` on success. + result = tryAcquireSys(lock) + +proc acquire*(lock: var RLock) = + ## Acquires the given lock. + acquireSys(lock) + +proc release*(lock: var RLock) = + ## Releases the given lock. + releaseSys(lock) + +template withRLock*(lock: var RLock, code: stmt): stmt = + ## Acquires the given lock and then executes the code + block: + acquire(lock) + defer: + release(lock) + {.locks: [lock].}: + code diff --git a/lib/system/syslocks.nim b/lib/system/syslocks.nim index 7a113b9d4..907a6c609 100644 --- a/lib/system/syslocks.nim +++ b/lib/system/syslocks.nim @@ -75,12 +75,24 @@ else: type SysLock {.importc: "pthread_mutex_t", pure, final, header: "".} = object + SysLockAttr {.importc: "pthread_mutexattr_t", pure, final + header: "".} = object SysCond {.importc: "pthread_cond_t", pure, final, header: "".} = object + SysLockType = distinct cint - proc initSysLock(L: var SysLock, attr: pointer = nil) {. + proc SysLockType_Reentrant: SysLockType = + {.emit: "`result` = PTHREAD_MUTEX_RECURSIVE;".} + + proc initSysLock(L: var SysLock, attr: ptr SysLockAttr = nil) {. importc: "pthread_mutex_init", header: "", noSideEffect.} + proc initSysLockAttr(a: var SysLockAttr) {. + importc: "pthread_mutexattr_init", header: "", noSideEffect.} + + proc setSysLockType(a: var SysLockAttr, t: SysLockType) {. + importc: "pthread_mutexattr_settype", header: "", noSideEffect.} + proc acquireSys(L: var SysLock) {.noSideEffect, importc: "pthread_mutex_lock", header: "".} proc tryAcquireSysAux(L: var SysLock): cint {.noSideEffect,