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.
  *
  * <p>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.</p>
  *
  * <p>The opposite of ThreadSafe is {@linkplain ThreadRestricted ThreadRestricted}.</p>
  *
  * <h3>Applied to fields</h3>
  *
  * <p>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).</p>
  *
  * <h3>Applied to constructors</h3>
  *
  * <p>An unannotated constructor is assumed to be thread safe.</p>
  *
  * <h3 id='method-test'>Applied to methods</h3>
  *
  * <p>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:</p>
  *
  * <ol>
  *
  *     <li>Look at the API documentation (javadoc page) of type T.</li>
  *
  *     <li>Find the method declaration on that page.  If the method is not found on that
  *     page (it is inherited, and not overridden), then look at the javadoc page of the
  *     supertype (or its supertype, and so on, until you find the method).  Refer to the
  *     thread-safety annotation of the method.  <br/>Or, if the method is
  *     unannotated:</li>
  *
  *     <li>Refer to the annotation of the method's <em>declaring</em> type (top of that
  *     same page). <br/>Or, if that type is unannotated:</li>
  *
  *     <li>Return to the original, javadoc page of type T (if you had left it), and refer
  *     to the annotation of type T. <br/>Failing that, unless you know otherwise:</li>
  *
  *     <li>Assume the method is {@linkplain ThreadRestricted ThreadRestricted}.</li>
  *
  *     </ol>
  *
  * <p>Or use {@linkplain ThreadSafe.U ThreadSafe.U} to perform these same tests at
  * runtime.</p>
  *
  * <h3>Applied to types</h3>
  *
  * <p>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 <a href='#method-test'>rules above</a> for determining
  * the thread safety of a method call.</p>
  *
  * <p>An unannotated Throwable is assumed to be thread safe.</p>
  *
  *     @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).
          *
          * <p>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.</p>
          *
          *     @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 <a href='ThreadSafe.html#method-test'>effectively
          * annotated thread safe</a>.
          *
          *     @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 <a
          * href='ThreadSafe.html#method-test'>effectively annotated thread safe</a>.
          *
          *     @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 ); }
        }


    }



}