start from fresh tree
[concurrent.git] / java / concurrent / FuturesService.java
blob59246e73a602d3b88e00c74b16c45ab31aa573d5
1 /***** BEGIN LICENSE BLOCK****
2 * Version: CPL 1.0/GPL 2.0/LGPL 2.1
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
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.
14 * Copyright (C) 2007 MenTaLguY <mental@rydia.net>
16 * Alternatively, the contents of this file may be used under the terms of
17 * either of the GNU General Public License Version 2 or later (the "GPL"),
18 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
19 * in which case the provisions of the GPL or the LGPL are applicable instead
20 * of those above. If you wish to allow use of your version of this file only
21 * under the terms of either the GPL or the LGPL, and not to allow others to
22 * use your version of this file under the terms of the CPL, indicate your
23 * decision by deleting the provisions above and replace them with the notice
24 * and other provisions required by the GPL or the LGPL. If you do not delete
25 * the provisions above, a recipient may use your version of this file under
26 * the terms of any one of the CPL, the GPL or the LGPL.
27 ***** END LICENSE BLOCK *****/
29 package concurrent;
31 import java.io.IOException;
32 import java.util.Iterator;
33 import java.util.Map;
35 import org.jruby.IRuby;
36 import org.jruby.RubyArray;
37 import org.jruby.RubyClass;
38 import org.jruby.RubyException;
39 import org.jruby.RubyFixnum;
40 import org.jruby.RubyFloat;
41 import org.jruby.RubyInteger;
42 import org.jruby.RubyModule;
43 import org.jruby.RubyString;
44 import org.jruby.ast.Node;
45 import org.jruby.exceptions.RaiseException;
46 import org.jruby.runtime.Block;
47 import org.jruby.runtime.CallbackFactory;
48 import org.jruby.runtime.callback.Callback;
49 import org.jruby.runtime.CallType;
50 import org.jruby.runtime.ObjectAllocator;
51 import org.jruby.runtime.ThreadContext;
52 import org.jruby.runtime.load.BasicLibraryService;
53 import org.jruby.runtime.builtin.IRubyObject;
55 public class FuturesService implements BasicLibraryService {
56 public boolean basicLoad(final IRuby runtime) throws IOException {
57 Thunk.setup(runtime);
58 return true;
61 public static class Thunk implements IRubyObject {
62 private IRuby runtime;
63 private RubyClass klass;
64 private IRubyObject source;
65 private IRubyObject value;
67 Thunk(IRuby runtime, RubyClass klass, IRubyObject source) {
68 this.runtime = runtime;
69 this.klass = klass;
70 this.source = source;
71 this.value = null;
74 public static IRubyObject newInstance(IRubyObject recv, IRubyObject source) {
75 return new Thunk(recv.getRuntime(), (RubyClass)recv, source);
78 public static void setup(final IRuby runtime) throws IOException {
79 RubyClass cThunk = runtime.getOrCreateModule("Concurrent").defineModuleUnder("Futures").defineClassUnder("Thunk", null, ObjectAllocator.NOT_ALLOCATABLE_ALLOCATOR);
80 CallbackFactory cb = runtime.callbackFactory(Thunk.class);
81 cThunk.getMetaClass().defineMethod("new", cb.getSingletonMethod("newInstance", IRubyObject.class));
82 cThunk.defineMethod("value", cb.getSingletonMethod("value", IRubyObject.class));
85 public static IRubyObject thunkValue(IRubyObject obj, boolean evaluate) {
86 IRubyObject original=obj;
88 while (obj instanceof Thunk) {
89 Thunk thunk=(Thunk)obj;
91 synchronized (thunk) {
92 if ( thunk.source != null ) {
93 if (evaluate) {
94 thunk.value = thunk.source.callMethod(thunk.source.getRuntime().getCurrentContext(), "value");
95 thunk.source = null;
98 if ( obj != original ) {
99 Thunk original_thunk = (Thunk)original;
100 synchronized (original_thunk) {
101 original_thunk.value = thunk.value;
105 if (!evaluate) {
106 break;
110 obj = thunk.value;
114 return obj;
117 public static IRubyObject evalThunk(IRubyObject obj) {
118 try {
119 return thunkValue(obj, true);
120 } catch (RaiseException e) {
121 RubyClass cAsyncError = obj.getRuntime().getModule("Concurrent").defineModuleUnder("Futures").getClass("AsyncError");
122 RubyException e2 = (RubyException)cAsyncError.callMethod(obj.getRuntime().getCurrentContext(), "new", e.getException());
123 throw new RaiseException(e2);
127 public static IRubyObject value(IRubyObject recv, IRubyObject obj) {
128 return thunkValue(obj, true);
131 public int getNativeTypeIndex() {
132 return evalThunk(this).getNativeTypeIndex();
135 public Map safeGetInstanceVariables() {
136 return evalThunk(this).safeGetInstanceVariables();
139 public boolean safeHasInstanceVariables() {
140 return evalThunk(this).safeHasInstanceVariables();
143 public IRubyObject getInstanceVariable(String name) {
144 return evalThunk(this).getInstanceVariable(name);
147 public IRubyObject setInstanceVariable(String name, IRubyObject value) {
148 return evalThunk(this).setInstanceVariable(name, value);
151 public Map getInstanceVariables() {
152 return evalThunk(this).getInstanceVariables();
155 public Map getInstanceVariablesSnapshot() {
156 return evalThunk(this).getInstanceVariablesSnapshot();
159 public IRubyObject callMethod(ThreadContext context, RubyModule rubyclass, String name, IRubyObject[] args, CallType callType, Block block) {
160 return evalThunk(this).callMethod(context, rubyclass, name, args, callType, block);
163 public IRubyObject callMethod(ThreadContext context, RubyModule rubyclass, byte switchValue, String name, IRubyObject[] args, CallType callType) {
164 return evalThunk(this).callMethod(context, rubyclass, switchValue, name, args, callType);
167 public IRubyObject callMethod(ThreadContext context, byte switchValue, String name, IRubyObject[] args, CallType callType, Block block) {
168 return evalThunk(this).callMethod(context, switchValue, name, args, callType, block);
171 public IRubyObject callMethod(ThreadContext context, String name, IRubyObject[] args, CallType callType) {
172 return evalThunk(this).callMethod(context, name, args, callType);
175 public IRubyObject callMethod(ThreadContext context, String name, IRubyObject[] args, CallType callType, Block block) {
176 return evalThunk(this).callMethod(context, name, args, callType, block);
179 public IRubyObject callMethod(ThreadContext context, String name) {
180 return evalThunk(this).callMethod(context, name);
183 public IRubyObject callMethod(ThreadContext context, String name, Block block) {
184 return evalThunk(this).callMethod(context, name, block);
187 public IRubyObject callMethod(ThreadContext context, String name, IRubyObject arg) {
188 return evalThunk(this).callMethod(context, name, arg);
191 public IRubyObject callMethod(ThreadContext context, String name, IRubyObject[] args) {
192 return evalThunk(this).callMethod(context, name, args);
195 public IRubyObject callMethod(ThreadContext context, String name, IRubyObject[] args, Block block) {
196 return evalThunk(this).callMethod(context, name, args, block);
199 public boolean isNil() {
200 return evalThunk(this).isNil();
203 public boolean isTrue() {
204 return evalThunk(this).isTrue();
207 public boolean isTaint() {
208 return evalThunk(this).isTaint();
211 public boolean isFrozen() {
212 return evalThunk(this).isFrozen();
215 public boolean isImmediate() {
216 return evalThunk(this).isImmediate();
219 public RubyClass getMetaClass() {
220 return evalThunk(this).getMetaClass();
223 public void setMetaClass(RubyClass metaClass) {
224 evalThunk(this).setMetaClass(metaClass);
227 public RubyClass getSingletonClass() {
228 return evalThunk(this).getSingletonClass();
231 public RubyClass getType() {
232 return evalThunk(this).getType();
235 public boolean isKindOf(RubyModule rubyClass) {
236 return evalThunk(this).isKindOf(rubyClass);
239 public boolean respondsTo(String method) {
240 return evalThunk(this).respondsTo(method);
243 public IRuby getRuntime() {
244 return this.runtime;
247 public Class getJavaClass() {
248 return evalThunk(this).getJavaClass();
251 public IRubyObject eval(Node iNode) {
252 return evalThunk(this).eval(iNode);
255 public IRubyObject evalWithBinding(ThreadContext context, IRubyObject evalString, IRubyObject binding, String file) {
256 return evalThunk(this).evalWithBinding(context, evalString, binding, file);
259 public IRubyObject evalSimple(ThreadContext context, IRubyObject evalString, String file) {
260 return evalThunk(this).evalSimple(context, evalString, file);
263 public void extendObject(RubyModule rubyModule) {
264 evalThunk(this).extendObject(rubyModule);
267 public String asSymbol() {
268 return evalThunk(this).asSymbol();
271 public RubyArray convertToArray() {
272 return evalThunk(this).convertToArray();
274 public RubyFloat convertToFloat() {
275 return evalThunk(this).convertToFloat();
277 public RubyInteger convertToInteger() {
278 return evalThunk(this).convertToInteger();
280 public RubyString convertToString() {
281 return evalThunk(this).convertToString();
284 public IRubyObject convertToType(String targetType, String convertMethod, boolean raiseOnError) {
285 return evalThunk(this).convertToType(targetType, convertMethod, raiseOnError);
288 public IRubyObject convertToTypeWithCheck(String targetType, String convertMethod) {
289 return evalThunk(this).convertToTypeWithCheck(targetType, convertMethod);
292 public void setTaint(boolean b) {
293 evalThunk(this).setTaint(b);
296 public void checkSafeString() {
297 evalThunk(this).checkSafeString();
300 public IRubyObject convertType(Class type, String string, String string1) {
301 return evalThunk(this).convertType(type, string, string1);
304 public IRubyObject dup() {
305 return evalThunk(this).dup();
308 public void initCopy(IRubyObject original) {
309 evalThunk(this).initCopy(original);
312 public void setFrozen(boolean b) {
313 evalThunk(this).setFrozen(b);
316 public IRubyObject inspect() {
317 return evalThunk(this).inspect();
320 public int checkArgumentCount(IRubyObject[] arguments, int minimum, int maximum) {
321 return evalThunk(this).checkArgumentCount(arguments, minimum, maximum);
324 public IRubyObject rbClone() {
325 return evalThunk(this).rbClone();
328 public void callInit(IRubyObject[] args, Block block) {
329 evalThunk(this).callInit(args, block);
332 public void defineSingletonMethod(String name, Callback callback) {
333 evalThunk(this).defineSingletonMethod(name, callback);
336 public boolean singletonMethodsAllowed() {
337 return evalThunk(this).singletonMethodsAllowed();
340 public boolean isSingleton() {
341 return evalThunk(this).isSingleton();
344 public Iterator instanceVariableNames() {
345 return evalThunk(this).instanceVariableNames();
348 public IRubyObject[] scanArgs(IRubyObject[] args, int required, int optional) {
349 return evalThunk(this).scanArgs(args, required, optional);
352 public void dataWrapStruct(Object obj) {
353 evalThunk(this).dataWrapStruct(obj);
356 public Object dataGetStruct() {
357 return evalThunk(this).dataGetStruct();
360 public RubyFixnum id() {
361 return evalThunk(this).id();
364 public IRubyObject anyToString() {
365 return evalThunk(this).anyToString();
368 public IRubyObject checkStringType() {
369 return evalThunk(this).checkStringType();