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