-
Notifications
You must be signed in to change notification settings - Fork 1
ActorContext
Text compliant with Leucine version 0.5.x, x >= 1 (minor differences with 0.5.0)
All action takes place against the so called ActorContext
, which should
always be available as a given. This context organizes the computation
for Actor
just as the standard ExecutionContext
for Future
does.
At the same time this isolates you from the platform by having an
platform dependent implementation for the JVM, JS and Native.
Even if the platform is single threaded (like JS and Native for now)
they still work as multithreaded to the user, as long as you do
not block in any actor. This is, by the way, a bad idea on a
multithreaded platform as well.
The signature of the ActorContext reads:
trait ActorContext extends PlatformContext with ExecutionContext
so it implements the standard ExecutionContext
as well as the
Leucine specific methods in PlatformContext
. For each supported
platform (JVM, JS, Native) there exists a special ContextImplementation
which ensures every call is handled the correct way for that specific platform.
For the user this is nice to know, but not that relevant. What however
may be relevant is how the ActorContext
itself is implemented by
for this ContextImplementation
to get a so called ActorContext.Implementation
.
Instances of such a class (which then expose the ActorContext interface
for use in your application) contain some parameters, the
SystemParameters
you may tweak, how is demonstrated on
a separate page.
There also exists the possibility for the user to define an own
ActorContext.Implementation
, for extra features. Per default two
are predefined:
-
ActorContext.DirectImplementation
: This provides the execution environment for the different platforms where they run directly on (JVM, JS, Native) -
ActorContext.EmulatedImplementation
: This provides an completely platform independent emulated execution environment.
The ActorContext.DirectImplementation
can be selected by defining:
given ActorContext = ActorContext.system
on top of your package. Doing so provides an instance of ActorContext.DirectImplementation
with the default system parameters. This is usually the most performant
implementation, and is the one we use in all examples. It makes use
of threading, if available, and also makes sure the ActorGuard
works
together with the platform properties.
Sometimes you want to be completely independent of the platform. To that end you can use an emulated version of the context:
given ActorContext = ActorContext.system
It provides its own scheduler, takes care of the timers etc. This extra layer may come at some performance loss though, compared to an implementation that runs directly on the metal.
But, given the fact that Scala Native is not yet multithreaded, Leucine uses a version of the emulator to make it run as if it where multithreaded on Native. This appears to run reasonably fast.
If you want to have extra functionality present in your context you can define
your own ActorContext.Implementation
it must at least extend the traits:
-
SystemParameters
toMySystemParameters
: if needed add you own parameters to the existing ones. -
ActorContext
toMyActorContext
: if needed add your own methods to the existing ones. - use one of
ContextImplementation
orContextEmulation
, defining your own is possible, but if not for an entirely new platform it does not make much sense
Then you can define for example:
object MySystem extends MySystemParameters :
def mySetting: Int = 42
...
/** The default ActorImplementation for the users. */
class MyImplementation(val parameters: MySystemParameters) extends ContextImplementation, MyActorContext, MySystemParameters :
export parameters.*
def platform = ContextImplementation.platform
val mySystem: ActorContext = new MyImplementation(MySystem)
and use this as given ActorContext
.