Skip to content

Commit

Permalink
blocking queue
Browse files Browse the repository at this point in the history
  • Loading branch information
Robbert van Renesse committed Nov 23, 2023
1 parent dd88878 commit 24877b5
Showing 1 changed file with 110 additions and 0 deletions.
110 changes: 110 additions & 0 deletions code/bqueueconc.hny
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import list
from alloc import malloc, free

def atomic_load(p):
atomically result = !p

def atomic_store(p, v):
atomically !p = v

def tas(lk):
atomically:
result = !lk
!lk = True

def cas(p, old, new):
atomically:
result = !p == old
if result:
!p = new

def BinSema(initial):
result = { .acquired: initial, .suspended: [] }

def Lock():
result = BinSema(False)

def acquire(binsema):
atomically:
if binsema->acquired:
stop ?binsema->suspended[len binsema->suspended]
assert binsema->acquired
else:
binsema->acquired = True

def release(binsema):
atomically:
assert binsema->acquired
if binsema->suspended == []:
binsema->acquired = False
else:
go (binsema->suspended[0]) ()
del binsema->suspended[0]

def held(binsema):
result = binsema->acquired

def Condition():
result = []

def wait(c, lk):
atomically:
release(lk)
stop ?(!c)[len !c]
acquire(lk)

def notify(c):
atomically if !c != []:
go (list.head(!c)) ()
!c = list.tail(!c)

def notifyAll(c):
atomically:
while !c != []:
go (list.head(!c)) ()
!c = list.tail(!c)

def Semaphore(cnt):
result = { .count: cnt, .waiters: [] }

def P(sema):
atomically:
if sema->count > 0:
sema->count -= 1
else:
stop ?sema->waiters[len sema->waiters]

def V(sema):
atomically let cnt, waiters = sema->count, sema->waiters:
if waiters != []:
assert cnt == 0
go (waiters[0]) ()
sema->waiters = list.tail(waiters)
else:
sema->count = cnt + 1

def Queue() returns empty:
empty = { .head: None, .tail: None, .lock: Lock(), .cv: Condition() }

def put(q, v):
let node = malloc({ .value: v, .next: None }):
acquire(?q->lock)
if q->tail == None:
q->tail = q->head = node
else:
q->tail->next = node
q->tail = node
notify(?q->cv)
release(?q->lock)

def get(q) returns next:
acquire(?q->lock)
while q->head == None:
wait(?q->cv, ?q->lock)
let node = q->head:
next = node->value
q->head = node->next
if q->head == None:
q->tail = None
free(node)
release(?q->lock)

0 comments on commit 24877b5

Please sign in to comment.