KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com4j > ComThread


1 package com4j;
2
3 import java.util.List JavaDoc;
4 import java.util.ArrayList JavaDoc;
5
6
7 /**
8  * Thread managed by com4j.
9  *
10  * <p>
11  * For each user thread that works with COM objects,
12  * one {@link ComThread} is created to manage those objects.
13  *
14  * @author Kohsuke Kawaguchi (kk@kohsuke.org)
15  */

16 final class ComThread extends Thread JavaDoc {
17
18     /**
19      * Used to associate a {@link ComThread} for every thread.
20      */

21     private static final ThreadLocal JavaDoc<ComThread> map = new ThreadLocal JavaDoc<ComThread>() {
22         public ComThread initialValue() {
23             if( isComThread() )
24                 return (ComThread)Thread.currentThread();
25             else
26                 return new ComThread(Thread.currentThread());
27         }
28     };
29
30     /**
31      * Gets the {@link ComThread} associated with the current thread.
32      */

33     static ComThread get() {
34         return map.get();
35     }
36
37
38
39     private ComThread(Thread JavaDoc peer) {
40         super("ComThread for "+peer.getName());
41         this.peer = peer;
42         setDaemon(true); // we don't want to block the JVM from exiting
43
start();
44     }
45
46     /**
47      * The peer thread.
48      */

49     private final Thread JavaDoc peer;
50
51     /**
52      * {@link Wrapper}s that are no longer referenced from anybody else
53      * are kept in this linked list, so that this thread can dispose them.
54      */

55     private Wrapper freeList;
56
57     /**
58      * Tasks that need to be processed.
59      */

60     private Task<?> taskList;
61
62     /**
63      * Number of {@link Wrapper} objects that this thread manages.
64      */

65     private int liveObjects = 0;
66
67     /**
68      * Listeners attached to this thread.
69      */

70     private final List JavaDoc<ComObjectListener> listeners = new ArrayList JavaDoc<ComObjectListener>();
71
72     /**
73      * Returns true if this thread can exit.
74      */

75     private boolean canExit() {
76         return !peer.isAlive() && liveObjects==0;
77     }
78
79     public synchronized void run() {
80         Native.coInitialize();
81
82         // TODO: we need to run Windows message pump
83
while(!canExit()) {
84             try {
85                 wait(1000);
86             } catch (InterruptedException JavaDoc e) {}
87
88             // dispose unused objects if any
89
while(freeList!=null) {
90                 if(freeList.dispose0())
91                     liveObjects--;
92                 freeList = freeList.next;
93             }
94
95             // do any scheduled tasks that need to be done
96
while(taskList!=null) {
97                 Task<?> task = taskList;
98                 taskList = task.next;
99                 task.invoke();
100             }
101         }
102
103         Native.coUninitialize();
104     }
105
106     /**
107      * Adds the given object to the free list
108      */

109     synchronized void addToFreeList(Wrapper wrapper) {
110         assert wrapper.next==null;
111         wrapper.next = freeList;
112         freeList = wrapper;
113     }
114
115     /**
116      * Executes a {link Task} in a {@link ComThread}
117      * and returns its result.
118      */

119     public <T> T execute(Task<T> task) {
120         synchronized(task) {
121             synchronized(this) {
122                 // add it to the link
123
task.next = taskList;
124                 taskList = task;
125
126                 // invoke the execution
127
notify();
128             }
129             // wait for the completion
130
try {
131                 task.wait();
132             } catch (InterruptedException JavaDoc e) {}
133
134             if(task.exception!=null) {
135                 RuntimeException JavaDoc e = task.exception;
136                 task.exception = null;
137                 e.fillInStackTrace();
138                 throw e;
139             } else {
140                 T r = task.result;
141                 task.result = null;
142                 return r;
143             }
144         }
145     }
146
147     public synchronized void addLiveObject( Com4jObject r ) {
148         liveObjects++;
149         if(!listeners.isEmpty()) {
150             for( int i=listeners.size()-1; i>=0; i-- )
151                 listeners.get(i).onNewObject(r);
152         }
153     }
154
155     /**
156      * Checks if the current thread is a COM thread.
157      */

158     static boolean isComThread() {
159         return Thread.currentThread() instanceof ComThread;
160     }
161
162     public void addListener(ComObjectListener listener) {
163         if(listener==null)
164             throw new IllegalArgumentException JavaDoc("listener is null");
165         if(listeners.contains(listener))
166             throw new IllegalArgumentException JavaDoc("can't register the same listener twice");
167         listeners.add(listener);
168     }
169
170     public void removeListener(ComObjectListener listener) {
171         if(!listeners.remove(listener))
172             throw new IllegalArgumentException JavaDoc("listener isn't registered");
173     }
174 }
175
Popular Tags