Skip to content
This repository has been archived by the owner on Sep 10, 2024. It is now read-only.

add withRunner method to EventStream to switch event flow context #74

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

Yarikx
Copy link

@Yarikx Yarikx commented Jun 6, 2013

it could be used to execute events on thread pools, actors, etc.

For example can be used to switch running context to UI thread in android

@nafg
Copy link
Owner

nafg commented Jun 28, 2013

Perhaps we should use scala.concurrent.ExecutionContext?

@dylemma
Copy link
Contributor

dylemma commented Jul 10, 2013

Maybe the Runner type should simply be replaced by something like Runnable => Unit. That would simplify the type signature so that it doesn't need to be an inner type. It would also fit pretty well with the signature of many existing constructs like ThreadPool and ExecutionContext

events.withRunner{ ExecutionContext.global execute _ }

@nafg
Copy link
Owner

nafg commented Jul 11, 2013

Maybe we just need an async method that takes an implicit
ExecutionContext.
Anyone know how prepare is meant to be used?

On Wed, Jul 10, 2013 at 4:29 PM, Dylan Halperin notifications@github.comwrote:

Maybe the Runner type should simply be replaced by something like Runnable
=> Unit. That would simplify the type signature so that it doesn't need
to be an inner type. It would also fit pretty well with the signature of
many existing constructs like ThreadPool and ExecutionContext

events.withRunner{ ExecutionContext.global execute _ }


Reply to this email directly or view it on GitHubhttps://github.com//pull/74#issuecomment-20770744
.

@dylemma
Copy link
Contributor

dylemma commented Jul 11, 2013

In that case wouldn't async be essentially the same as the current nonblocking method?

The value I see in using withRunner(runner: Runnable=>Unit) is that it could fit into non-scala things as well. For example, Java's SWT Display class has void asyncExec(Runnable runnable) and void syncExec(Runnable runnable) which cause a task to be run on the UI thread, which is sometimes mandatory. I imagine @Yarikx has similar motivations w.r.t. Android.

@dylemma
Copy link
Contributor

dylemma commented Jul 15, 2013

How about this:

def nonblocking(implicit ec: ExecutionContext): EventStream[T]
def withRunner(runner: Runnable => Unit): EventStream[T]

@nafg
Copy link
Owner

nafg commented Jul 18, 2013

@dylemma see my comment on the google group.

Here's the interface of ExecutionContext (docs removed):

trait ExecutionContext {
  def execute(runnable: Runnable): Unit
  def reportFailure(t: Throwable): Unit
  def prepare(): ExecutionContext = this
}

If you change execute to apply (and make ExecutionContext extend Function1), essentially ExecutionContext is a Runnable => Unit, with some extra methods (one mandatory). We could even make a converter:
implicit def fromFunc(f: Runnable=>Unit) = new ExecutionContext {
def execute(r: Runnable) = f(r)
def reportFailure(t: Throwable) = t.dumpStack // etc.
}

So you can easily write an ExecutionContext for SWT a/syncExec, or the AWT event thread, or anything.

@dylemma
Copy link
Contributor

dylemma commented Jul 18, 2013

Fair enough. Bonus points if that implicit doesn't need to be explicitly imported. I'm not sure, but maybe if it's defined in EventStream it may work without an import...

@nafg
Copy link
Owner

nafg commented Jul 21, 2013

On the other hand, if you're writing a function literal, in order to trigger an implicit conversion you have to write the types explicitly, but if you call the conversion explicitly the types can be inferred. So it's not really buying anything.

1a.
implicit val nowRunner: ExecutionContext = {r: Runnable => r.run() }; val es2 = es.async
1b.
val es2 = es.async((: Runnable).run())
2a.
implicit val nowRunner = fromFunc(
.run()); val es2 = es.async
2b.
val es2 = es.async(fromFunc{r => r.run() })

@nafg
Copy link
Owner

nafg commented Sep 7, 2014

I'm thinking to address this by using an ADT isomorphic to how RxJava handles success, failure, and END with separate execution paths. Basically foreach(A => Unit) is short for something like observe(Event[A] => Unit) where type Event = Success[A] | Failure | End.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants