KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jruby > internal > runtime > ThreadService


1 /***** BEGIN LICENSE BLOCK *****
2  * Version: CPL 1.0/GPL 2.0/LGPL 2.1
3  *
4  * The contents of this file are subject to the Common Public
5  * License Version 1.0 (the "License"); you may not use this file
6  * except in compliance with the License. You may obtain a copy of
7  * the License at http://www.eclipse.org/legal/cpl-v10.html
8  *
9  * Software distributed under the License is distributed on an "AS
10  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
11  * implied. See the License for the specific language governing
12  * rights and limitations under the License.
13  *
14  * Copyright (C) 2002-2004 Anders Bengtsson <ndrsbngtssn@yahoo.se>
15  * Copyright (C) 2004 Charles O Nutter <headius@headius.com>
16  * Copyright (C) 2004 Stefan Matthias Aust <sma@3plus4.de>
17  * Copyright (C) 2006 Miguel Covarrubias <mlcovarrubias@gmail.com>
18  *
19  * Alternatively, the contents of this file may be used under the terms of
20  * either of the GNU General Public License Version 2 or later (the "GPL"),
21  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
22  * in which case the provisions of the GPL or the LGPL are applicable instead
23  * of those above. If you wish to allow use of your version of this file only
24  * under the terms of either the GPL or the LGPL, and not to allow others to
25  * use your version of this file under the terms of the CPL, indicate your
26  * decision by deleting the provisions above and replace them with the notice
27  * and other provisions required by the GPL or the LGPL. If you do not delete
28  * the provisions above, a recipient may use your version of this file under
29  * the terms of any one of the CPL, the GPL or the LGPL.
30  ***** END LICENSE BLOCK *****/

31 package org.jruby.internal.runtime;
32
33 import java.util.ArrayList JavaDoc;
34 import java.util.Collections JavaDoc;
35 import java.util.Iterator JavaDoc;
36 import java.util.List JavaDoc;
37 import java.util.Set JavaDoc;
38
39 import org.jruby.Ruby;
40 import org.jruby.RubyThread;
41 import org.jruby.runtime.ThreadContext;
42 import org.jruby.util.collections.WeakHashSet;
43
44 public class ThreadService {
45     private Ruby runtime;
46     private ThreadContext mainContext;
47     private ThreadLocal JavaDoc localContext;
48     private ThreadGroup JavaDoc rubyThreadGroup;
49     private Set JavaDoc rubyThreadList;
50     private Thread JavaDoc mainThread;
51     private RubyThread criticalThread;
52
53     public ThreadService(Ruby runtime) {
54         this.runtime = runtime;
55         this.mainContext = new ThreadContext(runtime);
56         this.localContext = new ThreadLocal JavaDoc();
57         this.rubyThreadGroup = new ThreadGroup JavaDoc("Ruby Threads#" + runtime.hashCode());
58         this.rubyThreadList = Collections.synchronizedSet(new WeakHashSet());
59         
60         // Must be called from main thread (it is currently, but this bothers me)
61
mainThread = Thread.currentThread();
62         localContext.set(mainContext);
63         rubyThreadList.add(mainThread);
64     }
65
66     public void disposeCurrentThread() {
67         localContext.set(null);
68     }
69
70     public ThreadContext getCurrentContext() {
71         ThreadContext tc = (ThreadContext) localContext.get();
72         
73         if (tc == null) {
74             tc = adoptCurrentThread();
75         }
76         
77         return tc;
78     }
79     
80     private ThreadContext adoptCurrentThread() {
81         Thread JavaDoc current = Thread.currentThread();
82         
83         RubyThread.adopt(runtime.getClass("Thread"), current);
84         
85         return (ThreadContext) localContext.get();
86     }
87
88     public RubyThread getMainThread() {
89         return mainContext.getThread();
90     }
91
92     public void setMainThread(RubyThread thread) {
93         mainContext.setThread(thread);
94     }
95     
96     public synchronized RubyThread[] getActiveRubyThreads() {
97         // all threads in ruby thread group plus main thread
98

99         synchronized(rubyThreadList) {
100             List JavaDoc rtList = new ArrayList JavaDoc(rubyThreadList.size());
101         
102             for (Iterator JavaDoc iter = rubyThreadList.iterator(); iter.hasNext();) {
103                 Thread JavaDoc t = (Thread JavaDoc)iter.next();
104             
105                 if (!t.isAlive()) continue;
106             
107                 RubyThread rt = getRubyThreadFromThread(t);
108                 rtList.add(rt);
109             }
110         
111             RubyThread[] rubyThreads = new RubyThread[rtList.size()];
112             rtList.toArray(rubyThreads);
113         
114             return rubyThreads;
115         }
116     }
117     
118     public ThreadGroup JavaDoc getRubyThreadGroup() {
119         return rubyThreadGroup;
120     }
121
122     public synchronized void registerNewThread(RubyThread thread) {
123         localContext.set(new ThreadContext(runtime));
124         getCurrentContext().setThread(thread);
125         // This requires register to be called from within the registree thread
126
rubyThreadList.add(Thread.currentThread());
127     }
128     
129     public synchronized void setCritical(boolean critical) {
130         RubyThread currentThread = getCurrentContext().getThread();
131         
132         // TODO: this implementation is obviously dependent on native threads
133
if (criticalThread != null) {
134             // currently in a critical section
135
if (critical) {
136                 // enabling critical, do nothing
137
return;
138             }
139             if (criticalThread != currentThread) {
140                 // we're not the critical thread, do nothing (TODO: or perhaps wait on the critical thread here?)
141
return;
142             }
143             
144             // clear the critical thread and notify all waiting on it
145
synchronized (criticalThread) {
146                 RubyThread critThread = criticalThread;
147                 criticalThread = null;
148                 critThread.notifyAll();
149             }
150         } else {
151             // not in a critical section
152
if (!critical) {
153                 // not asking for critical, do nothing
154
return;
155             }
156             
157             // set the critical thread!
158
criticalThread = currentThread;
159         }
160     }
161     
162     private RubyThread getRubyThreadFromThread(Thread JavaDoc activeThread) {
163         RubyThread rubyThread;
164         if (activeThread instanceof RubyNativeThread) {
165             RubyNativeThread rubyNativeThread = (RubyNativeThread)activeThread;
166             rubyThread = rubyNativeThread.getRubyThread();
167         } else {
168             // main thread
169
rubyThread = mainContext.getThread();
170         }
171         return rubyThread;
172     }
173
174     public RubyThread getCriticalThread() {
175         return criticalThread;
176     }
177
178 }
179
Popular Tags