- A Concurrent Affair - https://www.concurrentaffair.org -

Realize Realized :)

I had to make a few changes, but at least for subclasses of java.lang.Component, there’s now an option to allow any thread before it has been realized, but only the event thread after that.

I replaced the eventThread member of the @ThreadDesc and @OnlyRunBy annotations to an enumeration OnlyRunBy.EVENT\_THREAD with the possible values NO, ONLY_AFTER\_REALIZED and ONLY, in increasingly strict order. If two of them are merged together, the strictest one will be picked, and it is a subtyping error to go from weaker to stronger, e.g. from ONLY\_AFTER\_REALIZED to ONLY, which corresponds exactly to a previous change from false to true.

Lets look at an example program:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
public class ThreadCheckSample2 {
    public void run() {
        JFrame [1] frame = new JFrame [1]("ThreadCheckSample2") {
            @OnlyRunBy(@ThreadDesc(eventThread=
                OnlyRunBy.EVENT\_THREAD.ONLY\_AFTER\_REALIZED))
            protected void processWindowEvent(WindowEvent [2] e) {
                super.processWindowEvent(e);
                if (WindowEvent [2].WINDOW_CLOSING == e.getID()) {
                    System [3].exit(0);
                }
            }
        };
        JPanel [4] panel = new JPanel [4]();
        JButton [5] button = new JButton [5]("Button") {
            @OnlyRunBy(@ThreadDesc(eventThread=
                OnlyRunBy.EVENT\_THREAD.ONLY\_AFTER\_REALIZED))
            public void addActionListener(ActionListener [6] l) {
                super.addActionListener(l);
            }
        };
        button.addActionListener(new ActionListener [6]() {
            public void actionPerformed(ActionEvent [7] e) {
                handleButton();
            }
        });
        panel.add(button);
        frame.getContentPane().add(panel);
        frame.pack();
        frame.setVisible(true);
        handleButton();
        button.addActionListener(new ActionListener [6]() {
            public void actionPerformed(ActionEvent [7] e) {
                System [3].out.println("2nd handler");
            }
        });
    }

    @OnlyRunBy(@ThreadDesc(eventThread=OnlyRunBy.EVENT\_THREAD.ONLY))
    private void handleButton() {
        System [3].out.println("Button was pushed");
    }

    public static void main(String [8][] args) {
        (new ThreadCheckSample2()).run();
    }
}

This generates the thread checker log:

----------------------------------------
Log opened 2006-08-10, 15:09:23 CST (GMT-5)
Thread Violation: OnlyRunBy
        Current thread 'main', id 1, group 'main' did not match
        the event thread
        at sample.threadCheck.ThreadCheckSample2.handleButton (ThreadCheckSample2.java:40)
        at sample.threadCheck.ThreadCheckSample2.run (ThreadCheckSample2.java:30)
        at sample.threadCheck.ThreadCheckSample2.main (ThreadCheckSample2.java:44)

Thread Violation: OnlyRunBy
        Current thread 'main', id 1, group 'main' did not match
        the event thread
        at sample.threadCheck.ThreadCheckSample2$2.addActionListener (ThreadCheckSample2.java:18)
        at sample.threadCheck.ThreadCheckSample2.run (ThreadCheckSample2.java:31)
        at sample.threadCheck.ThreadCheckSample2.main (ThreadCheckSample2.java:44)

The really interesting thing here is that I have annotated the addActionListener method of the button to allow only the event thread after the button has been realized. The first call to addActionListener in line 21 does not generate a violation, but the second call in line 31 does, because the call to JFrame.pack has realized the button.

This is pretty sweet already.

Update

Because determining if a component has been realized requires… a component, I have restricted the ONLY\_AFTER\_REALIZED to non-static methods in subclasses of java.awt.Component. But what should I do with static methods if the ONLY\_AFTER\_REALIZED annotation is on class-level? Right now I throw an exception, but I don’t think that’s right. But do I want to tighten the rules (ONLY) or relax them (NO)? Right now, I’m thinking I’ll print out a warning but then relax the annotation to NO.

I ran the DrJava unit tests again, and because I fixed a bug, this time I got a lot of reports of the same problem. I may want to think about removing duplicates and the ability to suppress certain reports.

[9] [10]Share [11]