core.sync.rwmutex example
Charles Hixson via Digitalmars-d-learn
digitalmars-d-learn at puremagic.com
Fri May 9 16:11:14 PDT 2014
On 05/09/2014 02:51 PM, Joshua Niehus via Digitalmars-d-learn wrote:
> Hi Charles,
>
> would the following work (just a shot in the dark) ?
>
> //---
> module test;
>
> import std.stdio;
> import std.concurrency;
>
> void spawnedFuncFoo(Tid tid, Tid tidBar) {
> receive(
> (int i) {
> writeln("Foo Received the number ", i);
> send(tidBar, i, thisTid);
> auto barSuccessful = receiveOnly!(string);
> writeln("Bar got my (Foo) message");
> }
> );
>
> send(tid, true);
> }
>
> void spawnedFuncBar(Tid tid) {
> receive(
> (int i, Tid tidFoo) {
> writeln("Foo passed me (Bar) the number ", i);
> send(tidFoo, "done");
> }
> );
>
> receive(
> (string sig) {
> writeln("Main says I'm (Bar) done.");
> send(tid, 42);
> }
> );
> }
>
> void main() {
> auto tidBar = spawn(&spawnedFuncBar, thisTid);
> auto tidFoo = spawn(&spawnedFuncFoo, thisTid, tidBar);
> send(tidFoo, 42);
> auto fooWasSuccessful = receiveOnly!(bool);
> assert(fooWasSuccessful);
>
> send(tidBar, "your done");
> auto barWasSuccessful = receiveOnly!(int);
> assert(barWasSuccessful == 42);
> writeln("Successfully had two separate threads communicate
> with each other");
> }
> //---
>
Thank you very much for the response.
How do you ensure that the received message (in "auto barWasSuccessful =
receiveOnly!(int); ") came from the thread sent to by tidFoo? Also, why
two receives in
spawnedFuncBar? I thought that receive handled multiple different
arguments with a single receive? Are you asserting that the arguments
happen in sequence, as it appears? That doesn't look as if it would
scale will to multiple threads. And with multiple threads I would
expect the mailbox to start getting very full with inappropriate
messages that never got handled, because they came at the wrong time
(and arguably from the wrong sender, as it seems that there is an
assumption that there is no intervening thread sending any messages).
That's why I was looking for a way to ensure that the message being
received came from the appropriate sender. You can't depend on messages
to always come from the source you expect. This probably means that you
need to have only ONE receive statement, located in a loop. And some
way to check and set the status of incoming messages. Also a yield
method that lets one receive and stack any incoming messages during a
busy cycle, though I think that that's what receive does.
OTOH, I do note that you are using "auto barWasSuccessful =
receiveOnly!(int);" which implies that the value returned is not a void,
even though you never use the result. This fits with the claims of
TDPL, but make me increasingly dubious about the documentation. Or do I
just not understand what a function of type void is supposed to return?
The hashtable itself will be a uint64_t[string] which is confined to one
thread, so the access methods need to be rather straightforwards. I'm
thinking of:
receive
( (string s, uint64_t id) { void set(s, id); }
(string s) { void get(s); }
(Variant v) { void reportError (v); }
);
get should send the id back to the calling thread. set updates the AA
and sends true or false (success) back to the calling thread. But
doesn't this design lock the entire hashtable while the update is in
progress? Is there a better way? set will be, approx:
void set (string s, uint64_t id)
{ tbl[s] = id;
send (tid, true);
}
etc. But I'm worried about the receiving end. It needs, somehow, to
ensure that the message it receives is the appropriate message, and that
other messages don't get dropped while it's waiting for the answer...or,
perhaps worse, substituted for the expected answer. If I can depend on
msg[0] of "auto msg = receiveOnly!(Tid, bool)" that will allow me to
check that the message was received from the proper source Also, if a
message is received that if of an inappropriate form, an exception is
thrown. Recovery looks problematic. But this is a case that should be
expected when different threads are sending messages. And if the
message is of the correct form, but from the wrong thread, how can one
re-queue it for later processing?
So far the best idea I've got is to have a dequeue of messages that are
stacked with "receiveOnly!Variant". But this would need to be accesses
in various places throughout the thread, and the handling looks messy.
OTOH, it does let me save messages that come in at the wrong time where
I can deal with them later. So it's not all bad. But it gives up on the
processing that receive makes available. And note that this processing
doesn't need to be done in the hashtable function, that's pretty clear,
but wherever it's used. Which is terrible. As it is, I might be better
putting the hashtable in s synchronized class. The entire hashtable is
getting locked on every read anyway.
-- Charles Hixson
More information about the Digitalmars-d-learn
mailing list