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 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


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 mfl...@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

_
  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


[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