@Documented @Retention(value=RUNTIME) @Target(value=TYPE) public @interface RegionLock
To declare more than one lock for a class use the RegionLocks
annotation. It is a modeling error for a class to have both a
RegionLocks and a RegionLock annotation.
The named lock is a Java object. If the object's type implements
java.util.concurrent.locks.Lock then the lock object must be used
according to the protocol of the Lock interface. Otherwise, the
object must be used as a Java intrinsic lock, i.e., with synchronized
blocks.
lockExpression
when the state specified by the regionName is read or written, unless
regionName is static and the
access occurs within the class initializer of the class that declares that
state; or
regionName is non-static and
the access occurs within a constructor of the class that declares that
state or one of its subclasses, and the object created by the constructor
is only accessed by the thread that invoked the constructor.
The locking policy
stated by a RegionLock annotation likely associated with a
higher-level invariant. This annotation does not, however, elicit the
higher-level invariant from the programmer.
SimpleLock, that indicates that synchronizing
on the instance protects the all of the instance's state.
@RegionLock("SimpleLock is this protects Instance")
class Simple { ... }
A locking policy, named ObserverLock, that indicates that
synchronizing on the field observerLock (which must be declared to be
final) protects the contents of the set observers.
@Region("private ObserverRegion")
@RegionLock("ObserverLock is observerLock protects ObserverRegion")
class Observer {
private final Object observerLock = new Object();
...
@UniqueInRegion("ObserverRegion")
private final Set<Callback> observers = new HashSet<Callback>();
...
private void add(Callback c) {
synchronized (observerLock) { observers.add(c); }
}
...
}
A locking policy, named StateLock, that indicates that locking on the
java.util.concurrent.Lock stateLock protects the two
long fields use to represent the position of the object.
@Region("private AircraftState")
@RegionLock("StateLock is stateLock protects AircraftState")
public class Aircraft {
private final Lock stateLock = new ReentrantLock();
...
@InRegion("AircraftState")
private long x, y;
...
public void setPosition(long x, long y) {
stateLock.lock();
try {
this.x = x;
this.y = y;
} finally {
stateLock.unlock();
}
}
...
}
The same lock object may be declared to be multiple locks (including to be
a PolicyLock):
@Regions({
@Region("protected Color"),
@Region("protected Position"),
@Region("protected Label")
})
@RegionLocks({
@RegionLock("L1 is this protects Color"),
@RegionLock("L2 is this protects Position"),
@RegionLock("L3 is lockField protects Label")
})
@PolicyLocks({
@PolicyLock("P1 is this"),
@PolicyLock("L1 is lockField")
})
public class Sprite {
protected final Object lockField = new Object();
...
}
Constructor annotation to support locking policies: To support the
RegionLock annotation, a Unique or Borrowed
annotation is needed on each constructor to assure that the object being
constructed is confined to the thread that invoked new. A second less
common approach, using effects, is described below.
Annotating @Unique("return") on a constructor is defined to
be equivalent to annotating @Borrowed("this"). Either of
these annotations indicate that the object being constructed is not aliased
during construction, which implies that the reference "returned" by the
new expression that invokes the constructor is unique. Which
annotation is preferred, @Unique("return") or
@Borrowed("this"), is a matter of programmer preference.
@RegionLock("Lock is this protects Instance")
public class Example {
int x = 1;
int y;
@Unique("return")
public Example(int y) {
this.y = y;
}
...
}
Alternatively, you could use @Borrowed("this").
@RegionLock("Lock is this protects Instance")
public class Example {
int x = 1;
int y;
@Borrowed("this")
public Example(int y) {
this.y = y;
}
...
}
It is also possible to support the RegionLock assertion with effects
(Starts and RegionEffects) annotations on a constructor
instead of using Unique or Borrowed. This is useful if the
constructor aliases the receiver into a field within the newly constructed
object. This situation is uncommon in real-world Java code. In the example
below if an explicit lock object is not provided to the constructor then
this is used and, hence, aliased into the field lock. In this
code @Unique("return") cannot be verified so the effects
annotations are used on the constructor instead.
@Region("private Y")
@RegionLock("Lock is lock protects Y")
public class Example {
private final Object lock;
@InRegion("Y")
private int y;
@Starts("nothing")
@RegionEffects("none")
public Example(int y, Object lock) {
this.y = y;
if (lock == null)
this.lock = this;
else
this.lock = lock;
}
public int getY() {
synchronized (lock) {
return y;
}
}
public void setY(int value) {
synchronized (lock) {
y = value;
}
}
}
The scoped promise Promise can be used if the constructor is implicit
(i.e., generated by the compiler). It has the ability to place promises on
implicit and explicit constructors.
@RegionLock("Lock is this protects Instance")
@Promise("@Unique(return) for new(**)")
public class Example {
int x = 1;
int y = 1;
...
}
@annotate tag.
/**
* @annotate RegionLock("SimpleLock is this protects Instance")
*/
class Simple { ... }
PolicyLock,
RegionLocks,
RequiresLock,
ReturnsLock| Modifier and Type | Required Element and Description |
|---|---|
String |
value
The value of this attribute must conform to the following grammar (in Augmented Backus–Naur
Form):
|
public abstract String value
value = IDENTIFIER "is" lockExpression "protects" regionName
lockExpression = simpleLockExpression / qualifiedLockExpression
simpleLockExpression =
"class" / ; the Class object referenced by the "class" pseudo-field of the annotated class
"this" / ; the instance itself
["this" "."] IDENTIFIER ; the object referenced by the named field
qualifiedLockExpression =
namedType "." "CLASS" / ; the Class object referenced by the "class" pseudo-field of a named class
namedType "." "THIS" / ; a named enclosing instance
namedType "." IDENTIFIER / ; a named static field
namedType "." THIS "." IDENTIFIER ; a named field of an enclosing instance
namedType = IDENTIFIER *("." IDENTIFIER)
regionName = IDENTIFIER
IDENTIFIER = Legal Java Identifier
Copyright © 2012 Surelogic, Inc.. All Rights Reserved.