core.sync.rwmutex example

Charles Hixson via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Mon May 12 11:01:37 PDT 2014


On 05/10/2014 06:28 PM, TheFlyingFiddle via Digitalmars-d-learn wrote:
> On Friday, 9 May 2014 at 23:12:44 UTC, Charles Hixson via 
> Digitalmars-d-learn wrote:
>
>> 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
>
> If you are worried that other messages having the same signature will 
> be sent from other sources than the expected source you could make use 
> of message tagging. Simply wrap the boolean result in a struct with a 
> descriptive name.
>
> struct SharedHashMapSetCB { bool flag; }
> void set (string s, uint64_t id)
> {
>    tbl[s] = id;
>    send (SharedHashMapSetCB(true));
> }
>
> //On the receiving end
> auto msg = receiveOnly!SharedHashMapSetCB();
>
>> But doesn't this design lock the entire hash-table while the update 
>> is in progress?  Is there a better way?
> I think a shared memory hash-map is better for your use case. Working 
> with message passing is preferable done asynchronously. Blocking calls 
> (send followed by receive) is likely to be slower then simply waiting 
> on a semaphore.
I think you're probably right.  It should be a fairly fast lookup 
anyway, and since there should be only one copy of the table, I don't 
think one would get much of a speedup no matter what one did. OTOH, it 
can't be directly shared.  What can be shared is a handle to a singleton 
synchronized class.  Its requirement that it can be updated, IIUC, means 
that it can't be directly shared.

OTOH... I think I may need to build a mailbox class, the design I'm not 
yet sure about, that acts as an interface between the major number of 
threads and each other.  Access to it needs to be non-blocking 
(essentially) so it had probably better ONLY act as a message 
switchboard.  I want it to pass messages with "time" and "origin" 
(thread id) prefixed to them.  OTOH, I probably only need to support a 
small number of message formats, perhaps two, perhaps three.  And it 
would be more efficient if whenever a thread polled it, it responded 
with all waiting mail for that destination.  So it's only sending in 
response to a received message directed at it, but it holds all messages 
directed at some other thread.  This allows the other threads to loop 
through their processing, only occasionally pausing to check whether 
they have any mail or not. I'm hoping a couple of ms will be a long 
enough timeout.  The mailbox could spend most of it's time sitting 
blocked at receive.

This isn't the design I was thinking about earlier, but it seems better, 
and it's the design I originally ended up with the last time I thought 
about this problem seriously, though admittedly I never got around to 
implementing it.  The question in my mind is "is it better to build this 
on top of std.concurrency, or to go back to the thread class.  The code 
of std.concurrency shows pretty clearly how to build a mailbox, but the 
one that it builds doesn't store the things that I want, and is a lot 
more flexible than I have any use for.  Still, it's being maintained as 
a part of the language...but it's a private class, so I can't use it 
directly.  But threading is difficult and error prone, so it might be 
better to write a layer on top of std.concurrency, even if it means I 
need to re-implement a lot of what has already been done.

-- 
Charles Hixson



More information about the Digitalmars-d-learn mailing list