package waymaker.gen; // Copyright © 2006 Michael Allan. Licence MIT. import java.lang.annotation.*; /** Warns that access to a field, constructor or method is restricted to a particular thread, * or to a thread that holds a particular lock, or meets some other particular constraint. * The opposite of ThreadRestricted is {@linkplain ThreadSafe ThreadSafe}. * *

The restriction applies to a field, constructor or method. It does not necessarily * apply to any associated object that is read from the field, or created by the * constructor, or returned by the method. The associated object's thread safety is * normally documented by its own type API. However, if the type API documents no * specific restriction, then the object assumes the restriction of the field, * constructor or method whence it came. [See also @{@linkplain Warning * Warning}("thread restricted object") and @{@linkplain Warning Warning}( "thread * restricted elements")].

* *

Restriction for constructors and methods defaults to type

* *

Any non-private constructor or method that lacks a ThreadRestricted or ThreadSafe annotation is * instead bound by the restriction of its declaring type (class or interface). See the step-by-step rules in this case. The effect is * equivalent to repeating the type annotation on the constructor or method: * *

  *     @ThreadRestricted("type restriction")
* *

The default restriction of the type may be qualified by a further restriction, such that both * apply. The following forms of annotation are therefore equivalent:

* *
  *     @ThreadRestricted("further restriction")
  *     @ThreadRestricted("type restriction, further restriction")
* *

Restriction to a known thread

* *

The restriction may be to a known instance of a thread. For example, most Swing code is * restricted to the AWT event dispatch thread. An appropriate annotation would be:

* *
  *     @ThreadRestricted("AWT event dispatch")
* *

As well, a constructor or method might implement an internal, runtime test of * compliance:

* *
  *     assert java.awt.EventQueue.isDispatchThread();
* *

Restriction to threads holding a particular lock

* *

The restriction may specify a particular synchronization lock. For example:

* *
  *     @ThreadRestricted("holds Class.this")
  *     @ThreadRestricted("holds object")
  *     @ThreadRestricted("holds lock")
* *

These specify that the thread must hold the monitor lock of the containing instance * (this), or of some other object; or that it must hold a particular {@linkplain * java.util.concurrent.locks.ReentrantLock ReentrantLock}. As well, the restricted code * may internally test compliance at runtime:

* *
  *     assert Thread.holdsLock( Class.this );
  *     assert Thread.holdsLock( object );
  *     assert lock.isHeldByCurrentThread();
* *

Restriction to touch-synchronizing threads

* *

The restriction may specify that threads must touch-synchronize. For example:

* *
  *     @ThreadRestricted("touch")
  *     @ThreadRestricted("touch object")
  *     @ThreadRestricted("touch lock")
  *     @ThreadRestricted("touch Class.this")
* *

Access is superficially thread-safe, but modifications to state variables are not * guaranteed visible across threads unless the threads touch-synchronize on a common * lock. The form of touch-synchronization depends on whether the thread is reading * from state, or writing to it. If reading, the thread must grab the lock at some point * before reading in order to invalidate its local memory cache. The thread * need not continue to hold the lock while reading, but may release it beforehand.

* *

If writing to state, the thread must release the lock at some point after * writing in order to flush its local memory cache. The thread need not hold the lock * at time of writing, but may subsequently grab it and release it. Only after the lock * is released are the state changes guaranteed to reach main memory and become readable * by other threads that touch-synchronize.

* *

If the thread is both reading and writing, then it must touch-synchronize twice, grabbing the * lock before reading, and releasing it after writing. It need not hold the lock in the meantime * unless it wants exclusive access, but may instead grab and immediately release the lock once * beforehand, then once again afterward. In the case of a monitor lock, each such immediate * grab-and-release (each touch per se) is formed as an empty synchronized block.

* *

If no particular lock is specified, then any lock will suffice. Visibility is guaranteed * only among threads that touch-synchronize on the same lock. This guarantee rests on the * Java memory model, in particular on the rule that * an “unlock action on monitor m synchronizes-with all subsequent lock actions on m” * and thereby happens-before those actions. * (See also this answer on Stack Exchange.)

* *

Restriction to a thread synchronized by starting

* *

The restriction may be to a thread that was synchronized by starting it from a known instance of * another thread:

* *
  *     @ThreadRestricted("StartSync from thread")
* *

Restriction unspecified

* *

The restriction may be left unspecified. This is the default value. The following * forms of annotation are therefore equivalent:

* *
  *     @ThreadRestricted
  *     @ThreadRestricted("unspecified")
  *     no annotation, neither @ThreadRestricted nor @ThreadSafe
* *

An unspecified restriction simply means “not thread safe” without specifying a particular means * of synchronization. Any general means will suffice. The choice may vary from instance to instance, * with the decision falling to the code that accesses each instance.

* *

A common pattern is a constructor or factory method annotated as thread safe, while other members * default to unsafe. This means that any thread may safely construct an instance of the type, and any * thread may first access it. No synchronization is required between initial construction and access * (A1). Only between A1 and each subsequent access (A2, A3, ...) is synchronization required, the * means of which is left to the programmer.

* * @see ThreadSafe */ @Documented @Retention(RetentionPolicy.SOURCE) // till more retention needed @Target({ ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD, ElementType.TYPE }) public @interface ThreadRestricted { /** Details of the thread restriction. */ public String value() default "unspecified"; }