mirror of
https://github.com/logos-storage/nim-datastore.git
synced 2026-01-02 21:53:05 +00:00
59 lines
1.3 KiB
Nim
59 lines
1.3 KiB
Nim
import std/atomics
|
|
import std/locks
|
|
|
|
type
|
|
Semaphore* = object
|
|
count: int
|
|
size: int
|
|
lock {.align: 64.}: Lock
|
|
cond: Cond
|
|
|
|
func `=`*(dst: var Semaphore, src: Semaphore) {.error: "A semaphore cannot be copied".}
|
|
func `=sink`*(dst: var Semaphore, src: Semaphore) {.error: "An semaphore cannot be moved".}
|
|
|
|
proc init*(_: type Semaphore, count: uint): Semaphore =
|
|
var
|
|
lock: Lock
|
|
cond: Cond
|
|
|
|
lock.initLock()
|
|
cond.initCond()
|
|
|
|
Semaphore(count: count.int, size: count.int, lock: lock, cond: cond)
|
|
|
|
proc `=destroy`*(self: var Semaphore) =
|
|
self.lock.deinitLock()
|
|
self.cond.deinitCond()
|
|
|
|
proc count*(self: var Semaphore): int =
|
|
self.count
|
|
|
|
proc size*(self: var Semaphore): int =
|
|
self.size
|
|
|
|
proc acquire*(self: var Semaphore) {.inline.} =
|
|
self.lock.acquire()
|
|
while self.count <= 0:
|
|
self.cond.wait(self.lock)
|
|
|
|
self.count -= 1
|
|
self.lock.release()
|
|
|
|
proc release*(self: var Semaphore) {.inline.} =
|
|
self.lock.acquire()
|
|
if self.count <= 0:
|
|
self.count += 1
|
|
self.cond.signal()
|
|
|
|
doAssert not (self.count > self.size),
|
|
"Semaphore count is greather than size: " & $self.size & " count is: " & $self.count
|
|
|
|
self.lock.release()
|
|
|
|
template withSemaphore*(self: var Semaphore, body: untyped) =
|
|
self.acquire()
|
|
try:
|
|
body
|
|
finally:
|
|
self.release()
|