Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add useful warnings. #170

Merged
merged 4 commits into from
Dec 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions src/bounded_queue/bounded_queue_intf.mli
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ module type BOUNDED_QUEUE = sig
(** [of_list_exn ~capacity list] creates a new queue from a list.

@raises Full if the length of [list] is greater than [capacity].

🐌 This is a linear-time operation.

{[
# open Saturn.Bounded_queue
Expand Down Expand Up @@ -107,7 +109,9 @@ module type BOUNDED_QUEUE = sig
queue is full. *)
end

(** {1 Examples}
(** {1 Examples} *)

(** {2 Sequential example}
An example top-level session:
{[
# open Saturn.Bounded_queue
Expand Down Expand Up @@ -135,9 +139,16 @@ end
- : int option = None
# pop_exn t
Exception: Saturn__Bounded_queue.Empty.]}
*)

(** {2 Multicore example}

Note: The barrier is used in this example solely to make the results more
interesting by increasing the likelihood of parallelism. Spawning a domain is
a costly operation, especially compared to the relatively small amount of work
being performed here. In practice, using a barrier in this manner is unnecessary.

A multicore example:
{@ocaml non-deterministic[
{@ocaml non-deterministic=command[
# open Saturn.Bounded_queue
# let t :int t = create ~capacity:4 ()
val t : int t = <abstr>
Expand Down
42 changes: 32 additions & 10 deletions src/bounded_stack.mli
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ val of_list_exn : ?capacity:int -> 'a list -> 'a t

@raises Full if the [list] is longer than the capacity of the stack.

🐌 This is a linear-time operation.
{[
# open Saturn.Bounded_stack
# let t : int t = of_list_exn [1;2;3;4]
Expand Down Expand Up @@ -106,18 +107,23 @@ val push_exn : 'a t -> 'a -> unit
val try_push : 'a t -> 'a -> bool
(** [try_push stack element] tries to add [element] to the top of the [stack].
Returns [true] if the element was successfully added, or [false] if the
stack is full. *)
stack is full.
*)

val push_all_exn : 'a t -> 'a list -> unit
(** [push_all_exn stack elements] adds all [elements] to the top of the [stack].

@raises Full if the [stack] is full. *)
@raises Full if the [stack] is full.

🐌 This is a linear-time operation on the size of [elements]. *)

val try_push_all : 'a t -> 'a list -> bool
(** [try_push_all stack elements] tries to add all [elements] to the top of the
[stack]. Returns [true] if the elements were successfully added, or [false] if
the stack is full.

🐌 This is a linear-time operation on the size of [elements].

{[
# let t : int t = create ()
val t : int t = <abstr>
Expand All @@ -142,21 +148,29 @@ bottom.
val of_seq : ?capacity:int -> 'a Seq.t -> 'a t
(** [of_seq seq] creates a stack from a [seq]. It must be finite.

@raises Full if the [list] is longer than the capacity of the stack.
@raises Full if the [seq] is longer than the capacity of the stack.

🐌 This is a linear-time operation.
*)

val add_seq_exn : 'a t -> 'a Seq.t -> unit
(** [add_seq_exn stack seq] adds all elements of [seq] to the top of the
[stack]. [seq] must be finite.

@raises Full if the [seq] is too long to fit in the stack. *)
@raises Full if the [seq] is too long to fit in the stack.

🐌 This is a linear-time operation on the size of [seq]. *)

val try_add_seq : 'a t -> 'a Seq.t -> bool
(** [try_add_seq stack seq] tries to add all elements of [seq] to the top of the
[stack]. Returns [true] if the elements were successfully added, or [false] if
the [seq] is too long to fit in the stack. *)
the [seq] is too long to fit in the stack.

🐌 This is a linear-time operation. *)

(** {1 Examples} *)

(** {1 Examples}
(** {2 Sequential example}
An example top-level session:
{[
# open Saturn.Bounded_stack
Expand All @@ -176,27 +190,36 @@ the [seq] is too long to fit in the stack. *)
- : int option = None
# pop_exn t
Exception: Saturn__Bounded_stack.Empty.]}
*)

(** {2 Multicore example}
Note: The barrier is used in this example solely to make the results more
interesting by increasing the likelihood of parallelism. Spawning a domain is
a costly operation, especially compared to the relatively small amount of work
being performed here. In practice, using a barrier in this manner is unnecessary.

A multicore example:
{@ocaml non-deterministic[

{@ocaml non-deterministic=command[
# open Saturn.Bounded_stack
# let t :int t = create ()
val t : int t = <abstr>
# let barrier = Atomic.make 2
val barrier : int Atomic.t = <abstr>

# let pusher () =
Atomic.decr barrier;
while Atomic.get barrier != 0 do Domain.cpu_relax () done;

try_push_all t [1;2;3] |> ignore;
push_exn t 42;
push_exn t 12
val pusher : unit -> unit = <fun>

# let popper () =
Atomic.decr barrier;
while Atomic.get barrier != 0 do Domain.cpu_relax () done;
List.init 6 (fun i -> Domain.cpu_relax (); pop_opt t)
val popper : unit -> int option list = <fun>

# let domain_pusher = Domain.spawn pusher
val domain_pusher : unit Domain.t = <abstr>
# let domain_popper = Domain.spawn popper
Expand All @@ -206,5 +229,4 @@ the [seq] is too long to fit in the stack. *)
# Domain.join domain_popper
- : int option list = [Some 42; Some 3; Some 2; Some 1; None; Some 12]
]}

*)
28 changes: 22 additions & 6 deletions src/treiber_stack.mli
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ val push : 'a t -> 'a -> unit
val push_all : 'a t -> 'a list -> unit
(** [push_all stack elements] adds all [elements] to the top of the [stack].

🐌 This is a linear-time operation on the size of [elements].

{[
# let t : int t = create ()
val t : int t = <abstr>
Expand All @@ -96,13 +98,19 @@ bottom.
🐌 This is a linear time operation. *)

val of_seq : 'a Seq.t -> 'a t
(** [of_seq seq] creates a stack from a [seq]. It must be finite. *)
(** [of_seq seq] creates a stack from a [seq]. It must be finite.

🐌 This is a linear-time operation. *)

val add_seq : 'a t -> 'a Seq.t -> unit
(** [add_seq stack seq] adds all elements of [seq] to the top of the
[stack]. [seq] must be finite. *)
[stack]. [seq] must be finite.

🐌 This is a linear-time operation on the size of [elements]. *)

(** {1 Examples}
(** {1 Examples} *)

(** {2 Sequential example}
An example top-level session:
{[
# open Saturn.Stack
Expand All @@ -120,26 +128,35 @@ val add_seq : 'a t -> 'a Seq.t -> unit
- : int list = [2; 1; 42]
# pop_exn t
Exception: Saturn__Treiber_stack.Empty.]}
*)

A multicore example:
{@ocaml non-deterministic[
(** {2 Multicore example}
Note: The barrier is used in this example solely to make the results more
interesting by increasing the likelihood of parallelism. Spawning a domain is
a costly operation, especially compared to the relatively small amount of work
being performed here. In practice, using a barrier in this manner is unnecessary.

{@ocaml non-deterministic=command[
# open Saturn.Stack
# let t : int t = create ()
val t : int t = <abstr>
# let barrier = Atomic.make 2
val barrier : int Atomic.t = <abstr>

# let pusher () =
Atomic.decr barrier;
while Atomic.get barrier != 0 do Domain.cpu_relax () done;
push_all t [1;2;3] |> ignore;
push t 42;
push t 12
val pusher : unit -> unit = <fun>

# let popper () =
Atomic.decr barrier;
while Atomic.get barrier != 0 do Domain.cpu_relax () done;
List.init 6 (fun i -> Domain.cpu_relax (); pop_opt t)
val popper : unit -> int option list = <fun>

# let domain_pusher = Domain.spawn pusher
val domain_pusher : unit Domain.t = <abstr>
# let domain_popper = Domain.spawn popper
Expand All @@ -149,5 +166,4 @@ val add_seq : 'a t -> 'a Seq.t -> unit
# Domain.join domain_popper
- : int option list = [Some 42; Some 3; Some 2; Some 1; None; Some 12]
]}

*)