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

2015-01-30 Thread Jan Dvořák
Thanks for your time.

On Thu, 2015-01-29 at 12:55 -0700, Matthew Flatt wrote:
> 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?

OK, my original goal is to implement a remote method call multiplexer.
The kind where you send a message with an identifier and the remote
party eventually replies with the same identifier or possibly with a
well-known one to indicate an out-of-bound notification.

So, I'd like to end up with (something-receive-evt something key) and
(something-call-evt something key request).

I can see two ways to do that;

 1.  Have a dispatch table with pending messages.
 2.  Broadcast all incoming messages to all waiters.

Dispatch table requires non-racy invalidation of pending requests to
prevent resource leaks.

Broadcasting messages requires construction of a thread-safe memoizing
event combinator (produces next-evt and a single result).

Also, I have a feeling that I could get close to (1) if I keep some
cleanup thread and utilize nack-guard-evt, but something tells me it
might be racy.

Best regards,
Jan Dvorak

_
  Racket Developers list:
  http://lists.racket-lang.org/dev


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

2015-01-29 Thread Jan Dvořák
On Thu, 2015-01-29 at 16:41 -0600, Robby Findler wrote:
> 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?

The problem is that the auxiliary thread would always wait for the E_b,
even when nobody is interested in the result anymore. Moreover, putting
the wait in another thread would require the E_b to be thread safe.

_
  Racket Developers list:
  http://lists.racket-lang.org/dev


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

2015-01-29 Thread Robby Findler
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  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

_
  Racket Developers list:
  http://lists.racket-lang.org/dev


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

2015-01-29 Thread Matthew Flatt
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


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

2015-01-28 Thread Jan Dvořák
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