-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathroony.nim
50 lines (44 loc) · 1.7 KB
/
roony.nim
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import roony/spec
import roony/ring
type
RoonyQueue*[T; N: static uint] = ref object
## Bounded circular queue which uses indirection to store and access values
aqo: RingQueue[N]
fqo: RingQueue[N]
val: array[N, T]
proc newRoonyQueue*[T](): auto =
## Create and initialise a RoonyQueue.
const sz = 1u shl (rqOrder + 1)
result =
RoonyQueue[T, sz](
aqo: newEmptyRingQueue(),
fqo: newFullRingQueue()
)
# ----------------------------------------- #
# Accessors to internal ring queues as vars #
proc fq[T; N](sq: RoonyQueue[T, N]): var RingQueue[N] = sq.fqo
proc aq[T; N](sq: RoonyQueue[T, N]): var RingQueue[N] = sq.aqo
# ----------------------------------------- #
proc push*[T; N](sq: RoonyQueue[T, N]; val: T): bool {.discardable.} =
## Push an item (val) onto the queue. False is returned if the queue is full.
var eidx = sq.fq().pop(true)
if eidx == high(uint):
result = false
else:
sq.val[eidx] = val
sq.aq().push(eidx, false)
result = true
proc pop*[T; N](sq: RoonyQueue[T, N], clear: static bool = false): T =
## Pop an item off the queue. Nil is returned if the queue is empty and must be
## handled in user code.
## By default, there is no reason for the item to be cleared from the slot
## since the queue uses indirection to give access to slots and their items.
## However, this must be forced when the object is a ref so that the ref count
## is *more* correct (requires atomic ref count to be truly correct). Users
## can also force this by setting the arg 'clear' to true.
var eidx = sq.aq().pop(false)
if eidx != high(uint):
result = sq.val[eidx]
when clear or T is ref:
sq.val[eidx] = nil
sq.fq().push(eidx, true)