New Annotatation Format

I must admit I haven’t been able to do as much as I had hoped during the last two days, but I did experiment with a new, more flexible format for the annotations. It’s a bit more verbose, but it essentially gives me what I had wanted (see end of this posting).

The preferred (and most future-proof) way of specifying threads now uses the value element, an array of @ThreadDesc annotations. The choice of value as name has the advantage that the programmer can drop the value= part if only the value element is assigned to. The @ThreadDesc annotation now contains the four elements name, id, group and eventThread (notice singular form on the first three), but only one of the four may be used at the same time, i.e. @ThreadDesc(name="foo") and @ThreadDesc(id=5) are legal, but @ThreadDesc(name="foo",id=5) is not.

The old elements of @NotRunBy and @OnlyRunBy, i.e. threadNames, threadIds, threadGroups and eventThread are still available and can be mixed with the new value element in any way, as long as anything regarding the event thread is not specified more than once, like in the following (illegal) annotation: @OnlyRunBy(eventThread=true, value=@ThreadDesc(eventThread=true)).

Here are some examples of the new style:

1
2
3
4
5
@NotRunBy({@ThreadDesc(name="bar"), @ThreadDesc(id=1)})
@NotRunBy({@ThreadDesc(name="main"), @ThreadDesc(name="fum")})
@OnlyRunBy(@ThreadDesc(eventThread=true))
@OnlyRunBy(value={@ThreadDesc(name="main3"), @ThreadDesc(group="foo")},
           threadGroups={"bar"}, threadIds={3, 4})

The major advantage is that I can add additional elements to the @ThreadDesc annotation, such as conditionals as discussed previously.

I also changed the way class-level annotations affect methods and floowed Corky’s advice: An annotation on a class, from now on only influences methods that were defined by that class, or are going to be defined in subclasses. Let’s look at a quick example:

1
2
3
4
5
6
abstract class Base {
    @OnlyRunBy(eventThread=true)
    public abstract void run();
    public abstract void doSomething();
}
public boolean equals(Object other) { ... }

In this class only the run method is annotated (and all methods in subclasses); >doSomething is not annotated.

Let’s look at a subclass:

1
2
3
4
5
6
@OnlyRunBy(eventThread=true)
class Sub extends Base {
    public void run() { ... }
    public void doSomething() { ... }
    public abstract void doSomethingElse() { ... }
}

Here, we have a class-level annotation: In my initial version, this annotation would have applied to all three methods in the Sub class; however, that caused a lot of warnings if subtyping was taken seriously. Now the annotation only applies to the doSomethingElse method, because both run and doSomething were already defined in the Base class. The Sub.run method nonetheless is annotated to allow only the event thread to run since Base.run is annotated with @OnlyRunBy(eventThread=true) and that applies to all subclasses as well.

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