* [Caml-list] semaphore puzzle
@ 2013-09-30 18:30 Matej Kosik
2013-10-01 11:30 ` Gerd Stolpmann
0 siblings, 1 reply; 2+ messages in thread
From: Matej Kosik @ 2013-09-30 18:30 UTC (permalink / raw)
To: caml-list
[-- Attachment #1: Type: text/plain, Size: 1000 bytes --]
Hi,
I am trying to find the most simple and, if possible, clean way to synchronize my threads.
In this particular case, semaphores would be ideal
(alternatively, unbounded channels)
(* Create a new semaphore with a given initial value. *)
val create : int -> t
(* V *)
val up : t -> unit
(* P *)
val down : t -> unit
val try_down : t -> bool
The "down" or "try_down" are almost the solutions, but not quite.
"down" may block forever ---> there is no timeout at all
(I need some)
"try_down" ---> the timeout is zero
(I prefer a non-zero timeout)
Obviously, I could use "try_down" in a loop, checking the system time myself and then either give up or actually manage to decrement the semaphore.
Is there a better solution than this?
(There is a Unix module, there are signals, but I am not sure whether it is safe to use them in multithreaded program.
At least, I did not have a luck.)
Thanks in advance for patience &| help.
[-- Attachment #2: semaphore.ml --]
[-- Type: text/plain, Size: 1075 bytes --]
exception Timeout
type t = {mutex : Mutex.t;
condition_lock : Condition.t;
mutable value : int}
let create initial_value =
assert (0 <= initial_value);
{mutex = Mutex.create ();
condition_lock = Condition.create ();
value = initial_value}
let up semaphore =
Mutex.lock semaphore.mutex;
semaphore.value <- succ semaphore.value;
Mutex.unlock semaphore.mutex;
Condition.signal semaphore.condition_lock
let down semaphore =
Mutex.lock semaphore.mutex;
assert (0 <= semaphore.value);
while semaphore.value = 0 do
Condition.wait semaphore.condition_lock semaphore.mutex
done;
semaphore.value <- pred semaphore.value;
Mutex.unlock semaphore.mutex
(* If it is possible to decrement the semaphore, do it and return "true".
Otherwise return "false". *)
let try_down semaphore =
Mutex.lock semaphore.mutex;
if 0 < semaphore.value then
begin
semaphore.value <- pred semaphore.value;
Mutex.unlock semaphore.mutex;
true
end
else
begin
Mutex.unlock semaphore.mutex;
false
end
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [Caml-list] semaphore puzzle
2013-09-30 18:30 [Caml-list] semaphore puzzle Matej Kosik
@ 2013-10-01 11:30 ` Gerd Stolpmann
0 siblings, 0 replies; 2+ messages in thread
From: Gerd Stolpmann @ 2013-10-01 11:30 UTC (permalink / raw)
To: Matej Kosik; +Cc: caml-list
[-- Attachment #1: Type: text/plain, Size: 2797 bytes --]
Hi,
Ocamlnet includes support for semaphores (at least for Unix platforms).
Am Montag, den 30.09.2013, 19:30 +0100 schrieb Matej Kosik:
> Hi,
>
> I am trying to find the most simple and, if possible, clean way to synchronize my threads.
>
> In this particular case, semaphores would be ideal
> (alternatively, unbounded channels)
>
> (* Create a new semaphore with a given initial value. *)
> val create : int -> t
Netsys_posix.sem_create (or sem_open or sem_init).
>
> (* V *)
> val up : t -> unit
Netsys_posix.sem_post
> (* P *)
> val down : t -> unit
Netsys_posix.sem_wait with option SEM_WAIT_BLOCK.
> val try_down : t -> bool
Netsys_posix.sem_wait with option SEM_WAIT_NONBLOCK.
> The "down" or "try_down" are almost the solutions, but not quite.
>
> "down" may block forever ---> there is no timeout at all
> (I need some)
>
> "try_down" ---> the timeout is zero
> (I prefer a non-zero timeout)
>
> Obviously, I could use "try_down" in a loop, checking the system time myself and then either give up or actually manage to decrement the semaphore.
>
> Is there a better solution than this?
The POSIX API specifies sem_timedwait, but I haven't included it in my
bindings, as it is optional in POSIX. What you could do as workaround is
to start a helper thread which will sem_post after the timeout. I admit
that it is difficult to find a clean solution here without race
conditions.
> (There is a Unix module, there are signals, but I am not sure whether it is safe to use them in multithreaded program.
> At least, I did not have a luck.)
The signal handling as provided by Unix (or better by the OCaml runtime)
is not sufficient for this kind of programming.
An alternative might be to use a pipe as returned by Unix.pipe. The
number of bytes in the pipe buffer is the semaphore counter:
post = add a byte to the buffer
wait = read a byte from the buffer
You can use Unix.select to specify a timeout when waiting. The solution
works as long as the pipe buffer doesn't fill up (at least 4096 bytes
are guaranteed). You can totally avoid that if you combine the pipe with
an additional counter (i.e. semaphore counter = pipe buffer + additional
counter), and you use the pipe only when the additional counter is 0.
Gerd
>
> Thanks in advance for patience &| help.
>
--
------------------------------------------------------------
Gerd Stolpmann, Darmstadt, Germany gerd@gerd-stolpmann.de
My OCaml site: http://www.camlcity.org
Contact details: http://www.camlcity.org/contact.html
Company homepage: http://www.gerd-stolpmann.de
------------------------------------------------------------
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 490 bytes --]
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2013-10-01 11:30 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-09-30 18:30 [Caml-list] semaphore puzzle Matej Kosik
2013-10-01 11:30 ` Gerd Stolpmann
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox