KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > bsf > debug > util > ThreadCell


1 /*
2  * The Apache Software License, Version 1.1
3  *
4  * Copyright (c) 2002 The Apache Software Foundation. All rights
5  * reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  *
14  * 2. Redistributions in binary form must reproduce the above copyright
15  * notice, this list of conditions and the following disclaimer in
16  * the documentation and/or other materials provided with the
17  * distribution.
18  *
19  * 3. The end-user documentation included with the redistribution, if
20  * any, must include the following acknowlegement:
21  * "This product includes software developed by the
22  * Apache Software Foundation (http://www.apache.org/)."
23  * Alternately, this acknowlegement may appear in the software itself,
24  * if and wherever such third-party acknowlegements normally appear.
25  *
26  * 4. The names "Apache BSF", "Apache", and "Apache Software Foundation"
27  * must not be used to endorse or promote products derived from
28  * this software without prior written permission. For written
29  * permission, please contact apache@apache.org.
30  *
31  * 5. Products derived from this software may not be called "Apache"
32  * nor may "Apache" appear in their names without prior written
33  * permission of the Apache Group.
34  *
35  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
36  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
37  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
38  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
39  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
42  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
43  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
44  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
45  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
46  * SUCH DAMAGE.
47  * ====================================================================
48  *
49  * This software consists of voluntary contributions made by many individuals
50  * on behalf of the Apache Software Foundation and was originally created by
51  * Sanjiva Weerawarana and others at International Business Machines
52  * Corporation. For more information on the Apache Software Foundation,
53  * please see <http://www.apache.org/>.
54  */

55
56 package org.apache.bsf.debug.util;
57
58 import org.apache.bsf.debug.util.DebugLog;
59
60 public class ThreadCell implements Runnable JavaDoc {
61
62     static private int ThreadIdGenerator = 0;
63     static boolean isServer;
64
65     static {
66         ThreadIdGenerator = (int)System.currentTimeMillis();
67         isServer = Boolean.getBoolean("org.apache.bsf.isServer");
68     }
69
70     Thread JavaDoc m_thread;
71     Object JavaDoc m_streamLock;
72     Object JavaDoc m_waitLock;
73     ResultCell m_stack;
74     int m_thid;
75     boolean m_loopback;
76     SocketConnection m_con;
77     boolean m_started;
78
79     /**
80      * This creates a distributed thread upon an outgoing
81      * invocation, whose first local thread is the one
82      * passed as parameter.
83      * Notice that the thId is generated either on the
84      * client or the server and distinguised through
85      * negative or positive numbers.
86      * IMPORTANT:
87      * This is a very simple scheme that allows only for
88      * one server and one client to dialog.
89      */

90     ThreadCell(SocketConnection con, Thread JavaDoc thread) {
91
92         m_streamLock = new Object JavaDoc();
93         m_waitLock = new Object JavaDoc();
94
95         m_con = con;
96         if (isServer)
97             m_thid = ++ThreadIdGenerator;
98         else
99             m_thid = --ThreadIdGenerator;
100
101         m_thread = thread;
102     }
103
104     /**
105      * This is to create a proxy of an existing distributed
106      * thread... it is called when an incoming invocation
107      * arrives under an unknown thid...
108      * A thread will be created later and provided to the
109      * ThreadCell::start method. This will be the thread
110      * carrying on the incoming call.
111      * See below.
112      */

113
114     ThreadCell(SocketConnection con, int thId) {
115         m_streamLock = new Object JavaDoc();
116         m_waitLock = new Object JavaDoc();
117         m_thread = new Thread JavaDoc(this, "BSF Thread " + thId);
118
119         m_started = false;
120         m_thread.start();
121         synchronized (m_waitLock) {
122             while (!m_started) {
123                 try {
124                     m_waitLock.wait(1);
125                 } catch (InterruptedException JavaDoc ex) {
126                 }
127             }
128         }
129         m_con = con;
130         m_thid = thId;
131         m_stack = null;
132     }
133
134     int getThId() {
135         return m_thid;
136     }
137
138     Thread JavaDoc getThread() {
139         return m_thread;
140     }
141
142     /**
143      * Simply allows to switch to this thread...
144      * it automatically executes the top invocation
145      * on the stack.
146      */

147     public synchronized void run() {
148             boolean loop = true;
149
150             m_started = true;
151             while (loop) {
152                 try {
153                     this.wait();
154                 } catch (InterruptedException JavaDoc ex) {
155                     loop = false;
156                     continue;
157                 }
158                 if (m_loopback) {
159                     // this thread has been looping back..
160
// the ResultCell of the loopback invocation has already
161
// been pushed on the stack, see loopbackNotify(ResultCell)
162
m_loopback = false;
163                     execTopStack();
164                     
165                     try {
166                         popInvocation(null,true);
167                     } catch (Exception JavaDoc ex) {
168                         // just ignore top-level exceptions...
169
}
170                     continue;
171                 }
172             }
173     }
174
175     /**
176      * Utility method for executing the top invocation
177      * on the stack. The top frame is not popped, it
178      * is left on the stack once invoked.
179      *
180      * Exception Management:
181      * If any exception occurs during the invoke it is
182      * caught and put in the result cell. It will therefore
183      * be sent back to the loopback invoker.
184      *
185      */

186     private synchronized void execTopStack() {
187         try {
188             m_con.dispatchInvocation(m_stack);
189         } catch (Exception JavaDoc ex) {
190             DebugLog.stderrPrintln("\nException Raised in loopback...", DebugLog.BSF_LOG_L3);
191             m_stack.setException(ex);
192         }
193         // send the result if any,
194
// or the exception if any occured.
195
m_stack.sendResult();
196     }
197
198     /**
199      * Wait for completion of an outgoing invocation.
200      * While waiting, it is possible to have a loopback
201      * condition, in which case this thread is reused to
202      * carry on the incoming invocation.
203      */

204     public synchronized void waitOnCompletion(ResultCell rcell)
205         throws Exception JavaDoc {
206
207         if (rcell != m_stack)
208             throw new Error JavaDoc("About to wait for completion, but not on the top of the stack...");
209
210                 // send the invocation for the top of the stack.
211
rcell.sendInvocation();
212                 
213                 // then suspend until done...
214
// see in the while, the loopback case...
215
while (!rcell.done) {
216                     try {
217                         this.wait();
218                     } catch (InterruptedException JavaDoc ex) {
219                     }
220                     // we have been awaken for one of two reasons:
221
// - loopback
222
// - the invocation we waited on completed
223

224                     if (m_loopback) {
225                         // this thread has been looping back..
226
// the ResultCell of the loopback invocation has
227
// already been pushed on the stack, see
228
// loopbackNotify(ResultCell)
229
m_loopback = false;
230                         
231                         // execute the loopback invocation,
232
// if any exception occurs, it is caught and sent back.
233
// it never percolates back up here.
234
execTopStack();
235                         
236                         // pop the loopback that just completed.
237
// ignore any exception because we are in a loopback,
238
// it has been sent over the wire already.
239
popInvocation(m_stack, true);
240                         continue;
241                     }
242                     if (m_stack.done) break;
243         }
244         popInvocation(rcell, false);
245     }
246
247     public synchronized void completionNotify(ResultCell rcell) {
248             rcell.done = true;
249             if (rcell.disconnected) m_thread.interrupt();
250             this.notify();
251     }
252
253     public synchronized void pushLoopback(ResultCell rcell) {
254             // push the incoming invocation on the
255
// top of the stack.
256
pushInvocation(rcell);
257             m_loopback = true;
258             this.notify();
259     }
260
261     public synchronized void pushInvocation(ResultCell rcell) {
262         // push the incoming invocation on the
263
// top of the stack.
264
rcell.thread = this;
265         rcell.parent = m_stack;
266         m_stack = rcell;
267     }
268
269     private synchronized ResultCell popInvocation (ResultCell rcell,
270                                                    boolean loopback)
271             throws Exception JavaDoc {
272         // push the incoming invocation on the
273
// top of the stack.
274
Exception JavaDoc ex;
275         if (m_stack==null)
276             throw new Error JavaDoc("***** Unpaired Push/Pop.");
277         if (rcell==null) {
278             if (m_stack.parent!=null)
279                 throw new Error JavaDoc("***** Not popping last frame...");
280             rcell = m_stack;
281             m_stack = null;
282         } else {
283             if (m_stack!=rcell)
284                 throw new Error JavaDoc("***** Popping but not top of stack.");
285             
286             m_stack = rcell.parent;
287         }
288
289         if (!loopback) {
290             ex = rcell.getException();
291             if (ex!=null)
292                 throw ex;
293         }
294         return rcell;
295     }
296 }
297
Popular Tags