Predicate Implementation

During the night and this morning, I worked on implementing the new annotation syntax for predicates. I got to a point where the program reads annotations on classes and method, checks if they contain the @PredicateLink meta-annotation, loads the class file specified, looks for a static method returning a boolean with the given name, and checks that the method takes an Object as first argument, and then an argument with the correct parameter and name (if available) for each value in the annotation. I haven’t extensively tested this yet, but it’s supposed to work both with and without a LocalVariableTable: If a LocalVariableTable is present, then it uses the name and the type to match values in the annotation to parameters in the predicate method; if it’s not available, then it just uses the type and requires that the parameters are in the same order as the values in the annotation. If all that works out, it creates a data structure that contains the predicate class and method name and basically name-value pairs, still in annotation element format. This also includes default values if the value of an element is not specified.

I extended the ScanThreadCheckStrategy to also include XML nodes for the predicate annotations; the data in the annotation is output as a list of name-type-value triples, I don’t yet handle structured data correctly: They should be nested nodes to make parsing easier. Right now, they just get printed as a flat string.

I also haven’t written any code that actually inserts any bytecode into class files. I have written the annotations, predicates, and the method that actually logs the violations, though. The annotations and predicates are able to express the following invariants:

  • Only executed by the event thread
  • Only executed by threads whose name is s
  • Only executed by threads whose name matches the regular expression r
  • Only executed by threads whose group name is s
  • Only executed by threads whose group name matches the regular expression r
  • Only executed by the thread stored in the field specified by class (or class name) c and field name s
  • Only executed by threads whose name is stored in the field specified by class (or class name) c and field name s
  • Only executed by threads whose group name is stored in the field specified by class (or class name) c and field name s

The last three predicates are written using reflection. Unfortunately, I have yet to find a way to actually combine these annotations into compounds. Right now, the executing the following method m() in a thread named “foo” (or “bar”, or any thread at all, actually) will log a violation, because the invariants must be satisfied, i.e. they are combined using “and”: m() may only be run by a thread whose name is both “foo” and “bar”, which is impossible.

@OnlyThreadWithName("foo")
class Test {
@OnlyThreadWithName("bar")
public static void m() {
...
}
}

That’s still a big problem, as is the fact that I can only use an annotation once per annotated element, which is why I put one of the two @OnlyThreadWithName on the class. If only annotations allowed subtyping…

Share

About Mathias

Software development engineer. Principal developer of DrJava. Recent Ph.D. graduate from the Department of Computer Science at Rice University.
This entry was posted in Concurrent Unit Testing. Bookmark the permalink.

Leave a Reply