From: Goswin von Brederlow <goswin-v-b@web.de>
To: caml-list@yquem.inria.fr
Subject: Re: [Caml-list] Smart ways to implement worker threads
Date: Sat, 17 Jul 2010 11:52:31 +0200 [thread overview]
Message-ID: <87hbjy77vk.fsf@frosties.localdomain> (raw)
In-Reply-To: <87sk3mcaeq.fsf@frosties.localdomain> (Goswin von Brederlow's message of "Wed, 14 Jul 2010 18:09:49 +0200")
Hi,
so I've been thinking and testing some possibilities.
It is now clear that I need 2 queues. One queue for jobs the worker
threads are to do and one queue for results from the worker threads.
The queue for the worker thread seems easy. Combine a Queue.t, Mutex.t
and Condition.t:
type 'a t = {
data : 'a Queue.t;
mutex : Mutext.t;
condition : Condition.t;
}
let take q =
Mutex.lock q.mutex;
while Queue.is_empty q.data do
Condition.wait q.condition q.mutex
done;
let d = Queue.take q.data
in
Mutex.unlock q.mutex;
d
let add q d =
Mutex.lock q.mutex;
Queue.add q.data d;
Condition.signal q.condition;
Mutex.unlock q.mutex
and so on. The standard mechanism for a thread safe queue used in most
languages.
Now I have been thinking about the other queue, for reporting the
results from the worker thread. The thing is that the main thread is
stuck in a select waiting for new requests to come in or for the send
buffer to clear so it can send out more replies (or more of a large
reply). So wouldn't it be nice if I could use select on a queue?
Well, in Linux there is the eventfd() system call.
So instead of using Condition.t to signal something was put into the
queue I use the eventfd.
type 'a t = {
data : 'a Queue.t;
mutex : Mutext.t;
fd : EventFD.t;
}
let take q =
let num = EventFD.read q.fd
in
Mutex.lock q.mutex;
let res = Queue.take q.data
in
Mutex.unlock q.mutex;
(* We only take one element, restore counter *)
EventFD.write q.fd (Int64.pred num);
res
let take_all q =
let num = EventFD.read q.fd in
let rec loop acc = function
0 -> List.rev acc
| n -> loop ((Queue.take q.data) :: acc) (n - 1)
in
Mutex.lock q.mutex;
let res = loop num
in
Mutex.unlock q.mutex;
res
let process q f =
let num = EventFD.read q.fd in
let rec loop = function
0 -> ()
| n ->
Mutex.lock q.mutex;
let res = Queue.take q.data
in
Mutex.unlock q.mutex;
f res;
loop (n - 1)
in
loop num
let add q d =
Mutex.lock q.mutex;
Queue.add q.data d;
EventFD.write q.fd 1;
Mutex.unlock q.mutex;
Now I have a queue that I can include in select. The take function can
be used by the worker threads. The main thread can use either take_all
or process to save on syscalls or stick with take to ensure the queue
does not starve the other FDs.
Also I think I can use the EventFD to terminate a queue and wake up all
listeners. Closing the EventFD should wake up any thread stuck in read
and prevent any threads from becoming stuck in the future. Haven't
tested that yet though.
MfG
Goswin
next prev parent reply other threads:[~2010-07-17 9:52 UTC|newest]
Thread overview: 31+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-07-14 16:09 Goswin von Brederlow
2010-07-15 15:58 ` [Caml-list] " Rich Neswold
2010-07-15 16:19 ` David McClain
2010-07-15 17:16 ` Ashish Agarwal
2010-07-15 18:24 ` Goswin von Brederlow
2010-07-15 18:37 ` David McClain
2010-07-15 18:40 ` David McClain
2010-07-15 19:56 ` Rich Neswold
2010-07-16 4:02 ` Goswin von Brederlow
2010-07-16 4:23 ` Rich Neswold
2010-07-16 13:02 ` Goswin von Brederlow
2010-07-16 14:40 ` Dawid Toton
2010-07-16 16:18 ` [Caml-list] " Rich Neswold
2010-07-17 17:53 ` Eray Ozkural
2010-07-20 4:54 ` Satoshi Ogasawara
2010-07-17 18:34 ` Eray Ozkural
2010-07-17 19:35 ` Goswin von Brederlow
2010-07-17 22:00 ` Eray Ozkural
2010-07-15 16:32 ` Romain Beauxis
2010-07-15 17:46 ` Goswin von Brederlow
2010-07-15 18:44 ` Romain Beauxis
2010-07-16 3:52 ` Goswin von Brederlow
2010-07-16 4:19 ` Romain Beauxis
2010-07-16 13:05 ` Goswin von Brederlow
2010-07-16 13:20 ` Romain Beauxis
2010-07-17 9:07 ` Goswin von Brederlow
2010-07-17 13:51 ` Romain Beauxis
2010-07-17 14:08 ` Goswin von Brederlow
2010-07-17 9:52 ` Goswin von Brederlow [this message]
2010-07-17 14:20 ` Romain Beauxis
2010-07-17 15:52 ` Goswin von Brederlow
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87hbjy77vk.fsf@frosties.localdomain \
--to=goswin-v-b@web.de \
--cc=caml-list@yquem.inria.fr \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox