[racket-dev] feature request: thread-safe memoize-evt

From: Robby Findler (robby at eecs.northwestern.edu)
Date: Thu Jan 29 17:41:16 EST 2015

Is the issue that the E_b from Jan's original message might produce
multiple values and you are supposed to take the value that's
available only after something syncs on the E_m?

That is, I thought you could just create a separate thread that sync's
on E_b and then whenever you get a value from it, then the E_m would
just continue to produce that all the time. But I think you're saying
that wouldn't work?

I guess I'm not getting it. Thanks for more explanation.

Robby


On Thu, Jan 29, 2015 at 1:55 PM, Matthew Flatt <mflatt at cs.utah.edu> wrote:
> Hi Jan,
>
> Interesting problem!
>
> I think I see what you mean: There's no way to combine the completion
> of an event plus saving its value as an atomic operation, except by
> putting the synchronization in its own thread. But if you put the
> synchronization in its own thread, then there's no way to prevent that
> thread's synchronization when a consumer synchronization (i.e., one
> that is waiting for the thread's result) picks a different event than
> the one represented by the thread.
>
> It's easy to make a complete+save combination atomic if it's built into
> the scheduler. So, I can easily imagine adding a simpler primitive,
> `once-evt`. The event OE created by `(once-evt E)` could save the first
> result produced by E, but not attempt to have only a single wait on E.
> That is, if OE1 is synchronized in multiple threads, then it would be
> like synchronizing E in multiple threads, but only the first result
> from E will be saved.
>
> Unfortunately, `once-evt` isn't enough to implement `memoize-evt`. The
> troublesome case is then thread T1 is synchronizing on OE1, T1 gets
> suspended, and T2 starts waiting on OE1. In that case, you'd like T2 to
> take over the wait, even if it means restarting E. You can detect that
> T1 is suspended and have T2 start waiting on E, but there's no way to
> cancel the wait of E in T1.
>
> Building `memoize-evt` into the core doesn't the avoid the need to, at
> some level, cancel T1's wait on E. I'll keep thinking about it, but it
> looks like that would require deep changes to the scheduler.
>
> Would the simpler `once-evt` work in your situation, or do you need the
> guarantee that only one wait of E happens at a time?
>
> Matthew
>
> At Wed, 28 Jan 2015 13:49:51 +0100, Jan Dvořák wrote:
>> Hi,
>>
>> I would like to ask for another extension of the Racket's event handling
>> system. A `memoize-evt` constructor with following semantics:
>>
>> Given a base event E_b, memoize-evt will produce a memoizing event E_m.
>> Synchronizing on E_m from any number of threads will block until a
>> single value is produced by E_b. This value is then stored inside the
>> E_m. From that moment on, E_m will always be immediately ready for
>> synchronization and produce the stored value in all waiting threads.
>>
>> The single-threaded implementation is a trivial guard-evt + replace-evt
>> + (wrap-evt always-evt) combo, but for thread-safety a temporary thread
>> would be needed to wait for the base event and the solution would have
>> different semantics then rest of the event system.
>>
>> A lower-level approach would also be possible; create something along
>> the lines of a dynamic-wind-evt that would, with some cleverness, allow
>> for generic thread-safe events via locking. Or create a locked-wrap-evt
>> constructor that will not be ready until it's handler finishes.
>>
>> Hoping that I am not being too bothersome,
>> from Prague with thanks,
>> Jan Dvorak
>
>
> _________________________
>   Racket Developers list:
>   http://lists.racket-lang.org/dev


Posted on the dev mailing list.