All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.strobel.core.Fences Maven / Gradle / Ivy

package com.strobel.core;

/*
 * Written by Doug Lea with assistance from members of JCP JSR-166
 * Expert Group and released to the public domain, as explained at
 * http://creativecommons.org/publicdomain/zero/1.0/
 */

/**
 * A set of methods providing fine-grained control over happens-before
 * and synchronization order relations among reads and/or writes.  The
 * methods of this class are designed for use in uncommon situations
 * where declaring variables {@code volatile} or {@code final}, using
 * instances of atomic classes, using {@code synchronized} blocks or
 * methods, or using other synchronization facilities are not possible
 * or do not provide the desired control.
 *
 * 

Memory Ordering. There are three methods for controlling * ordering relations among memory accesses (i.e., reads and * writes). Method {@code orderWrites} is typically used to enforce * order between two writes, and {@code orderAccesses} between a write * and a read. Method {@code orderReads} is used to enforce order * between two reads with respect to other {@code orderWrites} and/or * {@code orderAccesses} invocations. The formally specified * properties of these methods described below provide * platform-independent guarantees that are honored by all levels of a * platform (compilers, systems, processors). The use of these * methods may result in the suppression of otherwise valid compiler * transformations and optimizations that could visibly violate the * specified orderings, and may or may not entail the use of * processor-level "memory barrier" instructions. * *

Each ordering method accepts a {@code ref} argument, and * controls ordering among accesses with respect to this reference. * Invocations must be placed between accesses performed in * expression evaluations and assignment statements to control the * orderings of prior versus subsequent accesses appearing in program * order. These methods also return their arguments to simplify * correct usage in these contexts. * *

Usages of ordering methods almost always take one of the forms * illustrated in the examples below. These idioms arrange some of * the ordering properties associated with {@code volatile} and * related language-based constructions, but without other * compile-time and runtime benefits that make language-based * constructions far better choices when they are applicable. Usages * should be restricted to the control of strictly internal * implementation matters inside a class or package, and must either * avoid or document any consequent violations of ordering or safety * properties expected by users of a class employing them. * *

Reachability. Method {@code reachabilityFence} * establishes an ordering for strong reachability (as defined in the * {@link java.lang.ref} package specification) with respect to * garbage collection. Method {@code reachabilityFence} differs from * the others in that it controls relations that are otherwise only * implicit in a program -- the reachability conditions triggering * garbage collection. As illustrated in the sample usages below, * this method is applicable only when reclamation may have visible * effects, which is possible for objects with finalizers (see Section * 12.6 of the Java Language Specification) that are implemented in * ways that rely on ordering control for correctness. * *

Sample Usages * *

Safe publication. With care, method {@code orderWrites} * may be used to obtain the memory safety effects of {@code final} * for a field that cannot be declared as {@code final}, because its * primary initialization cannot be performed in a constructor, in * turn because it is used in a framework requiring that all classes * have a no-argument constructor; as in: * *

 * class WidgetHolder {
 *   private Widget widget;
 *   public WidgetHolder() {}
 *   public static WidgetHolder newWidgetHolder(Params params) {
 *     WidgetHolder h = new WidgetHolder();
 *     h.widget = new Widget(params);
 *     return Fences.orderWrites(h);
 *   }
 * }
 * 
* * Here, the invocation of {@code orderWrites} ensures that the * effects of the widget assignment are ordered before those of any * (unknown) subsequent stores of {@code h} in other variables that * make {@code h} available for use by other objects. Initialization * sequences using {@code orderWrites} require more care than those * involving {@code final} fields. When {@code final} is not used, * compilers cannot help you to ensure that the field is set correctly * across all usages. You must fully initialize objects * before the {@code orderWrites} invocation that makes * references to them safe to assign to accessible variables. Further, * initialization sequences must not internally "leak" the reference * by using it as an argument to a callback method or adding it to a * static data structure. If less constrained usages were required, * it may be possible to cope using more extensive sets of fences, or * as a normally better choice, using synchronization (locking). * Conversely, if it were possible to do so, the best option would be * to rewrite class {@code WidgetHolder} to use {@code final}. * *

An alternative approach is to place similar mechanics in the * (sole) method that makes such objects available for use by others. * Here is a stripped-down example illustrating the essentials. In * practice, among other changes, you would use access methods instead * of a public field. * *

 * class AnotherWidgetHolder {
 *   public Widget widget;
 *   void publish(Widget w) {
 *     this.widget = Fences.orderWrites(w);
 *   }
 *   // ...
 * }
 * 
* * In this case, the {@code orderWrites} invocation occurs before the * store making the object available. Correctness again relies on * ensuring that there are no leaks prior to invoking this method, and * that it really is the only means of accessing the * published object. This approach is not often applicable -- * normally you would publish objects using a thread-safe collection * that itself guarantees the expected ordering relations. However, it * may come into play in the construction of such classes themselves. * *

Safely updating fields. Outside of the initialization * idioms illustrated above, Fence methods ordering writes must be * paired with those ordering reads. To illustrate, suppose class * {@code c} contains an accessible variable {@code data} that should * have been declared as {@code volatile} but wasn't: * *

 * class C {
 *    Object data;  // need volatile access but not volatile
 *    // ...
 * }
 *
 * class App {
 *   Object getData(C c) {
 *      return Fences.orderReads(c).data;
 *   }
 *
 *   void setData(C c) {
 *      Object newValue = ...;
 *      c.data = Fences.orderWrites(newValue);
 *      Fences.orderAccesses(c);
 *   }
 *   // ...
 * }
 * 
* * Method {@code getData} provides an emulation of {@code volatile} * reads of (non-long/double) fields by ensuring that the read of * {@code c} obtained as an argument is ordered before subsequent * reads using this reference, and then performs the read of its * field. Method {@code setData} provides an emulation of volatile * writes, ensuring that all other relevant writes have completed, * then performing the assignment, and then ensuring that the write is * ordered before any other access. These techniques may apply even * when fields are not directly accessible, in which case calls to * fence methods would surround calls to methods such as {@code * c.getData()}. However, these techniques cannot be applied to * {@code long} or {@code double} fields because reads and writes of * fields of these types are not guaranteed to be * atomic. Additionally, correctness may require that all accesses of * such data use these kinds of wrapper methods, which you would need * to manually ensure. * *

More generally, Fence methods can be used in this way to achieve * the safety properties of {@code volatile}. However their use does * not necessarily guarantee the full sequential consistency * properties specified in the Java Language Specification chapter 17 * for programs using {@code volatile}. In particular, emulation using * Fence methods is not guaranteed to maintain the property that * {@code volatile} operations performed by different threads are * observed in the same order by all observer threads. * *

Acquire/Release management of thread safe objects. It may * be possible to use weaker conventions for volatile-like variables * when they are used to keep track of objects that fully manage their * own thread-safety and synchronization. Here, an acquiring read * operation remains the same as a volatile-read, but a releasing * write differs by virtue of not itself ensuring an ordering of its * write with subsequent reads, because the required effects are * already ensured by the referenced objects. * For example: * *

 * class Item {
 *    synchronized f(); // ALL methods are synchronized
 *    // ...
 * }
 *
 * class ItemHolder {
 *   private Item item;
 *   Item acquireItem() {
 *      return Fences.orderReads(item);
 *   }
 *
 *   void releaseItem(Item x) {
 *      item = Fences.orderWrites(x);
 *   }
 *
 *   // ...
 * }
 * 
* * Because this construction avoids use of {@code orderAccesses}, * which is typically more costly than the other fence methods, it may * result in better performance than using {@code volatile} or its * emulation. However, as is the case with most applications of fence * methods, correctness relies on the usage context -- here, the * thread safety of {@code Item}, as well as the lack of need for full * volatile semantics inside this class itself. However, the second * concern means that it can be difficult to extend the {@code * ItemHolder} class in this example to be more useful. * *

Avoiding premature finalization. Finalization may occur * whenever a Java Virtual Machine detects that no reference to an * object will ever be stored in the heap: A garbage collector may * reclaim an object even if the fields of that object are still in * use, so long as the object has otherwise become unreachable. This * may have surprising and undesirable effects in cases such as the * following example in which the bookkeeping associated with a class * is managed through array indices. Here, method {@code action} * uses a {@code reachabilityFence} to ensure that the Resource * object is not reclaimed before bookkeeping on an associated * ExternalResource has been performed; in particular here, to ensure * that the array slot holding the ExternalResource is not nulled out * in method {@link Object#finalize}, which may otherwise run * concurrently. * *

 * class Resource {
 *   private static ExternalResource[] externalResourceArray = ...
 *
 *   int myIndex;
 *   Resource(...) {
 *     myIndex = ...
 *     externalResourceArray[myIndex] = ...;
 *     ...
 *   }
 *   protected void finalize() {
 *     externalResourceArray[myIndex] = null;
 *     ...
 *   }
 *   public void action() {
 *     try {
 *       // ...
 *       int i = myIndex;
 *       Resource.update(externalResourceArray[i]);
 *     } finally {
 *       Fences.reachabilityFence(this);
 *     }
 *   }
 *   private static void update(ExternalResource ext) {
 *     ext.status = ...;
 *   }
 * }
 * 
* * Here, the call to {@code reachabilityFence} is unintuitively * placed after the call to {@code update}, to ensure that * the array slot is not nulled out by {@link Object#finalize} before * the update, even if the call to {@code action} was the last use of * this object. This might be the case if for example a usage in a * user program had the form {@code new Resource().action();} which * retains no other reference to this Resource. While probably * overkill here, {@code reachabilityFence} is placed in a {@code * finally} block to ensure that it is invoked across all paths in the * method. In a method with more complex control paths, you might * need further precautions to ensure that {@code reachabilityFence} * is encountered along all of them. * *

It is sometimes possible to better encapsulate use of * {@code reachabilityFence}. Continuing the above example, if it * were OK for the call to method update to proceed even if the * finalizer had already executed (nulling out slot), then you could * localize use of {@code reachabilityFence}: * *

 *   public void action2() {
 *     // ...
 *     Resource.update(getExternalResource());
 *   }
 *   private ExternalResource getExternalResource() {
 *     ExternalResource ext = externalResourceArray[myIndex];
 *     Fences.reachabilityFence(this);
 *     return ext;
 *   }
 * 
* *

Method {@code reachabilityFence} is not required in * constructions that themselves ensure reachability. For example, * because objects that are locked cannot in general be reclaimed, it * would suffice if all accesses of the object, in all methods of * class Resource (including {@code finalize}) were enclosed in {@code * synchronized (this)} blocks. (Further, such blocks must not include * infinite loops, or themselves be unreachable, which fall into the * corner case exceptions to the "in general" disclaimer.) However, * method {@code reachabilityFence} remains a better option in cases * where this approach is not as efficient, desirable, or possible; * for example because it would encounter deadlock. * *

Formal Properties. * *

Using the terminology of The Java Language Specification chapter * 17, the rules governing the semantics of the methods of this class * are as follows: * *

The following is still under construction. * *

* *
[Definitions] *
*
    * *
  • Define sequenced(a, b) to be true if a * occurs before b in program order. * *
  • Define accesses(a, p) to be true if * a is a read or write of a field (or if an array, an * element) of the object referenced by p. * *
  • Define deeplyAccesses(a, p) to be true if either * accesses(a, p) or deeplyAccesses(a, q) where * q is the value seen by some read r * such that accesses(r, p). * *
*

*

[Matching] *
Given: * *
    * *
  • p, a reference to an object * *
  • wf, an invocation of {@code orderWrites(p)} or * {@code orderAccesses(p)} * *
  • w, a write of value p * *
  • rf, an invocation of {@code orderReads(p)} or * {@code orderAccesses(p)} * *
  • r, a read returning value p * *
* If: *
    *
  • sequenced(wf, w) *
  • read r sees write w *
  • sequenced(r, rf) *
* Then: *
    * *
  • wf happens-before rf * *
  • wf precedes rf in the * synchronization order * *
  • If (r1, w1) and (r2, * w2) are two pairs of reads and writes, both * respectively satisfying the above conditions for p, * and sequenced(r1, r2) then it is not the case that w2 * happens-before w1. * *
*

*

[Initial Reads] *
Given: * *
    * *
  • p, a reference to an object * *
  • a, an access where deeplyAccesses(a, p) * *
  • wf, an invocation of {@code orderWrites(p)} or * {@code orderAccesses(p)} * *
  • w, a write of value p * *
  • r, a read returning value p * *
  • b, an access where accesses(b, p) * *
* If: *
    *
  • sequenced(a, wf); *
  • sequenced(wf, w) *
  • read r sees write w, and * r is the first read by some thread * t that sees value p *
  • sequenced(r, b) *
* Then: *
    *
  • the effects of b are constrained * by the relation a happens-before b. *
*

*

[orderAccesses] *
Given: * *
    *
  • p, a reference to an object *
  • f, an invocation of {@code orderAccesses(p)} *
* If: *
    *
  • sequenced(f, w) *
* * Then: * *
    * *
  • f is an element of the synchronization order. * *
*

*

[Reachability] *
Given: * *
    * *
  • p, a reference to an object * *
  • f, an invocation of {@code reachabilityFence(p)} * *
  • a, an access where accesses(a, p) * *
  • b, an action (by a garbage collector) taking * the form of an invocation of {@code * p.finalize()} or of enqueuing any {@link * java.lang.ref.Reference} constructed with argument p * *
* * If: *
    *
  • sequenced(a, f) *
* * Then: * *
    * *
  • a happens-before b. * *
* *
* * @since 1.7 * @author Doug Lea */ @SuppressWarnings("UnusedDeclaration") public class Fences { private Fences() {} // Non-instantiable /* * The methods of this class are intended to be intrinisified by a * JVM. However, we provide correct but inefficient Java-level * code that simply reads and writes a static volatile * variable. Without JVM support, the consistency effects are * stronger than necessary, and the memory contention effects can * be a serious performance issue. */ private static volatile int theVolatile; /** * Informally: Ensures that a read of the given reference prior to * the invocation of this method occurs before a subsequent use of * the given reference with the effect of reading or writing a * field (or if an array, element) of the referenced object. The * use of this method is sensible only when paired with other * invocations of {@link #orderWrites} and/or {@link * #orderAccesses} for the given reference. For details, see the * class documentation for this class. * * @param ref the reference. If null, this method has no effect. * @return the given ref, to simplify usage */ public static T orderReads(final T ref) { final int ignore = theVolatile; return ref; } /** * Informally: Ensures that a use of the given reference with the * effect of reading or writing a field (or if an array, element) * of the referenced object, prior to the invocation of this * method occur before a subsequent write of the reference. For * details, see the class documentation for this class. * * @param ref the reference. If null, this method has no effect. * @return the given ref, to simplify usage */ public static T orderWrites(final T ref) { theVolatile = 0; return ref; } /** * Informally: Ensures that accesses (reads or writes) using the * given reference prior to the invocation of this method occur * before subsequent accesses. For details, see the class * documentation for this class. * * @param ref the reference. If null, this method has no effect. * @return the given ref, to simplify usage */ public static T orderAccesses(final T ref) { theVolatile = 0; return ref; } /** * Ensures that the object referenced by the given reference * remains strongly reachable (as defined in the {@link * java.lang.ref} package documentation), regardless of any prior * actions of the program that might otherwise cause the object to * become unreachable; thus, the referenced object is not * reclaimable by garbage collection at least until after the * invocation of this method. Invocation of this method does not * itself initiate garbage collection or finalization. * *

See the class-level documentation for further explanation * and usage examples. * * @param ref the reference. If null, this method has no effect. */ public static void reachabilityFence(final Object ref) { if (ref != null) { synchronized (ref) {} } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy