Skip to content

Commit 7ccd770

Browse files
committed
Use a semaphore based bounded queue as an example
1 parent 33ffdca commit 7ccd770

File tree

1 file changed

+32
-28
lines changed

1 file changed

+32
-28
lines changed

lib/picos_std.sync/picos_std_sync.mli

Lines changed: 32 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -758,7 +758,7 @@ end
758758
{2 A simple bounded queue}
759759
760760
Here is an example of a simple bounded (blocking) queue using a lock and
761-
condition variables:
761+
semaphores:
762762
763763
{[
764764
module Bounded_q : sig
@@ -771,44 +771,48 @@ end
771771
type 'a t = {
772772
lock : Lock.t;
773773
queue : 'a Queue.t;
774-
capacity : int;
775-
not_empty : Lock.Condition.t;
776-
not_full : Lock.Condition.t;
774+
capacity : Sem.t;
775+
length : Sem.t;
777776
}
778777
779778
let create ~capacity =
780779
if capacity < 0 then invalid_arg "negative capacity"
781780
else
782-
let lock = Lock.create ()
781+
let lock = Lock.create ~padded:true ()
783782
and queue = Queue.create ()
784-
and not_empty = Lock.Condition.create ()
785-
and not_full = Lock.Condition.create () in
786-
{ lock; queue; capacity; not_empty; not_full }
783+
and capacity = Sem.create ~padded:true capacity
784+
and length = Sem.create ~padded:true 0 in
785+
{ lock; queue; capacity; length }
787786
788-
let is_full_unsafe t = t.capacity <= Queue.length t.queue
787+
let is_empty t =
788+
Lock.acquire t.lock;
789+
let result = Queue.is_empty t.queue in
790+
Lock.release t.lock;
791+
result
792+
793+
let release_and_reraise s exn =
794+
let bt = Printexc.get_raw_backtrace () in
795+
Sem.release s;
796+
Printexc.raise_with_backtrace exn bt
789797
790798
let push t x =
791-
let was_empty =
792-
Lock.protect t.lock @@ fun () ->
793-
while is_full_unsafe t do
794-
Lock.Condition.wait t.not_full t.lock
795-
done;
796-
Queue.push x t.queue;
797-
Queue.length t.queue = 1
798-
in
799-
if was_empty then Lock.Condition.broadcast t.not_empty
799+
Sem.acquire t.capacity;
800+
match Lock.acquire t.lock with
801+
| () ->
802+
Queue.push x t.queue;
803+
Lock.release t.lock;
804+
Sem.release t.length
805+
| exception exn -> release_and_reraise t.capacity exn
800806
801807
let pop t =
802-
let elem, was_full =
803-
Lock.protect t.lock @@ fun () ->
804-
while Queue.length t.queue = 0 do
805-
Lock.Condition.wait t.not_empty t.lock
806-
done;
807-
let was_full = is_full_unsafe t in
808-
(Queue.pop t.queue, was_full)
809-
in
810-
if was_full then Lock.Condition.broadcast t.not_full;
811-
elem
808+
Sem.acquire t.length;
809+
match Lock.acquire t.lock with
810+
| () ->
811+
let elem = Queue.pop t.queue in
812+
Lock.release t.lock;
813+
Sem.release t.capacity;
814+
elem
815+
| exception exn -> release_and_reraise t.length exn
812816
end
813817
]}
814818

0 commit comments

Comments
 (0)