package votorola.g.lang; // Copyright 2005, Brian Goetz and Tim Peierls; 2006-2008, 2012, 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 * specified by its own API documentation.
* *The opposite of ThreadSafe is {@linkplain ThreadRestricted ThreadRestricted}.
* *An unannotated field is assumed to be thread safe only if it is final. For * non-final fields, the safety of access (read or write) is specified by the rules of * the language (particularly by the memory model, chapter 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 possibile read/write caching of field values, by * threads (caches being flushed at synchronization points).
* *An unannotated constructor is assumed to be thread safe.
* *The thread safety of a call, such as object.method(), depends on the object's type * (T), where T = object.getClass(). To determine the thread safety of the call:
* *Or use {@linkplain ThreadSafe.U ThreadSafe.U} to perform these same tests at * runtime.
* *Annotation of a class or interface specifies the default thread safety for its * public methods. Only methods have such defaults, fields, constructors and static * member classes do not. See the rules above for determining * the thread safety of a method call.
* *An unannotated Throwable is assumed to be thread safe.
* * @see ThreadRestricted */ @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 as beign 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( final AnnotatedElement o ) { if( !isCheckingEnabled ) return true; final ThreadSafe safe = o.getAnnotation( ThreadSafe.class ); final ThreadRestricted restricted = o.getAnnotation( ThreadRestricted.class ); if( safe != null ) { 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 type of the object on which the method is called, per * object.getClass(). * @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( final Object o, final String publicMethodName, final Class>... methodParameterTypes ) { try { return isThreadSafe( o.getClass(), o.getClass().getMethod( publicMethodName, methodParameterTypes )); } catch( NoSuchMethodException x ) { throw new IllegalArgumentException( x ); } } } }