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