On 12/12/13 09:08, Attila Szegedi wrote:
On Dec 12, 2013, at 10:02 AM, Tim Fox <[email protected]
<mailto:[email protected]>> wrote:
On 12/12/13 08:49, Attila Szegedi wrote:
On Dec 12, 2013, at 8:00 AM, Tim Fox <[email protected]
<mailto:[email protected]>> wrote:
On 11/12/13 12:53, Attila Szegedi wrote:
On Dec 11, 2013, at 1:13 PM, Tim Fox <[email protected]
<mailto:[email protected]>> wrote:
Confused...
I assumed that if two scripts where run with their own script
context, then they would already have separate globals, i.e. if I do
myglobal = 1
in module 1 that won't be visible in module 2.
That's true, but then you also end up with the need for
ScriptObjectMirrors between them, and that was what I suggested
you try to avoid.
So I'm not sure really what --global-per-engine really means, if
the modules have their own globals anyway. I guess my
understanding must be wrong somewhere.
Well, it will mean that modules won't have their own globals…
--global-per-engine will make it so that the Global object is
specific to the ScriptEngine, and not to the ScriptContext, e.g.
even if you replace the ScriptContext of the engine, when scripts
are run, they'll still see the same global object as before the
replacement. The gist of it is:
a) without --global-per-engine, the Global object is specific to a
ScriptContext, each ScriptContext has its own. ENGINE_SCOPE
Bindings object of the context is actually a mirror of its Global.
b) with --global-per-engine, the Global object lives in the
ScriptEngine. ENGINE_SCOPE Bindings object of the context is just
a vanilla SimpleBindings (or whatever you set it to), and Global
will delegate property getters for non-existent properties to it
(but it'll still receive property setters, so new global variables
created by one script will be visible by another; no isolation there).
One more question on this. With --global-per-engine, and multiple
ScriptContext instances - if all the ScriptContext instances share
a single a single global, how is this different from just having a
single ScriptContext in which you execute all JavaScript?
Not much. Using separate ScriptContexts with single engine is pretty
much equivalent to modifying the initial ScriptContext of the
engine. When I thought you'll end up using Java code to implement
module loading, I suggested either using separate contexts, or at
least changing the ENGINE_SCOPE bindings of the original context to
contain "module", "exports", etc. but if you now implement those as
parameters of an anonymous function that you put around the module
source code and eval(), then you don't need even that.
So, yeah, you can have a single context for all JavaScript. As I
said earlier, it'll be single-threaded, but JavaScript the language
is by nature single-threaded (that's why node.js is single-threaded
too). Probably the better way to say it is that JavaScript language
has no defined multithreaded semantics, and thus a JavaScript
execution environment is unsafe to use in a multithreaded manner.
Regarding thread safety... Unlike node, Vert.x is multi-threaded,
however we guarantee that code in a particular Verticle is never
executed concurrently by more than one thread.
In other words - we have a single engine which might contain many
scripts, and may have many threads executing different scripts in it
at any one time, but we guarantee that any particular script is never
executed concurrently by more than one thread. So we don't need any
multithreaded JS semantics.
This works well with Rhino and DynJS. So I assume it's ok for a
single engine to be executed concurrently as long as those threads
don't bump into each other, i.e. don't try and execute the same code
concurrently?
Code execution is not a concern, multiple threads executing same code
is okay. Concurrent mutation of shared data is a concern. If those
verticles also have data separation, and whatever data they share they
only use as read-only (talking about native JS objects, arrays, and
global vars here; you can obviously share threadsafe POJOs). Native JS
objects and arrays in Nashorn aren't threadsafe. That's a conscious
design decision; since the language doesn't have defined multithreaded
semantics, it doesn't make much sense to pay the price for it in terms
of code complexity and runtime cost.
+1. This fits the Vert.x model well... we don't share any mutable state
between verticles, and I don't have any desire for the engine to support
it. Vert.x has an "actor-like" approach to concurrency - where each
verticle is like an actor (single threaded) and communicates with other
verticles by passing immutable messages.
Attila.