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.
  * <p>
  *     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>
  * <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 formally indicated by its own API.
  *     </p>
  * <p>
  *     The opposite of ThreadSafe is {@linkplain ThreadRestricted ThreadRestricted}.
  *     </p>
  *
  * <h3>Fields</h3>
  * <p>
  *     An unannotated field is assumed to be thread safe only if it is final.
  *     </p>
  * <p>
  *     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.
  *     </p>
  *
  * <h3>Constructors</h3>
  * <p>
  *     An unannotated constructor is assumed to be thread safe.
  *     </p>
  *
  * <h3 id='Methods'>Methods (and Types)</h3>
  * <p>
  *     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.
  *     </p>
  * <p>
  *     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:
  *     </p>
  * <ol id='method-test'>
  *     <li>
  *         Look at the API of the runtime type (e.g. its javadoc page).
  *         </li>
  *     <li>
  *         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.)
  *         <br/>Or, if the method is unannotated:
  *         </li>
  *     <li>
  *         Look at the annotation of the method's <em>declaring</em> type
  *         (top of that same page).
  *         <br/>Or, if that type is unannotated:
  *         </li>
  *     <li>
  *         Look at the annotation of the method's <em>runtime</em> type.
  *         (This will take you back to the original page, if you left it.)
  *         <br/>Failing that, unless you know otherwise:
  *         </li>
  *     <li>
  *         Assume the method is <em>not</em> thread safe.
  *         </li>
  *     </ol>
  * <p>
  *     Or use {@linkplain ThreadSafe.U ThreadSafe.U} to perform
  *     these same tests at runtime.
  *     </p>
  */
    @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 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
          * <a href='ThreadSafe.html#method-test'>effectively annotated thread safe</a>.
          *
          *     @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
          * <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(

            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
        }


    }



}