Home » openjdk-7 » java.lang.invoke » [javadoc | source]

    1   /*
    2    * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Oracle designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Oracle in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   22    * or visit www.oracle.com if you need additional information or have any
   23    * questions.
   24    */
   25   
   26   package java.lang.invoke;
   27   
   28   import java.util.concurrent.atomic.AtomicInteger;
   29   
   30   /**
   31    * A {@code MutableCallSite} is a {@link CallSite} whose target variable
   32    * behaves like an ordinary field.
   33    * An {@code invokedynamic} instruction linked to a {@code MutableCallSite} delegates
   34    * all calls to the site's current target.
   35    * The {@linkplain CallSite#dynamicInvoker dynamic invoker} of a mutable call site
   36    * also delegates each call to the site's current target.
   37    * <p>
   38    * Here is an example of a mutable call site which introduces a
   39    * state variable into a method handle chain.
   40    * <!-- JavaDocExamplesTest.testMutableCallSite -->
   41    * <blockquote><pre>
   42   MutableCallSite name = new MutableCallSite(MethodType.methodType(String.class));
   43   MethodHandle MH_name = name.dynamicInvoker();
   44   MethodType MT_str1 = MethodType.methodType(String.class);
   45   MethodHandle MH_upcase = MethodHandles.lookup()
   46       .findVirtual(String.class, "toUpperCase", MT_str1);
   47   MethodHandle worker1 = MethodHandles.filterReturnValue(MH_name, MH_upcase);
   48   name.setTarget(MethodHandles.constant(String.class, "Rocky"));
   49   assertEquals("ROCKY", (String) worker1.invokeExact());
   50   name.setTarget(MethodHandles.constant(String.class, "Fred"));
   51   assertEquals("FRED", (String) worker1.invokeExact());
   52   // (mutation can be continued indefinitely)
   53    * </pre></blockquote>
   54    * <p>
   55    * The same call site may be used in several places at once.
   56    * <blockquote><pre>
   57   MethodType MT_str2 = MethodType.methodType(String.class, String.class);
   58   MethodHandle MH_cat = lookup().findVirtual(String.class,
   59     "concat", methodType(String.class, String.class));
   60   MethodHandle MH_dear = MethodHandles.insertArguments(MH_cat, 1, ", dear?");
   61   MethodHandle worker2 = MethodHandles.filterReturnValue(MH_name, MH_dear);
   62   assertEquals("Fred, dear?", (String) worker2.invokeExact());
   63   name.setTarget(MethodHandles.constant(String.class, "Wilma"));
   64   assertEquals("WILMA", (String) worker1.invokeExact());
   65   assertEquals("Wilma, dear?", (String) worker2.invokeExact());
   66    * </pre></blockquote>
   67    * <p>
   68    * <em>Non-synchronization of target values:</em>
   69    * A write to a mutable call site's target does not force other threads
   70    * to become aware of the updated value.  Threads which do not perform
   71    * suitable synchronization actions relative to the updated call site
   72    * may cache the old target value and delay their use of the new target
   73    * value indefinitely.
   74    * (This is a normal consequence of the Java Memory Model as applied
   75    * to object fields.)
   76    * <p>
   77    * The {@link #syncAll syncAll} operation provides a way to force threads
   78    * to accept a new target value, even if there is no other synchronization.
   79    * <p>
   80    * For target values which will be frequently updated, consider using
   81    * a {@linkplain VolatileCallSite volatile call site} instead.
   82    * @author John Rose, JSR 292 EG
   83    */
   84   public class MutableCallSite extends CallSite {
   85       /**
   86        * Creates a blank call site object with the given method type.
   87        * The initial target is set to a method handle of the given type
   88        * which will throw an {@link IllegalStateException} if called.
   89        * <p>
   90        * The type of the call site is permanently set to the given type.
   91        * <p>
   92        * Before this {@code CallSite} object is returned from a bootstrap method,
   93        * or invoked in some other manner,
   94        * it is usually provided with a more useful target method,
   95        * via a call to {@link CallSite#setTarget(MethodHandle) setTarget}.
   96        * @param type the method type that this call site will have
   97        * @throws NullPointerException if the proposed type is null
   98        */
   99       public MutableCallSite(MethodType type) {
  100           super(type);
  101       }
  102   
  103       /**
  104        * Creates a call site object with an initial target method handle.
  105        * The type of the call site is permanently set to the initial target's type.
  106        * @param target the method handle that will be the initial target of the call site
  107        * @throws NullPointerException if the proposed target is null
  108        */
  109       public MutableCallSite(MethodHandle target) {
  110           super(target);
  111       }
  112   
  113       /**
  114        * Returns the target method of the call site, which behaves
  115        * like a normal field of the {@code MutableCallSite}.
  116        * <p>
  117        * The interactions of {@code getTarget} with memory are the same
  118        * as of a read from an ordinary variable, such as an array element or a
  119        * non-volatile, non-final field.
  120        * <p>
  121        * In particular, the current thread may choose to reuse the result
  122        * of a previous read of the target from memory, and may fail to see
  123        * a recent update to the target by another thread.
  124        *
  125        * @return the linkage state of this call site, a method handle which can change over time
  126        * @see #setTarget
  127        */
  128       @Override public final MethodHandle getTarget() {
  129           return target;
  130       }
  131   
  132       /**
  133        * Updates the target method of this call site, as a normal variable.
  134        * The type of the new target must agree with the type of the old target.
  135        * <p>
  136        * The interactions with memory are the same
  137        * as of a write to an ordinary variable, such as an array element or a
  138        * non-volatile, non-final field.
  139        * <p>
  140        * In particular, unrelated threads may fail to see the updated target
  141        * until they perform a read from memory.
  142        * Stronger guarantees can be created by putting appropriate operations
  143        * into the bootstrap method and/or the target methods used
  144        * at any given call site.
  145        *
  146        * @param newTarget the new target
  147        * @throws NullPointerException if the proposed new target is null
  148        * @throws WrongMethodTypeException if the proposed new target
  149        *         has a method type that differs from the previous target
  150        * @see #getTarget
  151        */
  152       @Override public void setTarget(MethodHandle newTarget) {
  153           checkTargetChange(this.target, newTarget);
  154           setTargetNormal(newTarget);
  155       }
  156   
  157       /**
  158        * {@inheritDoc}
  159        */
  160       @Override
  161       public final MethodHandle dynamicInvoker() {
  162           return makeDynamicInvoker();
  163       }
  164   
  165       /**
  166        * Performs a synchronization operation on each call site in the given array,
  167        * forcing all other threads to throw away any cached values previously
  168        * loaded from the target of any of the call sites.
  169        * <p>
  170        * This operation does not reverse any calls that have already started
  171        * on an old target value.
  172        * (Java supports {@linkplain java.lang.Object#wait() forward time travel} only.)
  173        * <p>
  174        * The overall effect is to force all future readers of each call site's target
  175        * to accept the most recently stored value.
  176        * ("Most recently" is reckoned relative to the {@code syncAll} itself.)
  177        * Conversely, the {@code syncAll} call may block until all readers have
  178        * (somehow) decached all previous versions of each call site's target.
  179        * <p>
  180        * To avoid race conditions, calls to {@code setTarget} and {@code syncAll}
  181        * should generally be performed under some sort of mutual exclusion.
  182        * Note that reader threads may observe an updated target as early
  183        * as the {@code setTarget} call that install the value
  184        * (and before the {@code syncAll} that confirms the value).
  185        * On the other hand, reader threads may observe previous versions of
  186        * the target until the {@code syncAll} call returns
  187        * (and after the {@code setTarget} that attempts to convey the updated version).
  188        * <p>
  189        * This operation is likely to be expensive and should be used sparingly.
  190        * If possible, it should be buffered for batch processing on sets of call sites.
  191        * <p>
  192        * If {@code sites} contains a null element,
  193        * a {@code NullPointerException} will be raised.
  194        * In this case, some non-null elements in the array may be
  195        * processed before the method returns abnormally.
  196        * Which elements these are (if any) is implementation-dependent.
  197        *
  198        * <h3>Java Memory Model details</h3>
  199        * In terms of the Java Memory Model, this operation performs a synchronization
  200        * action which is comparable in effect to the writing of a volatile variable
  201        * by the current thread, and an eventual volatile read by every other thread
  202        * that may access one of the affected call sites.
  203        * <p>
  204        * The following effects are apparent, for each individual call site {@code S}:
  205        * <ul>
  206        * <li>A new volatile variable {@code V} is created, and written by the current thread.
  207        *     As defined by the JMM, this write is a global synchronization event.
  208        * <li>As is normal with thread-local ordering of write events,
  209        *     every action already performed by the current thread is
  210        *     taken to happen before the volatile write to {@code V}.
  211        *     (In some implementations, this means that the current thread
  212        *     performs a global release operation.)
  213        * <li>Specifically, the write to the current target of {@code S} is
  214        *     taken to happen before the volatile write to {@code V}.
  215        * <li>The volatile write to {@code V} is placed
  216        *     (in an implementation specific manner)
  217        *     in the global synchronization order.
  218        * <li>Consider an arbitrary thread {@code T} (other than the current thread).
  219        *     If {@code T} executes a synchronization action {@code A}
  220        *     after the volatile write to {@code V} (in the global synchronization order),
  221        *     it is therefore required to see either the current target
  222        *     of {@code S}, or a later write to that target,
  223        *     if it executes a read on the target of {@code S}.
  224        *     (This constraint is called "synchronization-order consistency".)
  225        * <li>The JMM specifically allows optimizing compilers to elide
  226        *     reads or writes of variables that are known to be useless.
  227        *     Such elided reads and writes have no effect on the happens-before
  228        *     relation.  Regardless of this fact, the volatile {@code V}
  229        *     will not be elided, even though its written value is
  230        *     indeterminate and its read value is not used.
  231        * </ul>
  232        * Because of the last point, the implementation behaves as if a
  233        * volatile read of {@code V} were performed by {@code T}
  234        * immediately after its action {@code A}.  In the local ordering
  235        * of actions in {@code T}, this read happens before any future
  236        * read of the target of {@code S}.  It is as if the
  237        * implementation arbitrarily picked a read of {@code S}'s target
  238        * by {@code T}, and forced a read of {@code V} to precede it,
  239        * thereby ensuring communication of the new target value.
  240        * <p>
  241        * As long as the constraints of the Java Memory Model are obeyed,
  242        * implementations may delay the completion of a {@code syncAll}
  243        * operation while other threads ({@code T} above) continue to
  244        * use previous values of {@code S}'s target.
  245        * However, implementations are (as always) encouraged to avoid
  246        * livelock, and to eventually require all threads to take account
  247        * of the updated target.
  248        *
  249        * <p style="font-size:smaller;">
  250        * <em>Discussion:</em>
  251        * For performance reasons, {@code syncAll} is not a virtual method
  252        * on a single call site, but rather applies to a set of call sites.
  253        * Some implementations may incur a large fixed overhead cost
  254        * for processing one or more synchronization operations,
  255        * but a small incremental cost for each additional call site.
  256        * In any case, this operation is likely to be costly, since
  257        * other threads may have to be somehow interrupted
  258        * in order to make them notice the updated target value.
  259        * However, it may be observed that a single call to synchronize
  260        * several sites has the same formal effect as many calls,
  261        * each on just one of the sites.
  262        *
  263        * <p style="font-size:smaller;">
  264        * <em>Implementation Note:</em>
  265        * Simple implementations of {@code MutableCallSite} may use
  266        * a volatile variable for the target of a mutable call site.
  267        * In such an implementation, the {@code syncAll} method can be a no-op,
  268        * and yet it will conform to the JMM behavior documented above.
  269        *
  270        * @param sites an array of call sites to be synchronized
  271        * @throws NullPointerException if the {@code sites} array reference is null
  272        *                              or the array contains a null
  273        */
  274       public static void syncAll(MutableCallSite[] sites) {
  275           if (sites.length == 0)  return;
  276           STORE_BARRIER.lazySet(0);
  277           for (int i = 0; i < sites.length; i++) {
  278               sites[i].getClass();  // trigger NPE on first null
  279           }
  280           // FIXME: NYI
  281       }
  282       private static final AtomicInteger STORE_BARRIER = new AtomicInteger();
  283   }

Home » openjdk-7 » java.lang.invoke » [javadoc | source]