Ok, during the last day and a bit, I changed my completely working implementation of passing method arguments. Before, there was one argument in the predicate method for each argument in the method that was annotated. That limited the applicability of the annotations. Now I pass an Object[]
array that can be empty, contain one element, or however many. The coolest thing is that it automatically takes care of the subtyping problem.
Here are rewritten predicates and annotations from the last post:
public class TCSample14 {
public static class CheckSynchronized {
public static boolean check(
Object thisObject, Object args[], int value) {
if (value>=args.length) return false;
return ThreadCheckPredicates.checkMonitorOwned(args[value]);
}
public static boolean checkNot(
Object thisObject, Object args[], int value) {
if (value>=args.length) return false;
return !ThreadCheckPredicates.checkMonitorOwned(args[value]);
}
}
@PredicateLink(
value=CheckSynchronized.class,
arguments=true)
public static interface OnlySynchronized {
int value() default 0;
}
@PredicateLink(
value=CheckSynchronized.class,
method="checkNot",
arguments=true)
public static interface NotSynchronized {
int value() default 0;
}
public static void main(String[] args) {
TCSample14 o = new TCSample14();
System.out.println("main!");
o.succeeds();
o.fails();
System.out.println("end main!");
}
// these invariants all succeed
void succeeds() {
String o1 = "foo";
String o2 = "bar";
notUnary(o1);
synchronized(o1) {
unary(o1);
binary1st(o1,o2);
notBinary2nd(o1,o2);
}
synchronized(o2) {
notBinary1st(o1,o2);
binary2nd(o1,o2);
}
}
@OnlySynchronized(0)
void unary(Object o1) {
System.out.println("unary!");
}
@OnlySynchronized(0)
void binary1st(Object o1, Object o2) {
System.out.println("binary1st");
}
@OnlySynchronized(1)
void binary2nd(Object o1, Object o2) {
System.out.println("binary2nd");
}
// these invariants all fail
private void fails() {
String o1 = "foo";
String o2 = "bar";
unary(o1);
synchronized(o1) {
notUnary(o1);
notBinary1st(o1,o2);
binary2nd(o1,o2);
}
synchronized(o2) {
binary1st(o1,o2);
notBinary2nd(o1,o2);
}
}
@NotSynchronized(0)
void notUnary(Object o1) {
System.out.println("notUnary!");
}
@NotSynchronized(0)
void notBinary1st(Object o1, Object o2) {
System.out.println("notBinary1st");
}
@NotSynchronized(1)
void notBinary2nd(Object o1, Object o2) {
System.out.println("notBinary2nd");
}
}
Now I think this is pretty cool. It even auto-boxes primitive types to their boxed types. Now I’m just running some more tests, and then it’s time to sleep.
PS: Whatever happened to Beer Bike today?