Manual
Next chapter: Entering Executables
Or, go back to the manual's table of contents
Part 3: Threads and Execution Contexts
In the example in part 2, every time we call "execute()" we create a global state for the executable, which is discarded when the executable is done. Scripturian lets us explicitly manipulate and reuse this state, and makes sure to decouple the executing thread from the executable itself. For example:
ExecutionContext executionContext = new ExecutionContext(); try { StringWriter writer = new StringWriter(); StringWriter log = new StringWriter(); executionContext.setWriter( writer ); executionContext.setServices().put( "log", log ); executable.execute( executionContext ); String result = write.toString(); } finally { executionContext.release(); }
Note immediately that if you create an execution context, you are responsible for releasing it.
You can control standard output and error for the context. More interesting is that you can install "services", which are available from inside the executable as global instances. For example, in JavaScript we would be able to execute code like this:"
print('hello to standard out from javascript!'); log.write('hello to the log file from javascript!');
The services put in the execution context are also your way of getting state out of the executable when it's done executing, or even while it's executing. Though, note that it's up to you to make sure that your services are thread-safe if necessary.
What makes the above code powerful is that concurrent threads can execute the executable using different execution contexts, so that standard out and services are different for each thread. To return to our an example of a server application, we can use "setWriter()" to send the output of an executable directly to the user over the network. Concurrent requests would thus be properly and elegantly handled. See the ExecutionContext documentation for more options.
Thread Safety
It's important to note that an execution context is not immediately thread-safe. There are actually two use cases for it, only one which requires thread safety:
- In the first, you have each thread that executes the executable create (and subsequently release) its own execution context. The execution context is in fact bound to the thread. That is the use case implied in the example above.
- In the second use case, "makeImmutable()" is internally called on the execution context, which makes it naturally thread-safe. It is used for "entering" executables, as detailed below.
Next chapter: Entering Executables
Or, go back to the manual's table of contents