Yield with (an unbounded but recycled number of) threads. We used to use a wonderful homemade byte-code rewriting based trick to implement 'yield' for annotated methods. This trick takes a very different path, it's less space and time efficient (the context switch into the method is much slower
| 25 | * TODO: finish making _r = wrap( () => {}) work |
| 26 | */ |
| 27 | public class ThreadSync { |
| 28 | static public final boolean enabled = Options.dict() |
| 29 | .isTrue(new Dict.Prop("threaded"), false); |
| 30 | static private final ExecutorService executor = Executors.newCachedThreadPool(); |
| 31 | static public Object NULL = new Object(); |
| 32 | public static ThreadLocal<Fiber> fiber = new ThreadLocal<>(); |
| 33 | static ThreadLocal<ThreadSync> threadingModel = new ThreadLocal<>(); |
| 34 | static private Map<Thread, ThreadSync> models = new MapMaker().weakKeys() |
| 35 | .makeMap(); |
| 36 | static public Thread mainThread; |
| 37 | Set<Fiber> live = new LinkedHashSet<Fiber>(); |
| 38 | |
| 39 | public Fiber currentFiber; |
| 40 | |
| 41 | // this should be getThreadingModelForCurrentThread(); |
| 42 | protected ThreadSync() { |
| 43 | mainThread = Thread.currentThread(); |
| 44 | } |
| 45 | |
| 46 | static public ThreadSync get() { |
| 47 | return models.computeIfAbsent(Thread.currentThread(), k -> new ThreadSync()); |
| 48 | } |
| 49 | |
| 50 | static public <K> Supplier<K> input(Iterator<K> a) { |
| 51 | return () -> { |
| 52 | if (a.hasNext()) { |
| 53 | K k = a.next(); |
| 54 | if (k == null) throw new Stop("input returned null"); |
| 55 | return a.next(); |
| 56 | } |
| 57 | throw new Stop(); |
| 58 | }; |
| 59 | } |
| 60 | |
| 61 | static public <T> T callInMainThreadAndWait(Callable<T> c) throws Exception { |
| 62 | if (Thread.currentThread() == RunLoop.main.mainThread) { |
| 63 | System.out.println("||||||||||||||||||||||||||||||| already main thread"); |
| 64 | return c.call(); |
| 65 | } else { |
| 66 | |
| 67 | System.out.println(" current thread :"+Thread.currentThread()+" "+RunLoop.main.mainThread); |
| 68 | |
| 69 | CompletableFuture<T> f = new CompletableFuture<>(); |
| 70 | System.out.println("||||||||||||||||||||||||||||||| call once "); |
| 71 | RunLoop.main.once(() -> { |
| 72 | try { |
| 73 | f.complete(c.call()); |
| 74 | } catch (Throwable t) { |
| 75 | f.completeExceptionally(t); |
| 76 | } |
| 77 | }); |
| 78 | |
| 79 | // should be rejoin? |
| 80 | System.out.println("||||||||||||||||||||||||||||||| begin wait "); |
| 81 | while (!f.isDone()) { |
| 82 | System.out.println("||||||||||||||||||||||||||||||| yield to main loop"); |
| 83 | ThreadSync.yield(true); |
| 84 | System.out.println("||||||||||||||||||||||||||||||| back from main loop"); |