**** BEGIN LICENSE BLOCK ***** Version: EPL 2.0/GPL 2.0/LGPL 2.1 The contents of this file are subject to the Eclipse Public License Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.eclipse.org/legal/epl-v20.html Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. Copyright (C) 2009-2011 Yoko Harada , CloudBees, Inc. Alternatively, the contents of this file may be used under the terms of either of the GNU General Public License Version 2 or later (the "GPL"), or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), in which case the provisions of the GPL or the LGPL are applicable instead of those above. If you wish to allow use of your version of this file only under the terms of either the GPL or the LGPL, and not to allow others to use your version of this file under the terms of the EPL, indicate your decision by deleting the provisions above and replace them with the notice and other provisions required by the GPL or the LGPL. If you do not delete the provisions above, a recipient may use your version of this file under the terms of any one of the EPL, the GPL or the LGPL. **** END LICENSE BLOCK *****
/** * **** BEGIN LICENSE BLOCK ***** * Version: EPL 2.0/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Eclipse Public * License Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.eclipse.org/legal/epl-v20.html * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * Copyright (C) 2009-2011 Yoko Harada <yokolet@gmail.com>, CloudBees, Inc. * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the EPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the EPL, the GPL or the LGPL. * **** END LICENSE BLOCK ***** */
package org.jruby.embed; import org.jruby.Ruby; import org.jruby.embed.internal.LocalContext;
LocalContextState defines four scopes to maintain LocalContext.

A single ScriptingContainer can be configured to act as a facade for multiple Ruby runtimes (or really multiple Ruby VMs, since each Ruby instance is a Ruby "VM"), and this enum controls that behaviour. (this behaviour is bit like that of ThreadLocal — it changes its behaviour silently depending on the calling thread, an act of multiplexing.)

When you think of this multiplexing behaviour, there are two sets of states that need separate attention. One is Ruby instance, which represents the whole VM, classes, global variables, etc. Then there's attributes and so-called variables, which are really a special scope induced by the scripting container for better JSR-223 interop. In this documentation, we refer to the former as "the runtime" and the latter as "the variables", but the variables shouldn't be confused with the global variables in Ruby's semantics, which belongs to the runtime.

Author:Yoko Harada , Kohsuke Kawaguchi
See Also:
  • https://github.com/jruby/jruby/wiki/RedBridge
/** * LocalContextState defines four scopes to maintain {@link LocalContext}. * * <p> * A single {@link ScriptingContainer} can be configured to act as a facade for multiple {@link Ruby} runtimes * (or really multiple Ruby VMs, since each {@link Ruby} instance is a Ruby "VM"), and this enum controls * that behaviour. (this behaviour is bit like that of {@link ThreadLocal} &mdash; it changes its behaviour * silently depending on the calling thread, an act of multiplexing.) * * <p> * When you think of this multiplexing behaviour, there are two sets of states that need separate attention. * One is {@link Ruby} instance, which represents the whole VM, classes, global variables, etc. Then * there's {@linkplain ScriptingContainer#getAttributeMap() attributes} and so-called * {@linkplain ScriptingContainer#getVarMap() variables}, which are really a special scope induced by the * scripting container for better JSR-223 interop. * In this documentation, we refer to the former as "the runtime" and the latter as "the variables", * but the variables shouldn't be confused with the global variables in Ruby's semantics, which belongs * to the runtime. * * @author Yoko Harada <yokolet@gmail.com> * @author Kohsuke Kawaguchi * @see https://github.com/jruby/jruby/wiki/RedBridge */
public enum LocalContextScope {
Uses a "global" singleton runtime and variables. All the ScriptingContainers that are created with this scope will share a single runtime and a single set of variables. Therefore one container can set a value and another container will see the same value. The global runtime comes from Ruby.getGlobalRuntime(), which initializes or retrieves a Ruby instance in a static field on Ruby. All singleton context scopes will reuse this instance. When any singleton-based scripting container is torn down (ScriptingContainer.terminate()), the global runtime will also be torn down and cleared. Subsequent singleton containers will see a new runtime. Note that unlike the other modes, containers created with singleton context scoping will not tear down the associated JRuby runtime upon finalization.
/** * Uses a "global" singleton runtime and variables. * * All the {@link ScriptingContainer}s that are created with this scope will share a single * runtime and a single set of variables. Therefore one container can * {@link ScriptingContainer#put(String, Object) set a value} and another container will see the same value. * * The global runtime comes from {@link org.jruby.Ruby#getGlobalRuntime()}, which initializes or retrieves a Ruby * instance in a static field on {@link org.jruby.Ruby}. All singleton context scopes will reuse this instance. * When any singleton-based scripting container is torn down ({@link ScriptingContainer#terminate()}), the global runtime will also * be torn down and cleared. Subsequent singleton containers will see a new runtime. * * Note that unlike the other modes, containers created with singleton context scoping will not tear down * the associated JRuby runtime upon finalization. * */
SINGLETON,
ScriptingContainer will not do any multiplexing at all.

ScriptingContainer will get one runtime and one set of variables, and regardless of the calling thread it'll use this same pair.

If you have multiple threads calling single ScriptingContainer instance, then you may need to take caution as a variable set by one thread will be visible to another thread.

If you aren't using the variables of ScriptingContainer, this is normally what you want.

/** * {@link ScriptingContainer} will not do any multiplexing at all. * * <p> * {@link ScriptingContainer} will get one runtime and one set of variables, and regardless of the calling * thread it'll use this same pair. * <p> * If you have multiple threads calling single {@link ScriptingContainer} instance, * then you may need to take caution as a variable set by one thread will be visible to another thread. * <p> * If you aren't using the variables of {@link ScriptingContainer}, this is normally what you want. */
SINGLETHREAD,
Maintain separate runtimes and variable maps for each calling thread.

Known as the "apartment thread model", this mode makes ScriptingContainer lazily creates a runtime and a variable map separately for each calling thread. Therefore, despite the fact that multiple threads call on the same object, they are completely isolated from each other. (the flip side of the coin is that no ruby objects can be shared between threads as they belong to different "ruby VM".)

/** * Maintain separate runtimes and variable maps for each calling thread. * * <p> * Known as the "apartment thread model", this mode makes {@link ScriptingContainer} lazily * creates a runtime and a variable map separately for each calling thread. Therefore, despite * the fact that multiple threads call on the same object, they are completely isolated from each other. * (the flip side of the coin is that no ruby objects can be shared between threads as they belong * to different "ruby VM".) */
THREADSAFE,
Use a single runtime but variable maps are thread local.

In this mode, there'll be a single runtime dedicated for each ScriptingContainer, but a separate map of variables are created for each calling thread through ThreadLocal. In a situation where you have multiple threads calling one ScriptingContainer, this means ruby code will see multiple threads calling them, and therefore they need to be thread safe. But because variables are thread local, if your program does something like (1) set a few variables, (2) evaluate a script that refers to those variables, then you won't have to worry about values from multiple threads mixing with each other.

/** * Use a single runtime but variable maps are thread local. * * <p> * In this mode, there'll be a single runtime dedicated for each {@link ScriptingContainer}, * but a separate map of variables are created for each calling thread through {@link ThreadLocal}. * * In a situation where you have multiple threads calling one {@link ScriptingContainer}, this means * ruby code will see multiple threads calling them, and therefore they need to be thread safe. * But because variables are thread local, if your program does something like (1) set a few variables, * (2) evaluate a script that refers to those variables, then you won't have to worry about values from * multiple threads mixing with each other. */
CONCURRENT }