package textbender.g.lang; // Copyright 2005, Brian Goetz and Tim Peierls; 2006-2007, Michael Allan. Released under the Creative Commons Attribution License (http://creativecommons.org/licenses/by/2.5). Official home: http://www.jcip.net. Any republication or derived work distributed in source code form must include this copyright and license notice. import java.lang.annotation.*; import java.lang.reflect.*; /** Indicates thread safety of fields, constructors and methods. *

* Access to thread-safe fields, and calls to thread-safe constructors * and methods, will never put the program into an invalid state, * regardless of how the runtime interleaves those actions, * and without requiring any additional synchronization * or coordination on the part of the caller. *

*

* The indication of thread safety applies to a field, constructor * or method. It never applies to an object read from the field, * or created by the constructor, or returned by the method. * Thread-safe fields, constructors and methods are not constrained * to dispense only thread-safe objects. Each object's own thread safety * is formally indicated by its own API. *

*

* The opposite of ThreadSafe is {@linkplain ThreadRestricted ThreadRestricted}. *

* *

Fields

*

* An unannotated field is assumed to be thread safe only if it is final. *

*

* Note that thread safety of access (read or write) to non-final fields * is fundamentally limited by the rules of the language, * particularly by its memory model (specification, 17). * Strictly speaking, only certain types of volatile field * (and their equivalents in java.util.concurrent.{@linkplain java.util.concurrent.atomic atomic}) * can be thread safe. All others are subject * to read/write caching of their values. Caches are only flushed at synchronization points. *

* *

Constructors

*

* An unannotated constructor is assumed to be thread safe. *

* *

Methods (and Types)

*

* Annotation of a type (class or interface) * specifies the default thread safety of its public methods. * An unannotated public method aquires the annotation * of its declaring type, or, failing that, its runtime object's type. * Only methods have such defaults; not fields or contructors. *

*

* A method's thread safety depends on the runtime type of the object * on which it is called. To determine a method's thread safety: *

*
    *
  1. * Look at the API of the runtime type (e.g. its javadoc page). *
  2. *
  3. * Find the method and its thread-safety or thread-restriction annotation. * (The search may take you to a supertype page, if the method is inherited unchanged.) *
    Or, if the method is unannotated: *
  4. *
  5. * Look at the annotation of the method's declaring type * (top of that same page). *
    Or, if that type is unannotated: *
  6. *
  7. * Look at the annotation of the method's runtime type. * (This will take you back to the original page, if you left it.) *
    Failing that, unless you know otherwise: *
  8. *
  9. * Assume the method is not thread safe. *
  10. *
*

* Or use {@linkplain ThreadSafe.U ThreadSafe.U} to perform * these same tests at runtime. *

*/ @Documented @Retention( RetentionPolicy.RUNTIME ) @Target({ ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD, ElementType.TYPE }) public @interface ThreadSafe { // ==================================================================================== /** Thread-safety utilities. Includes utility methods for accessors * to test the safety of code, prior to accessing it. * For tests that code can use, after access, * see {@linkplain ThreadRestricted ThreadRestricted}. */ public @ThreadSafe static final class U { private U() {} /** Returns true if thread-safety checks are actually performed (normal situation); * false if they were disabled in this classloader's runtime. * This flag affects the various thread-safety tests; * if checking is disabled, they will always test positive (thread safe). *

* Checking may be disabled by code that lacks permission * to read annotations. For instance, an unsigned applet * may disable checking to avoid having AccessControlExceptions * thrown by underlying library code that makes use of these tests. *

* * @see #disableChecking() */ public static boolean isCheckingEnabled() { return isCheckingEnabled; } private static volatile boolean isCheckingEnabled = true; public static void disableChecking() { isCheckingEnabled = false; } /** Tests whether the object is annotated thread safe. * Checks both {@linkplain ThreadSafe ThreadSafe} * and {@linkplain ThreadRestricted ThreadRestricted}. * * @return TRUE if {@linkplain #isCheckingEnabled() checking is disabled}, * or annotated thread safe; FALSE if annotated thread restricted; * or null if none of the above * * @throws AssertionError if assertions enabled, and two annotations contradict */ private static Boolean isThreadSafe( AnnotatedElement o ) { if( !isCheckingEnabled ) return true; final ThreadSafe safe = o.getAnnotation( ThreadSafe.class ); final ThreadRestricted restricted = o.getAnnotation( ThreadRestricted.class ); if( safe != null ) { // assert !safe.value() || restricted == null : "either thread safe or restricted, not both"; assert restricted == null : "either thread safe or restricted, not both"; return true; } else if( restricted != null ) return false; return null; } /** Tests whether a method is * effectively annotated thread safe. * * @param objectType actual (runtime) type of the object * on which the method is called * @param method of the object (declared or inherited) * * @return true iff the method is effectively annotated thread safe; * or if {@linkplain #isCheckingEnabled() checking is disabled} */ public static boolean isThreadSafe( final Class objectType, final Method method ) { // if( !isCheckingEnabled ) return true; //// redundant, per first call to isThreadSafe() Boolean safe = isThreadSafe( method ); if( safe != null ) return safe; if( !Modifier.isPublic( method.getModifiers() )) return false; safe = isThreadSafe( method.getDeclaringClass() ); if( safe != null ) return safe; safe = isThreadSafe( objectType ); if( safe != null ) return safe; return false; } /** Tests whether a public method is * effectively annotated thread safe. * * @return true iff the method is effectively annotated thread safe; * or if {@linkplain #isCheckingEnabled() checking is disabled} * * @throws IllegalArgumentException if there is no such public method, * per Class.{@linkplain Class#getMethod getMethod}() */ public static boolean isThreadSafe( Object o, String publicMethodName, Class... methodParameterTypes ) { try { return isThreadSafe ( o.getClass(), o.getClass().getMethod( publicMethodName, methodParameterTypes ) ); } catch( NoSuchMethodException x ) { throw new IllegalArgumentException( x ); } // not expected } } }