├── .classpath ├── .gitignore ├── .project ├── README.md ├── export.jardesc ├── lib-continuations.jar ├── lib └── asm-all-5.0.3.jar ├── src-test └── net │ └── indiespot │ └── continuations │ └── test │ ├── basics │ ├── ContinuationsTestBasics.java │ ├── ContinuationsTestCoIterator.java │ ├── VirtualThreadTestBoundedBuffer.java │ ├── VirtualThreadTestException.java │ ├── VirtualThreadTestExchanger.java │ ├── VirtualThreadTestHeavyLoad.java │ ├── VirtualThreadTestMessages.java │ ├── VirtualThreadTestSchedule.java │ ├── VirtualThreadTestSerializable.java │ ├── VirtualThreadTestThreadLocal.java │ └── VirtualThreadTestYieldMutex.java │ ├── game │ ├── Action.java │ ├── Game.java │ ├── GameCanvas.java │ ├── GameItem.java │ ├── Misc.java │ ├── MoveAction.java │ ├── ResourceConversion.java │ ├── ResourceGroup.java │ ├── ResourceHolder.java │ ├── ResourceSource.java │ └── ResourceType.java │ ├── game1 │ ├── Human.java │ ├── TestVirtualThreadsGame1.java │ ├── Wanderer.java │ └── Well.java │ ├── game2 │ ├── Lumberjack.java │ ├── Storage.java │ ├── TestVirtualThreadsGame2.java │ └── Tree.java │ ├── game3 │ ├── Smith.java │ ├── TestVirtualThreadsGame3.java │ ├── Transporter.java │ └── WoodShop.java │ ├── game4 │ ├── Commander.java │ ├── Soldier.java │ └── TestVirtualThreadsGame4.java │ └── nio │ └── VirtualThreadNIO.java └── src ├── de └── matthiasmann │ └── continuations │ ├── CoIterator.java │ ├── Coroutine.java │ ├── CoroutineProto.java │ ├── SomeInterface.java │ ├── Stack.java │ ├── SuspendExecution.java │ ├── Util.java │ ├── instrument │ ├── AlreadyInstrumented.java │ ├── CheckInstrumentationVisitor.java │ ├── DBClassWriter.java │ ├── ExtractSuperClass.java │ ├── InstrumentClass.java │ ├── InstrumentMethod.java │ ├── JavaAgent.java │ ├── Log.java │ ├── LogLevel.java │ ├── MethodDatabase.java │ ├── NewValue.java │ ├── OmittedInstruction.java │ ├── TypeAnalyzer.java │ ├── TypeInterpreter.java │ ├── UnableToInstrumentException.java │ ├── UnresolvedValue.java │ └── package-info.java │ └── package-info.java └── net └── indiespot ├── continuations ├── VirtualProcessor.java ├── VirtualRunnable.java ├── VirtualThread.java ├── VirtualThreadLocal.java ├── VirtualThreadQueue.java ├── VirtualThreadState.java ├── VirtualUncaughtExceptionHandler.java ├── libcontinuations.mf └── util │ ├── VirtualCondition.java │ ├── VirtualExchanger.java │ ├── VirtualLock.java │ ├── VirtualMessage.java │ └── VirtualMessageQueue.java └── dependencies ├── CircularArrayList.java ├── EasyMath.java ├── Filter.java ├── IntList.java └── Vec2.java /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /bin 2 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | LibContinuations 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.jdt.core.javanature 16 | 17 | 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## LibContinuations 2 | 3 | LibContinuations is a small library that enables the use of [Green Threads](http://en.wikipedia.org/wiki/Green_threads) in Java. 4 | 5 | Conceptually, a green threead is a virtual thread that runs on real (native) threads. A green thread can `sleep` or `yield` and its state is preserved while other threads execute, enabling you to write normal Java code that doesn't suffer from multithreading overhead and related complexity (locks, race conditions, etc). LibContinuations is as close as possible to regular threads, runnables and locks so integrates easily with existing code. There is very little overhead per green thread, allowing many thousands of green threads to be run on a single thread. 6 | 7 | ## Use case 8 | 9 | For example, AI code can be written with your usual Java control-flow: 10 | 11 | ```java 12 | public void run () throws SuspendExecution { 13 | while (true) { // this is the AI of the unit, it will go on forever 14 | Vec2 originalLocation = new Vec2(this.position); 15 | Water water = this.findWater(); 16 | this.moveTo(water.position); 17 | this.drink(water); 18 | this.moveTo(originalLocation); // walk back 19 | } 20 | } 21 | 22 | public void drink (Water water) throws SuspendExecution { 23 | while (!this.isFull() && water.level > 0) { 24 | water.level--; 25 | this.water++; 26 | sleep(1500); // drinking takes a while 27 | } 28 | } 29 | 30 | public void moveTo (Vec2 end) throws SuspendExecution { 31 | Vec2 start = new Vec2(this.position); 32 | float distance = Vec2.distance(start); 33 | float duration = distance / this.speed; 34 | for (float traveled = 0; traveled <= duration; traveled += this.speed) { 35 | float ratio = Math.min(traveled / distance, 1); 36 | this.position.x = start.x + ratio * (end.x - start.x); 37 | this.position.y = start.y + ratio * (end.y - start.y); 38 | yield(); // wake up here in the next game tick 39 | } 40 | } 41 | 42 | ``` 43 | 44 | ## Implementation 45 | 46 | LibContinuations is written on top of Matthias Mann's [Continuations Library](http://www.matthiasmann.de/content/view/24/26/) which provides the concept of `yield return`, as found in C# and other languages. This works by rewriting bytecode to store and restore the Java stack. 47 | 48 | ## Adjusting your bytecode 49 | 50 | There are two ways to apply the bytecode rewriting: 51 | 52 | * At runtime: A Java agent intercepts classloading and adjusts each class as it is loaded. This is convenient while developing. 53 | * Ahead of time: Java code or an Ant task discovers your class files and rewrites them. This is convenient to do before deploying your application. 54 | 55 | With either option you still have full debugging functionality in your IDE: step into/over/out and breakpoints work as always. 56 | 57 | ## Using LibContinuations 58 | 59 | `VirtualProcessor` manages all green threads for a single native thread. `VirtualThread` takes a `VirtualRunnable` and behaves just like `java.lang.Thread` and `java.lang.Runnable`. Methods that can be suspended via `VirtualThread.sleep()` or `VirtualThread.yield()` must throw `SuspendExecution`. 60 | 61 | 62 | ```java 63 | import net.indiespot.continuations.*; 64 | import de.matthiasmann.continuations.SuspendExecution; 65 | 66 | public class Example { 67 | public Example () { 68 | VirtualProcessor processor = new VirtualProcessor(); 69 | 70 | new VirtualThread(new VirtualRunnable() { 71 | public void run () throws SuspendExecution { 72 | while (true) { 73 | System.out.println("first task"); 74 | VirtualThread.sleep(1000); 75 | } 76 | } 77 | }).start(processor); 78 | 79 | new VirtualThread(new VirtualRunnable() { 80 | public void run () throws SuspendExecution { 81 | while (true) { 82 | System.out.println("second task"); 83 | VirtualThread.sleep(800); 84 | } 85 | } 86 | }).start(); // the last VirtualProcessor for this thread is used if omitted 87 | 88 | while (true) { 89 | long now = System.nanoTime() / 1000000l; 90 | processor.tick(now); 91 | } 92 | } 93 | 94 | public static void main (String[] args) throws Exception { 95 | new Example(); 96 | } 97 | } 98 | 99 | ``` 100 | 101 | Before this code can be run, it must be processed ahead of time by the Ant task or Java code, or the Java agent must be used. To use the Java agent, these JVM parameters must be used: 102 | 103 | 104 | ``` 105 | -javaagent:continuations-agent.jar -ea 106 | ``` 107 | 108 | To use Ant: 109 | 110 | ```xml 111 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | ``` 121 | 122 | To use Java: 123 | 124 | ```java 125 | import de.matthiasmann.continuations.instrument.DBClassWriter; 126 | import de.matthiasmann.continuations.instrument.InstrumentClass; 127 | import de.matthiasmann.continuations.instrument.MethodDatabase; 128 | 129 | ... 130 | 131 | // Collect each class file that may need to be processed. 132 | MethodDatabase db = new MethodDatabase(MethodDatabase.class.getClassLoader()); 133 | for (String classFile : Scar.paths("classes", "**.class")) // uses Scar to collect paths 134 | db.checkClass(new File(classFile)); 135 | 136 | // Rewrite the class files that need processing. 137 | for (File file : db.getWorkList()) 138 | instrumentClass(db, file); 139 | 140 | ... 141 | 142 | 143 | static private void instrumentClass (MethodDatabase db, File file) throws IOException { 144 | FileInputStream input = new FileInputStream(file); 145 | ClassReader reader = new ClassReader(input); 146 | input.close(); 147 | 148 | ClassWriter writer = new DBClassWriter(db, reader); 149 | reader.accept(new InstrumentClass(writer, db, false), ClassReader.SKIP_FRAMES); 150 | byte[] newClass = writer.toByteArray(); 151 | 152 | FileOutputStream output = new FileOutputStream(file); 153 | output.write(newClass); 154 | output.close(); 155 | } 156 | 157 | ``` 158 | -------------------------------------------------------------------------------- /export.jardesc: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /lib-continuations.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/riven8192/LibContinuations/ad15ab9005069115955f368bc42dcd2422b9eca5/lib-continuations.jar -------------------------------------------------------------------------------- /lib/asm-all-5.0.3.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/riven8192/LibContinuations/ad15ab9005069115955f368bc42dcd2422b9eca5/lib/asm-all-5.0.3.jar -------------------------------------------------------------------------------- /src-test/net/indiespot/continuations/test/basics/ContinuationsTestBasics.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012, Enhanced Four 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are 7 | * met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * * Neither the name of 'Enhanced Four' nor the names of its contributors 17 | * may be used to endorse or promote products derived from this software 18 | * without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | package net.indiespot.continuations.test.basics; 34 | 35 | import de.matthiasmann.continuations.Coroutine; 36 | import de.matthiasmann.continuations.Coroutine.State; 37 | import de.matthiasmann.continuations.CoroutineProto; 38 | import de.matthiasmann.continuations.SuspendExecution; 39 | 40 | public class ContinuationsTestBasics implements CoroutineProto { 41 | public static void main(String[] args) { 42 | Coroutine coroutine = new Coroutine(new ContinuationsTestBasics()); 43 | 44 | for (int i = 0; coroutine.getState() != State.FINISHED; i++) { 45 | System.out.println("loop-" + (i + 1)); 46 | coroutine.run(); 47 | } 48 | } 49 | 50 | @Override 51 | public void coExecute() throws SuspendExecution { 52 | System.out.println("\tco-routine-1"); 53 | Coroutine.yield(); 54 | System.out.println("\tco-routine-2"); 55 | Coroutine.yield(); 56 | System.out.println("\tco-routine-3"); 57 | this.lala1(); 58 | } 59 | 60 | public void lala1() throws SuspendExecution { 61 | Coroutine.yield(); 62 | System.out.println("\tco-routine-4"); 63 | this.lala2(); 64 | } 65 | 66 | public void lala2() throws SuspendExecution { 67 | Coroutine.yield(); 68 | System.out.println("\tco-routine-5"); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src-test/net/indiespot/continuations/test/basics/ContinuationsTestCoIterator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012, Enhanced Four 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are 7 | * met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * * Neither the name of 'Enhanced Four' nor the names of its contributors 17 | * may be used to endorse or promote products derived from this software 18 | * without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | package net.indiespot.continuations.test.basics; 34 | 35 | import java.util.Iterator; 36 | 37 | import de.matthiasmann.continuations.CoIterator; 38 | import de.matthiasmann.continuations.SuspendExecution; 39 | 40 | public class ContinuationsTestCoIterator { 41 | 42 | @SuppressWarnings("serial") 43 | static class YieldReturn extends CoIterator { 44 | @Override 45 | protected void run() throws SuspendExecution { 46 | this.produce("a"); 47 | this.produce("b"); 48 | for (int i = 0; i < 4; i++) { 49 | produce("c" + i); 50 | } 51 | this.produce("d"); 52 | this.produce("e"); 53 | } 54 | } 55 | 56 | public static void main(String[] args) { 57 | Iterator iterator = new YieldReturn(); 58 | for (String str : asIterable(iterator)) { 59 | System.out.println("got: " + str); 60 | } 61 | } 62 | 63 | private static final Iterable asIterable(final Iterator iterator) { 64 | return new Iterable() { 65 | @Override 66 | public Iterator iterator() { 67 | return iterator; 68 | } 69 | }; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src-test/net/indiespot/continuations/test/basics/VirtualThreadTestBoundedBuffer.java: -------------------------------------------------------------------------------- 1 | package net.indiespot.continuations.test.basics; 2 | 3 | import static net.indiespot.continuations.VirtualThread.sleep; 4 | import de.matthiasmann.continuations.SuspendExecution; 5 | import net.indiespot.continuations.*; 6 | import net.indiespot.continuations.util.VirtualCondition; 7 | import net.indiespot.continuations.util.VirtualLock; 8 | 9 | public class VirtualThreadTestBoundedBuffer { 10 | 11 | static class BoundedBuffer { 12 | final VirtualLock lock = new VirtualLock(); 13 | final VirtualCondition notFull = lock.newCondition(); 14 | final VirtualCondition notEmpty = lock.newCondition(); 15 | 16 | final Object[] items; 17 | public int putptr, takeptr, count; 18 | 19 | public BoundedBuffer(int cap) { 20 | items = new Object[cap]; 21 | } 22 | 23 | public void put(Object x) throws SuspendExecution { 24 | lock.lock(); 25 | try { 26 | while (count == items.length) { 27 | notFull.await(); 28 | } 29 | 30 | items[putptr] = x; 31 | if (++putptr == items.length) { 32 | putptr = 0; 33 | } 34 | ++count; 35 | 36 | notEmpty.signal(); 37 | } finally { 38 | lock.unlock(); 39 | } 40 | } 41 | 42 | public Object take() throws SuspendExecution { 43 | lock.lock(); 44 | try { 45 | while (count == 0) { 46 | notEmpty.await(); 47 | } 48 | 49 | Object x = items[takeptr]; 50 | if (++takeptr == items.length) { 51 | takeptr = 0; 52 | } 53 | --count; 54 | 55 | notFull.signal(); 56 | return x; 57 | } finally { 58 | lock.unlock(); 59 | } 60 | } 61 | } 62 | 63 | @SuppressWarnings("serial") 64 | public static void main(String[] args) { 65 | final VirtualProcessor processor = new VirtualProcessor(); 66 | 67 | final BoundedBuffer bb = new BoundedBuffer(10); 68 | 69 | final int slowDownFactor = 10; 70 | 71 | new VirtualThread(new VirtualRunnable() { 72 | @Override 73 | public void run() throws SuspendExecution { 74 | for (int i = 0; true; i++) { 75 | bb.put(Integer.valueOf(i)); 76 | 77 | // varying production rate 78 | sleep(slowDownFactor * (5 + (i / 10) % 15)); 79 | } 80 | } 81 | }).start(); 82 | 83 | new VirtualThread(new VirtualRunnable() { 84 | @Override 85 | public void run() throws SuspendExecution { 86 | while (true) { 87 | System.out.println("size=" + bb.count); 88 | bb.take(); 89 | 90 | // constant consumption rate 91 | sleep(slowDownFactor * 10); 92 | } 93 | } 94 | }).start(); 95 | 96 | // game loop 97 | do { 98 | processor.tick(now()); 99 | 100 | try { 101 | Thread.sleep(1); 102 | } catch (InterruptedException exc) { 103 | // ignore 104 | } 105 | } while (processor.hasPendingTasks()); 106 | } 107 | 108 | static long now() { 109 | return System.nanoTime() / 1_000_000L; 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src-test/net/indiespot/continuations/test/basics/VirtualThreadTestException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012, Enhanced Four 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are 7 | * met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * * Neither the name of 'Enhanced Four' nor the names of its contributors 17 | * may be used to endorse or promote products derived from this software 18 | * without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | package net.indiespot.continuations.test.basics; 34 | 35 | import net.indiespot.continuations.VirtualProcessor; 36 | import net.indiespot.continuations.VirtualRunnable; 37 | import net.indiespot.continuations.VirtualThread; 38 | import de.matthiasmann.continuations.*; 39 | 40 | public class VirtualThreadTestException { 41 | public static void main(String[] args) { 42 | VirtualProcessor proc = new VirtualProcessor(); 43 | 44 | @SuppressWarnings("serial") 45 | VirtualRunnable task = new VirtualRunnable() { 46 | @Override 47 | public void run() throws SuspendExecution { 48 | a(); 49 | } 50 | 51 | private void a() throws SuspendExecution { 52 | b(); 53 | } 54 | 55 | private void b() throws SuspendExecution { 56 | c(); 57 | } 58 | 59 | private void c() throws SuspendExecution { 60 | throw new RuntimeException("what to do?"); 61 | } 62 | }; 63 | 64 | VirtualThread thread = new VirtualThread(task); 65 | thread.start(); 66 | 67 | System.out.println("---"); 68 | proc.tick(System.currentTimeMillis()); 69 | System.out.println("---"); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src-test/net/indiespot/continuations/test/basics/VirtualThreadTestExchanger.java: -------------------------------------------------------------------------------- 1 | package net.indiespot.continuations.test.basics; 2 | 3 | import de.matthiasmann.continuations.SuspendExecution; 4 | import net.indiespot.continuations.*; 5 | import net.indiespot.continuations.util.VirtualExchanger; 6 | 7 | public class VirtualThreadTestExchanger { 8 | 9 | @SuppressWarnings("serial") 10 | public static void main(String[] args) { 11 | final VirtualProcessor processor = new VirtualProcessor(); 12 | 13 | final VirtualExchanger ex = new VirtualExchanger<>(); 14 | 15 | new VirtualThread(new VirtualRunnable() { 16 | @Override 17 | public void run() throws SuspendExecution { 18 | String got = ex.exchange("object1a"); 19 | System.out.println("thread1 got: " + got); 20 | 21 | got = ex.exchange("object1b"); 22 | System.out.println("thread1 got: " + got); 23 | } 24 | }).start(); 25 | System.out.println("start thread1"); 26 | 27 | new VirtualThread(new VirtualRunnable() { 28 | @Override 29 | public void run() throws SuspendExecution { 30 | String got = ex.exchange("object2a"); 31 | System.out.println("thread2 got: " + got); 32 | 33 | got = ex.exchange("object2b"); 34 | System.out.println("thread2 got: " + got); 35 | } 36 | }).start(); 37 | System.out.println("start thread2"); 38 | 39 | // game loop 40 | do { 41 | processor.tick(now()); 42 | 43 | try { 44 | Thread.sleep(1); 45 | } catch (InterruptedException exc) { 46 | // ignore 47 | } 48 | } while (processor.hasPendingTasks()); 49 | 50 | System.out.println("stopped"); 51 | } 52 | 53 | static long now() { 54 | return System.nanoTime() / 1_000_000L; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src-test/net/indiespot/continuations/test/basics/VirtualThreadTestHeavyLoad.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012, Enhanced Four 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are 7 | * met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * * Neither the name of 'Enhanced Four' nor the names of its contributors 17 | * may be used to endorse or promote products derived from this software 18 | * without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | package net.indiespot.continuations.test.basics; 34 | 35 | import static net.indiespot.continuations.VirtualThread.*; 36 | 37 | import java.util.Random; 38 | 39 | import net.indiespot.continuations.*; 40 | import de.matthiasmann.continuations.SuspendExecution; 41 | 42 | public class VirtualThreadTestHeavyLoad { 43 | @SuppressWarnings("serial") 44 | public static void main(String[] args) { 45 | final VirtualProcessor processor = new VirtualProcessor(1); 46 | 47 | final Random rndm = new Random(2346L); 48 | 49 | final long[] hash = new long[1]; 50 | 51 | int virtualThreads = 0; 52 | 53 | long tA = System.nanoTime(); 54 | 55 | // game loop 56 | long now = 0; 57 | do { 58 | if (virtualThreads < 2_500_000) { 59 | for (int i = 0; i < 10_000; i++) { 60 | virtualThreads += 1; 61 | 62 | new VirtualThread(new VirtualRunnable() { 63 | @Override 64 | public void run() throws SuspendExecution { 65 | while (true) { 66 | float f = rndm.nextFloat(); 67 | sleep((int) (10 + 1000 * f * f * f)); 68 | } 69 | } 70 | 71 | @SuppressWarnings("unused") 72 | private void doh(int sleep) throws SuspendExecution { 73 | hash[0] *= 37; 74 | duh(sleep); 75 | } 76 | 77 | private void duh(int sleep) throws SuspendExecution { 78 | hash[0] ^= sleep; 79 | sleep(sleep); 80 | } 81 | }).start(); 82 | } 83 | } else { 84 | //System.out.println("ok:done"); 85 | } 86 | 87 | //long t0 = System.nanoTime(); 88 | //int count = processor.tick(now++); 89 | //long t1 = System.nanoTime(); 90 | 91 | //System.out.println(count + " tasks took: " + (t1 - t0) / 1_000_000L + "ms, " + (t1 - t0) / Math.max(1, count) + "nanos/switch"); 92 | 93 | if (now == 5000) { 94 | System.out.println(hash[0]); 95 | break; 96 | } 97 | } while (processor.hasPendingTasks()); 98 | 99 | long tB = System.nanoTime(); 100 | System.out.println((tB - tA) / 1000000 + "ms"); 101 | } 102 | 103 | static long now() { 104 | return System.nanoTime() / 1_000_000L; 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src-test/net/indiespot/continuations/test/basics/VirtualThreadTestMessages.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012, Enhanced Four 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are 7 | * met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * * Neither the name of 'Enhanced Four' nor the names of its contributors 17 | * may be used to endorse or promote products derived from this software 18 | * without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | package net.indiespot.continuations.test.basics; 34 | 35 | import net.indiespot.continuations.*; 36 | import net.indiespot.continuations.util.VirtualMessage; 37 | import de.matthiasmann.continuations.SuspendExecution; 38 | 39 | public class VirtualThreadTestMessages { 40 | @SuppressWarnings("serial") 41 | public static void main(String[] args) { 42 | final VirtualProcessor processor = new VirtualProcessor(); 43 | 44 | final VirtualThread threadA = new VirtualThread(new VirtualRunnable() { 45 | @Override 46 | public void run() throws SuspendExecution { 47 | VirtualMessage got = VirtualThread.awaitMessage(); 48 | System.out.println(got.author()); 49 | System.out.println(got.message()); 50 | } 51 | }); 52 | 53 | final VirtualThread threadB = new VirtualThread(new VirtualRunnable() { 54 | @Override 55 | public void run() throws SuspendExecution { 56 | threadA.passMessage("hello"); 57 | } 58 | }); 59 | 60 | threadA.start(); 61 | threadB.start(); 62 | 63 | // game loop 64 | do { 65 | processor.tick(now()); 66 | 67 | try { 68 | Thread.sleep(1); 69 | } catch (InterruptedException exc) { 70 | // ignore 71 | } 72 | } while (processor.hasPendingTasks()); 73 | } 74 | 75 | static long now() { 76 | return System.nanoTime() / 1_000_000L; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src-test/net/indiespot/continuations/test/basics/VirtualThreadTestSchedule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012, Enhanced Four 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are 7 | * met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * * Neither the name of 'Enhanced Four' nor the names of its contributors 17 | * may be used to endorse or promote products derived from this software 18 | * without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | package net.indiespot.continuations.test.basics; 34 | 35 | import static net.indiespot.continuations.VirtualThread.*; 36 | import net.indiespot.continuations.*; 37 | import de.matthiasmann.continuations.SuspendExecution; 38 | 39 | public class VirtualThreadTestSchedule { 40 | @SuppressWarnings("serial") 41 | public static void main(String[] args) { 42 | final VirtualProcessor processor = new VirtualProcessor(); 43 | 44 | // create virtual threads (or green threads, if you will) 45 | 46 | final long started = now(); 47 | final long finalWake = now() + 5000; 48 | 49 | new VirtualThread(new VirtualRunnable() { 50 | @Override 51 | public void run() throws SuspendExecution { 52 | System.out.println("thread 1: a (" + (now() - started) + "ms)"); 53 | sleep(1000); 54 | System.out.println("thread 1: b (" + (now() - started) + "ms)"); 55 | sleep(1000); 56 | System.out.println("thread 1: c (" + (now() - started) + "ms)"); 57 | sleep(1000); 58 | System.out.println("thread 1: d (" + (now() - started) + "ms)"); 59 | yield(); 60 | System.out.println("thread 1: e (" + (now() - started) + "ms)"); 61 | wakeupAt(finalWake); 62 | System.out.println("thread 1: f (" + (now() - started) + "ms)"); 63 | } 64 | }).start(); 65 | 66 | new VirtualThread(new VirtualRunnable() { 67 | @Override 68 | public void run() throws SuspendExecution { 69 | sleep(500); 70 | System.out.println("thread 2: a (" + (now() - started) + "ms)"); 71 | sleep(2000); 72 | System.out.println("thread 2: b (" + (now() - started) + "ms)"); 73 | } 74 | }).start(); 75 | 76 | new VirtualThread(new VirtualRunnable() { 77 | @Override 78 | public void run() throws SuspendExecution { 79 | sleep(1500); 80 | System.out.println("thread 3: a (" + (now() - started) + "ms)"); 81 | sleep(100); 82 | System.out.println("thread 3: b (" + (now() - started) + "ms)"); 83 | sleep(100); 84 | System.out.println("thread 3: c (" + (now() - started) + "ms)"); 85 | sleep(100); 86 | System.out.println("thread 3: d (" + (now() - started) + "ms)"); 87 | } 88 | }).start(); 89 | 90 | // game loop 91 | do { 92 | processor.tick(now()); 93 | 94 | try { 95 | Thread.sleep(1); 96 | } catch (InterruptedException exc) { 97 | // ignore 98 | } 99 | } while (processor.hasPendingTasks()); 100 | } 101 | 102 | static long now() { 103 | return System.nanoTime() / 1_000_000L; 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src-test/net/indiespot/continuations/test/basics/VirtualThreadTestSerializable.java: -------------------------------------------------------------------------------- 1 | package net.indiespot.continuations.test.basics; 2 | 3 | import de.matthiasmann.continuations.SuspendExecution; 4 | import net.indiespot.continuations.*; 5 | 6 | public class VirtualThreadTestSerializable { 7 | 8 | @SuppressWarnings("serial") 9 | public static void main(String[] args) { 10 | final VirtualProcessor processor = new VirtualProcessor(); 11 | 12 | final VirtualThread vt = new VirtualThread(new VirtualRunnable() { 13 | @Override 14 | public void run() throws SuspendExecution { 15 | for (int i = 0; true; i++) { 16 | System.out.println("i=" + i); 17 | VirtualThread.sleep(101); 18 | 19 | if (i == 13) { 20 | VirtualThread.suspend(); 21 | } 22 | } 23 | } 24 | }); 25 | vt.start(); 26 | 27 | final VirtualThread vt2 = new VirtualThread(new VirtualRunnable() { 28 | @Override 29 | public void run() throws SuspendExecution { 30 | 31 | while (vt.getState() != VirtualThreadState.SUSPENDED) { 32 | VirtualThread.sleep(25); 33 | } 34 | 35 | System.out.println("serializing..."); 36 | byte[] data = vt.serialize(); 37 | System.out.println("deserializing " + data.length + " bytes..."); 38 | VirtualThread vt = VirtualThread.deserialize(processor, data); 39 | System.out.println("resuming..."); 40 | vt.resume(); 41 | } 42 | }); 43 | vt2.start(); 44 | 45 | // game loop 46 | do { 47 | processor.tick(now()); 48 | 49 | try { 50 | Thread.sleep(1); 51 | } catch (InterruptedException exc) { 52 | // ignore 53 | } 54 | } while (processor.hasPendingTasks()); 55 | } 56 | 57 | static long now() { 58 | return System.nanoTime() / 1_000_000L; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src-test/net/indiespot/continuations/test/basics/VirtualThreadTestThreadLocal.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012, Enhanced Four 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are 7 | * met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * * Neither the name of 'Enhanced Four' nor the names of its contributors 17 | * may be used to endorse or promote products derived from this software 18 | * without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | package net.indiespot.continuations.test.basics; 34 | 35 | import net.indiespot.continuations.*; 36 | import de.matthiasmann.continuations.SuspendExecution; 37 | 38 | public class VirtualThreadTestThreadLocal { 39 | @SuppressWarnings("serial") 40 | public static void main(String[] args) { 41 | final VirtualProcessor processor = new VirtualProcessor(); 42 | 43 | final VirtualThreadLocal threadLocal = new VirtualThreadLocal() { 44 | protected String initialValue() { 45 | return "initial"; 46 | } 47 | }; 48 | 49 | new VirtualThread(new VirtualRunnable() { 50 | @Override 51 | public void run() throws SuspendExecution { 52 | System.out.println("thread1.get=" + threadLocal.get()); 53 | VirtualThread.yield(); 54 | threadLocal.set("thread1"); 55 | VirtualThread.yield(); 56 | System.out.println("thread1.get=" + threadLocal.get()); 57 | } 58 | }).start(); 59 | 60 | new VirtualThread(new VirtualRunnable() { 61 | @Override 62 | public void run() throws SuspendExecution { 63 | System.out.println("thread2.get=" + threadLocal.get()); 64 | threadLocal.set("thread2"); 65 | System.out.println("thread2.get=" + threadLocal.get()); 66 | } 67 | }).start(); 68 | 69 | // game loop 70 | do { 71 | processor.tick(now()); 72 | 73 | try { 74 | Thread.sleep(1); 75 | } catch (InterruptedException exc) { 76 | // ignore 77 | } 78 | } while (processor.hasPendingTasks()); 79 | } 80 | 81 | static long now() { 82 | return System.nanoTime() / 1_000_000L; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src-test/net/indiespot/continuations/test/basics/VirtualThreadTestYieldMutex.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012, Enhanced Four 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are 7 | * met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * * Neither the name of 'Enhanced Four' nor the names of its contributors 17 | * may be used to endorse or promote products derived from this software 18 | * without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | package net.indiespot.continuations.test.basics; 34 | 35 | import net.indiespot.continuations.VirtualProcessor; 36 | import net.indiespot.continuations.VirtualRunnable; 37 | import net.indiespot.continuations.VirtualThread; 38 | import net.indiespot.continuations.util.VirtualCondition; 39 | import de.matthiasmann.continuations.*; 40 | 41 | public class VirtualThreadTestYieldMutex { 42 | @SuppressWarnings("serial") 43 | public static void main(String[] args) { 44 | VirtualProcessor proc = new VirtualProcessor(); 45 | 46 | final VirtualCondition condition = new VirtualCondition(); 47 | 48 | VirtualRunnable task = new VirtualRunnable() { 49 | @Override 50 | public void run() throws SuspendExecution { 51 | System.out.println("hello"); 52 | VirtualThread.yield(); 53 | System.out.println("world"); 54 | VirtualThread.yield(); 55 | System.out.println("aight?"); 56 | condition.await(); 57 | System.out.println("aight!"); 58 | } 59 | }; 60 | 61 | VirtualThread thread = new VirtualThread(task); 62 | thread.start(); 63 | 64 | System.out.println("---"); 65 | proc.tick(System.currentTimeMillis()); 66 | System.out.println("---"); 67 | proc.tick(System.currentTimeMillis()); 68 | System.out.println("---"); 69 | proc.tick(System.currentTimeMillis()); 70 | System.out.println("---"); 71 | proc.tick(System.currentTimeMillis()); 72 | System.out.println("---"); 73 | condition.signal(); 74 | System.out.println("---"); 75 | proc.tick(System.currentTimeMillis()); 76 | System.out.println("---"); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src-test/net/indiespot/continuations/test/game/Action.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012, Enhanced Four 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are 7 | * met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * * Neither the name of 'Enhanced Four' nor the names of its contributors 17 | * may be used to endorse or promote products derived from this software 18 | * without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | package net.indiespot.continuations.test.game; 34 | 35 | public interface Action { 36 | public boolean perform(); 37 | 38 | public void end(); 39 | } 40 | -------------------------------------------------------------------------------- /src-test/net/indiespot/continuations/test/game/GameCanvas.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012, Enhanced Four 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are 7 | * met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * * Neither the name of 'Enhanced Four' nor the names of its contributors 17 | * may be used to endorse or promote products derived from this software 18 | * without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | package net.indiespot.continuations.test.game; 34 | 35 | import java.awt.*; 36 | import java.awt.event.*; 37 | 38 | import javax.swing.*; 39 | 40 | import net.indiespot.continuations.test.game1.*; 41 | 42 | 43 | @SuppressWarnings("serial") 44 | public class GameCanvas extends JPanel { 45 | 46 | boolean renderLabelsForHumans = false; 47 | 48 | @Override 49 | public void addNotify() { 50 | super.addNotify(); 51 | 52 | this.addMouseListener(new MouseAdapter() { 53 | @Override 54 | public void mousePressed(MouseEvent e) { 55 | if (e.getButton() != 1) { 56 | renderLabelsForHumans ^= true; 57 | } 58 | } 59 | }); 60 | } 61 | 62 | @Override 63 | protected void paintComponent(Graphics g) { 64 | super.paintComponent(g); 65 | 66 | for (GameItem item : Game.ALL_ITEMS) { 67 | 68 | g.setColor(Color.BLUE); 69 | 70 | int x = (int) item.position.x; 71 | int y = (int) item.position.y; 72 | g.setColor(item.color); 73 | g.fillRect(x - 3, y - 3, 6, 6); 74 | 75 | if (!item.displayLabels) { 76 | continue; 77 | } 78 | 79 | if (item.travelTarget != null) { 80 | g.setColor(Color.LIGHT_GRAY); 81 | g.drawLine((int) item.position.x, (int) item.position.y, (int) item.travelTarget.x, (int) item.travelTarget.y); 82 | } 83 | 84 | g.setColor(Color.BLACK); 85 | if (item.name != null && !item.name.isEmpty()) { 86 | g.drawString(item.toString(), x + 10, y); 87 | 88 | if (renderLabelsForHumans || !(item instanceof Human)) { 89 | 90 | for (ResourceType type : item.consumingResources.types()) { 91 | y += 14; 92 | g.drawString("consuming " + type.name() + ": " + item.consumingResources.get(type), x + 20, y); 93 | } 94 | 95 | for (ResourceType type : item.producingResources.types()) { 96 | y += 14; 97 | g.drawString("producing " + type.name() + ": " + item.producingResources.get(type), x + 20, y); 98 | } 99 | 100 | for (ResourceType type : item.holdingResources.types()) { 101 | y += 14; 102 | g.drawString("holding " + type.name() + ": " + item.holdingResources.get(type), x + 20, y); 103 | } 104 | } 105 | } 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src-test/net/indiespot/continuations/test/game/Misc.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012, Enhanced Four 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are 7 | * met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * * Neither the name of 'Enhanced Four' nor the names of its contributors 17 | * may be used to endorse or promote products derived from this software 18 | * without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | package net.indiespot.continuations.test.game; 34 | 35 | import java.util.*; 36 | 37 | public class Misc { 38 | 39 | private static final Random rand = new Random(2345245 + 10); 40 | 41 | public static float randomBase(float base, float margin) { 42 | return random(base - margin, base + margin); 43 | } 44 | 45 | public static float random(float min, float max) { 46 | return min + rand.nextFloat() * (max - min); 47 | } 48 | 49 | public static long random(long min, long max) { 50 | return min + (long) (rand.nextFloat() * (max - min)); 51 | } 52 | 53 | public static int random(int min, int max) { 54 | return min + (int) (rand.nextFloat() * (max - min)); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src-test/net/indiespot/continuations/test/game/MoveAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012, Enhanced Four 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are 7 | * met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * * Neither the name of 'Enhanced Four' nor the names of its contributors 17 | * may be used to endorse or promote products derived from this software 18 | * without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | package net.indiespot.continuations.test.game; 34 | 35 | import net.indiespot.continuations.VirtualThread; 36 | import net.indiespot.dependencies.EasyMath; 37 | import net.indiespot.dependencies.Vec2; 38 | import de.matthiasmann.continuations.*; 39 | 40 | public class MoveAction implements Action { 41 | private final Vec2 pos, src, dst; 42 | private final long departAt, arriveAt; 43 | private final VirtualThread toResume; 44 | 45 | private MoveAction(Vec2 pos, long duration, Vec2 src, Vec2 dst) { 46 | if (duration < 0) { 47 | throw new IllegalStateException(); 48 | } 49 | 50 | this.pos = pos; 51 | this.departAt = Game.TIME; 52 | this.arriveAt = Game.TIME + duration; 53 | this.src = src; 54 | this.dst = dst; 55 | 56 | this.toResume = VirtualThread.peekCurrentThread(); 57 | } 58 | 59 | @Override 60 | public boolean perform() { 61 | float ratio = EasyMath.invLerpWithCap(Game.TIME, departAt, arriveAt); 62 | pos.x = EasyMath.lerp(src.x, dst.x, ratio); 63 | pos.y = EasyMath.lerp(src.y, dst.y, ratio); 64 | return Game.TIME <= arriveAt; 65 | } 66 | 67 | @Override 68 | public void end() { 69 | this.toResume.resume(); 70 | } 71 | 72 | public static void moveTo(GameItem item, Vec2 dst) throws SuspendExecution { 73 | Vec2 src = new Vec2(item.position); 74 | 75 | float dx = src.x - dst.x; 76 | float dy = src.y - dst.y; 77 | float dist2 = dx * dx + dy * dy; 78 | if (dist2 == 0.0f) { 79 | return; 80 | } 81 | 82 | float distance = (float) Math.sqrt(dist2); 83 | float duration = distance / item.speed; 84 | long durationMillis = (long) (duration * 1000L); 85 | 86 | item.setAction(new MoveAction(item.position, durationMillis, src, dst)); 87 | 88 | // VirtualThread.sleep(durationMillis); 89 | VirtualThread.suspend(); // resume at end of MoveAction 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src-test/net/indiespot/continuations/test/game/ResourceConversion.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012, Enhanced Four 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are 7 | * met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * * Neither the name of 'Enhanced Four' nor the names of its contributors 17 | * may be used to endorse or promote products derived from this software 18 | * without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | package net.indiespot.continuations.test.game; 34 | 35 | import java.util.*; 36 | 37 | import net.indiespot.dependencies.IntList; 38 | 39 | public class ResourceConversion { 40 | private final List consumeTypes = new ArrayList<>(); 41 | private final List produceTypes = new ArrayList<>(); 42 | private final IntList consumeAmount = new IntList(); 43 | private final IntList produceAmount = new IntList(); 44 | 45 | public void consume(ResourceType type, int amount) { 46 | if (type == null) { 47 | throw new NullPointerException(); 48 | } 49 | if (amount <= 0) { 50 | throw new IllegalArgumentException(); 51 | } 52 | 53 | this.consumeTypes.add(type); 54 | this.consumeAmount.add(amount); 55 | } 56 | 57 | public void produce(ResourceType type, int amount) { 58 | if (type == null) { 59 | throw new NullPointerException(); 60 | } 61 | if (amount <= 0) { 62 | throw new IllegalArgumentException(); 63 | } 64 | 65 | this.produceTypes.add(type); 66 | this.produceAmount.add(amount); 67 | } 68 | 69 | public boolean convert(GameItem item) { 70 | for (int i = 0; i < consumeTypes.size(); i++) { 71 | ResourceType type = consumeTypes.get(i); 72 | int take = consumeAmount.get(i); 73 | if (item.consumingResources.get(type).getFilledSpace() < take) { 74 | return false; 75 | } 76 | } 77 | 78 | for (int i = 0; i < produceTypes.size(); i++) { 79 | ResourceType type = produceTypes.get(i); 80 | int make = produceAmount.get(i); 81 | if (item.producingResources.get(type).getFreeSpace() < make) { 82 | return false; 83 | } 84 | } 85 | 86 | // 87 | 88 | for (int i = 0; i < consumeTypes.size(); i++) { 89 | ResourceType type = consumeTypes.get(i); 90 | int take = consumeAmount.get(i); 91 | if (item.consumingResources.get(type).take(take) != take) { 92 | throw new IllegalStateException(); 93 | } 94 | } 95 | 96 | for (int i = 0; i < produceTypes.size(); i++) { 97 | ResourceType type = produceTypes.get(i); 98 | int make = produceAmount.get(i); 99 | if (item.producingResources.get(type).put(make) != make) { 100 | throw new IllegalStateException(); 101 | } 102 | } 103 | 104 | return true; 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src-test/net/indiespot/continuations/test/game/ResourceGroup.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012, Enhanced Four 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are 7 | * met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * * Neither the name of 'Enhanced Four' nor the names of its contributors 17 | * may be used to endorse or promote products derived from this software 18 | * without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | package net.indiespot.continuations.test.game; 34 | 35 | import java.util.*; 36 | 37 | import de.matthiasmann.continuations.*; 38 | 39 | public class ResourceGroup { 40 | private final Map mapping; 41 | 42 | public ResourceGroup() { 43 | this.mapping = new HashMap(); 44 | } 45 | 46 | public ResourceHolder register(ResourceType type, ResourceHolder holder) { 47 | if (this.mapping.containsKey(type)) { 48 | throw new IllegalStateException(); 49 | } 50 | this.mapping.put(type, holder); 51 | return holder; 52 | } 53 | 54 | public ResourceHolder get(ResourceType type) { 55 | ResourceHolder holder = this.mapping.get(type); 56 | if (holder == null) { 57 | throw new NoSuchElementException("type: " + type.name()); 58 | } 59 | return holder; 60 | } 61 | 62 | public ResourceHolder getOrNull(ResourceType type) { 63 | return this.mapping.get(type); 64 | } 65 | 66 | public Set types() { 67 | return this.mapping.keySet(); 68 | } 69 | 70 | @Override 71 | public String toString() { 72 | return this.mapping.toString(); 73 | } 74 | 75 | // 76 | 77 | public static int transfer(ResourceType type, ResourceGroup src, ResourceGroup dst) { 78 | return ResourceHolder.transfer(src.get(type), dst.get(type)); 79 | } 80 | 81 | public static int transfer(ResourceType type, ResourceGroup src, ResourceGroup dst, int max) { 82 | return ResourceHolder.transfer(src.get(type), dst.get(type), max); 83 | } 84 | 85 | public static int transferSlowly(ResourceType type, ResourceGroup src, ResourceGroup dst, int maxToBeTransfered, int maxPerTransfer, int attemptInterval, int maxAttempts) throws SuspendExecution { 86 | return ResourceHolder.transferSlowly(src.get(type), dst.get(type), maxToBeTransfered, maxPerTransfer, attemptInterval, maxAttempts); 87 | } 88 | } -------------------------------------------------------------------------------- /src-test/net/indiespot/continuations/test/game/ResourceHolder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012, Enhanced Four 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are 7 | * met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * * Neither the name of 'Enhanced Four' nor the names of its contributors 17 | * may be used to endorse or promote products derived from this software 18 | * without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | package net.indiespot.continuations.test.game; 34 | 35 | import net.indiespot.continuations.VirtualThread; 36 | import de.matthiasmann.continuations.*; 37 | 38 | public class ResourceHolder { 39 | private int holding; 40 | private int capacity; 41 | 42 | public ResourceHolder(int capacity) { 43 | if (capacity < 1) { 44 | throw new IllegalArgumentException(); 45 | } 46 | this.capacity = capacity; 47 | } 48 | 49 | public ResourceHolder(int holding, int capacity) { 50 | if (capacity < 1) { 51 | throw new IllegalArgumentException(); 52 | } 53 | if (holding < 0) { 54 | throw new IllegalArgumentException(); 55 | } 56 | if (holding > capacity) { 57 | throw new IllegalArgumentException(); 58 | } 59 | this.holding = holding; 60 | this.capacity = capacity; 61 | } 62 | 63 | public void grow(int amount) { 64 | if (amount < 0) { 65 | throw new IllegalArgumentException(); 66 | } 67 | this.capacity += amount; 68 | } 69 | 70 | public void shrink(int amount) { 71 | if (amount < 0) { 72 | throw new IllegalArgumentException(); 73 | } 74 | if (this.capacity - amount < this.holding) { 75 | throw new IllegalStateException(); 76 | } 77 | this.capacity -= amount; 78 | } 79 | 80 | public boolean isEmpty() { 81 | return this.holding == 0; 82 | } 83 | 84 | public float getRatio() { 85 | return (float) this.holding / this.capacity; 86 | } 87 | 88 | public boolean isFull() { 89 | return this.holding == this.capacity; 90 | } 91 | 92 | public int getFilledSpace() { 93 | return this.holding; 94 | } 95 | 96 | public int getFreeSpace() { 97 | return this.capacity - this.holding; 98 | } 99 | 100 | public int drain() { 101 | return this.take(this.getFilledSpace()); 102 | } 103 | 104 | public int fill() { 105 | return this.put(this.getFreeSpace()); 106 | } 107 | 108 | public int put(int amount) { 109 | if (amount < 0) { 110 | throw new IllegalArgumentException(); 111 | } 112 | int transfer = Math.min(amount, this.getFreeSpace()); 113 | this.holding += transfer; 114 | return transfer; 115 | } 116 | 117 | public int take(int amount) { 118 | if (amount < 0) { 119 | throw new IllegalArgumentException(); 120 | } 121 | int transfer = Math.min(amount, this.holding); 122 | this.holding -= transfer; 123 | return transfer; 124 | } 125 | 126 | @Override 127 | public String toString() { 128 | return this.holding + "/" + this.capacity; 129 | } 130 | 131 | // 132 | 133 | public static int transfer(ResourceHolder src, ResourceHolder dst) { 134 | return transfer(src, dst, Integer.MAX_VALUE); 135 | } 136 | 137 | public static int transfer(ResourceHolder src, ResourceHolder dst, int max) { 138 | if (max < 0) { 139 | throw new IllegalArgumentException("cannot transfer less than zero resources: " + max); 140 | } 141 | 142 | int transfer = Math.min(src.getFilledSpace(), dst.getFreeSpace()); 143 | 144 | transfer = Math.min(max, transfer); 145 | 146 | if (src.take(transfer) != transfer) { 147 | throw new IllegalStateException(); 148 | } 149 | 150 | if (dst.put(transfer) != transfer) { 151 | throw new IllegalStateException(); 152 | } 153 | 154 | return transfer; 155 | } 156 | 157 | public static int transferSlowly(ResourceHolder src, ResourceHolder dst, int maxToBeTransfered, int maxPerTransfer, int attemptInterval, int maxAttempts) throws SuspendExecution { 158 | 159 | int rem = maxToBeTransfered; 160 | 161 | while (true) { 162 | int move = Math.min(rem, maxPerTransfer); 163 | if (move <= 0) { 164 | break; 165 | } 166 | 167 | int moved = ResourceHolder.transfer(src, dst, move); 168 | if (moved == 0) { 169 | break; 170 | } 171 | 172 | VirtualThread.sleep(attemptInterval); 173 | } 174 | 175 | return maxToBeTransfered - rem; 176 | } 177 | } -------------------------------------------------------------------------------- /src-test/net/indiespot/continuations/test/game/ResourceSource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012, Enhanced Four 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are 7 | * met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * * Neither the name of 'Enhanced Four' nor the names of its contributors 17 | * may be used to endorse or promote products derived from this software 18 | * without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | package net.indiespot.continuations.test.game; 34 | 35 | public class ResourceSource extends ResourceHolder { 36 | 37 | public ResourceSource() { 38 | super(Integer.MAX_VALUE); 39 | } 40 | 41 | public boolean isEmpty() { 42 | return false; 43 | } 44 | 45 | public float getRatio() { 46 | return 1.0f; 47 | } 48 | 49 | public boolean isFull() { 50 | return true; 51 | } 52 | 53 | public int getFilledSpace() { 54 | return Integer.MAX_VALUE; 55 | } 56 | 57 | public int getFreeSpace() { 58 | return Integer.MAX_VALUE; 59 | } 60 | 61 | public int put(int amount) { 62 | if (amount < 0) { 63 | throw new IllegalArgumentException(); 64 | } 65 | return amount; 66 | } 67 | 68 | public int take(int amount) { 69 | if (amount < 0) { 70 | throw new IllegalArgumentException(); 71 | } 72 | return amount; 73 | } 74 | 75 | @Override 76 | public String toString() { 77 | return "infinite/infinite"; 78 | } 79 | 80 | } -------------------------------------------------------------------------------- /src-test/net/indiespot/continuations/test/game/ResourceType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012, Enhanced Four 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are 7 | * met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * * Neither the name of 'Enhanced Four' nor the names of its contributors 17 | * may be used to endorse or promote products derived from this software 18 | * without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | package net.indiespot.continuations.test.game; 34 | 35 | public enum ResourceType { 36 | TREE, LOG, WATER, IRON, // 37 | CHARCOAL, PLANK, TOOL 38 | } 39 | -------------------------------------------------------------------------------- /src-test/net/indiespot/continuations/test/game1/Human.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012, Enhanced Four 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are 7 | * met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * * Neither the name of 'Enhanced Four' nor the names of its contributors 17 | * may be used to endorse or promote products derived from this software 18 | * without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | package net.indiespot.continuations.test.game1; 34 | 35 | import static net.indiespot.continuations.test.game.ResourceType.*; 36 | 37 | import java.awt.*; 38 | 39 | import net.indiespot.continuations.VirtualRunnable; 40 | import net.indiespot.continuations.VirtualThread; 41 | import net.indiespot.continuations.test.game.Game; 42 | import net.indiespot.continuations.test.game.GameItem; 43 | import net.indiespot.continuations.test.game.Misc; 44 | import net.indiespot.continuations.test.game.ResourceHolder; 45 | import net.indiespot.dependencies.Filter; 46 | import net.indiespot.dependencies.Vec2; 47 | import de.matthiasmann.continuations.*; 48 | 49 | public abstract class Human extends GameItem { 50 | 51 | @SuppressWarnings("serial") 52 | public Human() { 53 | this.name = "human"; 54 | this.color = Color.DARK_GRAY; 55 | 56 | this.speed = 25f + (float) Math.random() * 25f; 57 | 58 | this.consumingResources.register(WATER, new ResourceHolder(Misc.random(25, 50), Misc.random(50, 100))); 59 | 60 | this.spawn(new VirtualRunnable() {@Override 61 | public void run() throws SuspendExecution { 62 | Human.this.ai(); 63 | } 64 | }); 65 | 66 | this.spawn(new VirtualRunnable() { 67 | @Override 68 | public void run() throws SuspendExecution { 69 | while (true) { 70 | VirtualThread.sleep(1250); 71 | 72 | if (consumingResources.get(WATER).take(1) == 0) { 73 | System.out.println(Human.this.toString() + " died of thirst"); 74 | kill(); 75 | throw new IllegalStateException("never happens"); 76 | } 77 | } 78 | } 79 | }); 80 | } 81 | 82 | public abstract void ai() throws SuspendExecution; 83 | 84 | protected void survive() throws SuspendExecution { 85 | Vec2 goBackTo = new Vec2(this.position); 86 | 87 | boolean didSomethingElse = false; 88 | while (this.isThirsty()) { 89 | this.task = "looking for water"; 90 | GameItem water = this.findNearestWater(); 91 | if (water == null) { 92 | break; 93 | } 94 | 95 | didSomethingElse = true; 96 | 97 | this.task = "walking to water"; 98 | moveTo(water.position); 99 | 100 | this.task = "drinking water"; 101 | this.drinkWater(water); 102 | } 103 | 104 | if (didSomethingElse) { 105 | this.task = "going back..."; 106 | } 107 | moveTo(goBackTo); 108 | } 109 | 110 | public boolean isThirsty() { 111 | return this.consumingResources.get(WATER).getFilledSpace() < 20; 112 | } 113 | 114 | private int drinkWater(GameItem water) throws SuspendExecution { 115 | return water.transfer(WATER, this, 50); 116 | } 117 | 118 | private GameItem findNearestWater() throws SuspendExecution { 119 | //return Game.nearest(Well.class, new WellFilledWellFilter(), this.position); 120 | return Game.nearestProducer(WATER, false, new WellFilledWellFilter(), this.position); 121 | } 122 | 123 | // 124 | 125 | private static class WellFilledWellFilter implements Filter { 126 | @Override 127 | public boolean accept(GameItem item) { 128 | return item.producingResources.get(WATER).getFilledSpace() > 20; 129 | } 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /src-test/net/indiespot/continuations/test/game1/TestVirtualThreadsGame1.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012, Enhanced Four 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are 7 | * met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * * Neither the name of 'Enhanced Four' nor the names of its contributors 17 | * may be used to endorse or promote products derived from this software 18 | * without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | package net.indiespot.continuations.test.game1; 34 | 35 | import net.indiespot.continuations.test.game.Game; 36 | import net.indiespot.continuations.test.game.Misc; 37 | 38 | public class TestVirtualThreadsGame1 { 39 | public static void main(String[] args) throws Exception { 40 | Game.init(new Runnable() { 41 | @Override 42 | public void run() { 43 | // add water 44 | for (int i = 0; i < 25; i++) { 45 | Well well = new Well(); 46 | well.position.x = Misc.randomBase(1024 / 2, 1024 / 2); 47 | well.position.y = Misc.randomBase(768 / 2, 768 / 2); 48 | Game.addItem(well); 49 | } 50 | 51 | // add wanderers 52 | for (int i = 0; i < 5; i++) { 53 | Game.addItem(new Wanderer()); 54 | } 55 | } 56 | }); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src-test/net/indiespot/continuations/test/game1/Wanderer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012, Enhanced Four 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are 7 | * met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * * Neither the name of 'Enhanced Four' nor the names of its contributors 17 | * may be used to endorse or promote products derived from this software 18 | * without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | package net.indiespot.continuations.test.game1; 34 | 35 | import net.indiespot.continuations.test.game.Misc; 36 | import net.indiespot.dependencies.Vec2; 37 | import de.matthiasmann.continuations.*; 38 | 39 | public class Wanderer extends Human { 40 | 41 | public Wanderer() { 42 | this.name = "wanderer"; 43 | } 44 | 45 | @Override 46 | public void ai() throws SuspendExecution { 47 | Vec2 dst = new Vec2(Misc.random(200.0f, 600.0f), Misc.random(200.0f, 400.0f)); 48 | 49 | this.position.add(dst); 50 | 51 | while (true) { 52 | dst.x = Misc.randomBase(position.x, 25.0f); 53 | dst.y = Misc.randomBase(position.y, 25.0f); 54 | this.moveTo(dst); 55 | 56 | this.survive(); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src-test/net/indiespot/continuations/test/game1/Well.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012, Enhanced Four 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are 7 | * met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * * Neither the name of 'Enhanced Four' nor the names of its contributors 17 | * may be used to endorse or promote products derived from this software 18 | * without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | package net.indiespot.continuations.test.game1; 34 | 35 | import static net.indiespot.continuations.test.game.ResourceType.*; 36 | 37 | import java.awt.*; 38 | 39 | import net.indiespot.continuations.VirtualRunnable; 40 | import net.indiespot.continuations.VirtualThread; 41 | import net.indiespot.continuations.test.game.GameItem; 42 | import net.indiespot.continuations.test.game.Misc; 43 | import net.indiespot.continuations.test.game.ResourceHolder; 44 | import de.matthiasmann.continuations.*; 45 | 46 | public class Well extends GameItem { 47 | 48 | @SuppressWarnings("serial") 49 | public Well() { 50 | this.name = "well"; 51 | this.color = Color.BLUE; 52 | 53 | this.producingResources.register(WATER, new ResourceHolder(100, 150)); 54 | 55 | this.spawn(new VirtualRunnable() { 56 | @Override 57 | public void run() throws SuspendExecution { 58 | ai(); 59 | } 60 | }); 61 | } 62 | 63 | void ai() throws SuspendExecution { 64 | while (true) { 65 | VirtualThread.sleep(750); 66 | this.producingResources.get(WATER).put(Misc.random(1, 3)); 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src-test/net/indiespot/continuations/test/game2/Lumberjack.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012, Enhanced Four 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are 7 | * met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * * Neither the name of 'Enhanced Four' nor the names of its contributors 17 | * may be used to endorse or promote products derived from this software 18 | * without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | package net.indiespot.continuations.test.game2; 34 | 35 | import static net.indiespot.continuations.test.game.ResourceType.*; 36 | import net.indiespot.continuations.VirtualThread; 37 | import net.indiespot.continuations.test.game.Game; 38 | import net.indiespot.continuations.test.game.GameItem; 39 | import net.indiespot.continuations.test.game.Misc; 40 | import net.indiespot.continuations.test.game.ResourceConversion; 41 | import net.indiespot.continuations.test.game.ResourceHolder; 42 | import net.indiespot.continuations.test.game1.*; 43 | import net.indiespot.dependencies.Vec2; 44 | import de.matthiasmann.continuations.*; 45 | 46 | public class Lumberjack extends Human { 47 | 48 | final ResourceConversion makeLogs; 49 | 50 | public Lumberjack() { 51 | this.name = "lumberjack"; 52 | 53 | this.consumingResources.register(TREE, new ResourceHolder(Misc.random(5, 8))); 54 | this.producingResources.register(LOG, new ResourceHolder(Misc.random(5, 8))); 55 | 56 | this.makeLogs = new ResourceConversion() { 57 | { 58 | this.consume(TREE, 2); 59 | this.produce(LOG, 1); 60 | } 61 | }; 62 | } 63 | 64 | @Override 65 | public void ai() throws SuspendExecution { 66 | 67 | GameItem lastTree = null; 68 | 69 | while (true) { 70 | this.survive(); 71 | 72 | lastTree = this.gatherWood(lastTree); 73 | 74 | this.dumpWood(); 75 | 76 | VirtualThread.sleep(1000); 77 | } 78 | } 79 | 80 | public int chop(GameItem tree) throws SuspendExecution { 81 | 82 | int transfer = tree.transfer(TREE, this, 1); 83 | if (tree.producingResources.get(TREE).isEmpty()) { 84 | tree.kill(); 85 | } 86 | 87 | return transfer; 88 | } 89 | 90 | private GameItem gatherWood(GameItem tree) throws SuspendExecution { 91 | while (!this.producingResources.get(LOG).isFull()) { 92 | this.survive(); 93 | 94 | this.task = "looking for a tree"; 95 | if (tree == null || !tree.isAlive()) { 96 | tree = this.findNearestTree(); 97 | if (tree == null) { 98 | break; 99 | } 100 | } 101 | 102 | this.task = ((Math.random() < 0.1) ? 't' : 'w') + "alking to tree"; 103 | this.moveTo(tree.position); 104 | 105 | this.task = "chopping tree"; 106 | while (this.chop(tree) > 0) { 107 | VirtualThread.sleep(Misc.random(500, 1500)); 108 | this.survive(); 109 | } 110 | 111 | this.task = "chopping tree into logs"; 112 | do { 113 | VirtualThread.sleep(Misc.random(500, 1500)); 114 | this.survive(); 115 | } while (this.makeLogs.convert(this)); 116 | } 117 | return tree; 118 | } 119 | 120 | private void dumpWood() throws SuspendExecution { 121 | while (!this.producingResources.get(LOG).isEmpty()) { 122 | this.task = "looking for storage"; 123 | GameItem storage = this.findNearestStorageWithFreeSpace(); 124 | if (storage == null) { 125 | break; 126 | } 127 | 128 | this.task = "dragging logs to " + storage; 129 | this.moveTo(storage.position); 130 | 131 | this.survive(); 132 | 133 | this.task = "dumping logs at " + storage; 134 | /* int dumped = */this.transfer(LOG, storage); 135 | 136 | VirtualThread.sleep(1000); 137 | } 138 | } 139 | 140 | private GameItem findNearestTree() throws SuspendExecution { 141 | return Game.nearestProducer(TREE, false, null, this.position); 142 | } 143 | 144 | private GameItem findNearestStorageWithFreeSpace() throws SuspendExecution { 145 | GameItem item1 = Game.nearestHolderWithSpace(LOG, null, this.position); 146 | GameItem item2 = Game.nearestConsumer(LOG, false, null, this.position); 147 | 148 | if (item1 != null && item2 != null) { 149 | float dist1 = Vec2.distanceSquared(item1.position, this.position); 150 | float dist2 = Vec2.distanceSquared(item2.position, this.position); 151 | return dist1 < dist2 ? item1 : item2; 152 | } 153 | 154 | return (item1 != null) ? item1 : item2; 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /src-test/net/indiespot/continuations/test/game2/Storage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012, Enhanced Four 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are 7 | * met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * * Neither the name of 'Enhanced Four' nor the names of its contributors 17 | * may be used to endorse or promote products derived from this software 18 | * without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | package net.indiespot.continuations.test.game2; 34 | 35 | import static net.indiespot.continuations.test.game.ResourceType.*; 36 | 37 | import java.awt.*; 38 | 39 | import net.indiespot.continuations.*; 40 | import net.indiespot.continuations.test.game.GameItem; 41 | import net.indiespot.continuations.test.game.Misc; 42 | import net.indiespot.continuations.test.game.ResourceHolder; 43 | import de.matthiasmann.continuations.*; 44 | 45 | public class Storage extends GameItem { 46 | 47 | @SuppressWarnings("serial") 48 | public Storage() { 49 | this.name = "storage"; 50 | this.color = Color.PINK; 51 | 52 | this.holdingResources.register(LOG, new ResourceHolder(100)); 53 | this.holdingResources.register(PLANK, new ResourceHolder(1000)); 54 | 55 | // burn off some logs to keep the place from freezing over! 56 | this.spawn(new VirtualRunnable() { 57 | @Override 58 | public void run() throws SuspendExecution { 59 | while (true) { 60 | VirtualThread.sleep(1250); 61 | 62 | holdingResources.get(LOG).take(Misc.random(1, 2)); 63 | } 64 | } 65 | }); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src-test/net/indiespot/continuations/test/game2/TestVirtualThreadsGame2.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012, Enhanced Four 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are 7 | * met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * * Neither the name of 'Enhanced Four' nor the names of its contributors 17 | * may be used to endorse or promote products derived from this software 18 | * without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | package net.indiespot.continuations.test.game2; 34 | 35 | import java.awt.event.*; 36 | 37 | import net.indiespot.continuations.test.game.Game; 38 | import net.indiespot.continuations.test.game.GameCanvas; 39 | import net.indiespot.continuations.test.game.Misc; 40 | import net.indiespot.continuations.test.game1.*; 41 | import net.indiespot.dependencies.Vec2; 42 | 43 | public class TestVirtualThreadsGame2 { 44 | public static void main(String[] args) throws Exception { 45 | GameCanvas canvas = Game.init(new Runnable() { 46 | @Override 47 | public void run() { 48 | // add trees 49 | for(int i = 0; i < 1024 / 4; i++) { 50 | Tree tree = new Tree(); 51 | tree.position.x = Misc.random(32, 1024 - 32); 52 | tree.position.y = Misc.random(32, 768 - 32); 53 | Game.addItem(tree); 54 | } 55 | 56 | // add storages 57 | for(int i = 0; i < 7; i++) { 58 | Storage storage = new Storage(); 59 | storage.position.x = Misc.random(32, 1024 - 32); 60 | storage.position.y = Misc.random(32, 768 - 32); 61 | Game.addItem(storage); 62 | } 63 | 64 | // add water 65 | for(int i = 0; i < 15; i++) { 66 | Well water = new Well(); 67 | water.position.x = Misc.random(32, 1024 - 32); 68 | water.position.y = Misc.random(32, 768 - 32); 69 | Game.addItem(water); 70 | } 71 | } 72 | }); 73 | 74 | canvas.addMouseListener(new MouseAdapter() { 75 | @Override 76 | public void mousePressed(MouseEvent e) { 77 | Vec2 p = new Vec2(e.getX(), e.getY()); 78 | 79 | // add lumberjack 80 | Lumberjack lumberjack = new Lumberjack(); 81 | lumberjack.position.load(p); 82 | Game.addItem(lumberjack); 83 | } 84 | }); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src-test/net/indiespot/continuations/test/game2/Tree.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012, Enhanced Four 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are 7 | * met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * * Neither the name of 'Enhanced Four' nor the names of its contributors 17 | * may be used to endorse or promote products derived from this software 18 | * without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | package net.indiespot.continuations.test.game2; 34 | 35 | import static net.indiespot.continuations.test.game.ResourceType.*; 36 | 37 | import java.awt.*; 38 | 39 | import net.indiespot.continuations.*; 40 | import net.indiespot.continuations.test.game.Game; 41 | import net.indiespot.continuations.test.game.GameItem; 42 | import net.indiespot.continuations.test.game.Misc; 43 | import net.indiespot.continuations.test.game.ResourceHolder; 44 | import de.matthiasmann.continuations.*; 45 | 46 | public class Tree extends GameItem { 47 | 48 | @SuppressWarnings("serial") 49 | public Tree() { 50 | this.name = null; 51 | this.color = Color.GREEN; 52 | 53 | this.producingResources.register(TREE, new ResourceHolder(Misc.random(10, 40), 50)); 54 | 55 | this.spawn(new VirtualRunnable() { 56 | @Override 57 | public void run() throws SuspendExecution { 58 | ai(); 59 | } 60 | }); 61 | } 62 | 63 | void ai() throws SuspendExecution { 64 | while (true) { 65 | VirtualThread.sleep(Misc.random(5 * 1100, 5 * 2100)); 66 | 67 | if (Math.random() < 0.01) { 68 | if (this.producingResources.get(TREE).getRatio() > 0.50f) { 69 | Tree tree = new Tree(); 70 | tree.position.x = Misc.randomBase(position.x, 32); 71 | tree.position.y = Misc.randomBase(position.y, 32); 72 | // System.out.println("new tree"); 73 | Game.addItem(tree); 74 | } 75 | } 76 | 77 | if (Math.random() < 0.1) { 78 | if (this.producingResources.get(TREE).put(1) == 1) { 79 | // System.out.println("grew tree"); 80 | color = new Color(0, 255 - (this.producingResources.get(TREE).getFilledSpace() * 2), 0); 81 | } 82 | } 83 | 84 | if (Math.random() < 0.1) { 85 | if (this.producingResources.get(TREE).getRatio() > 0.80f) { 86 | // System.out.println("killed tree"); 87 | kill(); 88 | } 89 | } 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src-test/net/indiespot/continuations/test/game3/Smith.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012, Enhanced Four 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are 7 | * met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * * Neither the name of 'Enhanced Four' nor the names of its contributors 17 | * may be used to endorse or promote products derived from this software 18 | * without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | package net.indiespot.continuations.test.game3; 34 | 35 | import static net.indiespot.continuations.test.game.ResourceType.*; 36 | 37 | import java.awt.*; 38 | 39 | import net.indiespot.continuations.*; 40 | import net.indiespot.continuations.test.game.GameItem; 41 | import net.indiespot.continuations.test.game.ResourceConversion; 42 | import net.indiespot.continuations.test.game.ResourceHolder; 43 | import de.matthiasmann.continuations.*; 44 | 45 | public class Smith extends GameItem { 46 | 47 | @SuppressWarnings("serial") 48 | public Smith() { 49 | this.name = "smith"; 50 | this.color = Color.MAGENTA; 51 | 52 | this.consumingResources.register(IRON, new ResourceHolder(100, 100)); 53 | this.consumingResources.register(LOG, new ResourceHolder(100)); 54 | this.producingResources.register(TOOL, new ResourceHolder(25)); 55 | 56 | final ResourceConversion makeTools = new ResourceConversion() { 57 | { 58 | this.consume(IRON, 1); 59 | this.consume(LOG, 1); 60 | this.produce(TOOL, 2); 61 | } 62 | }; 63 | 64 | this.spawn(new VirtualRunnable() { 65 | @Override 66 | public void run() throws SuspendExecution { 67 | while (true) { 68 | VirtualThread.sleep(1250); 69 | 70 | if (makeTools.convert(Smith.this)) { 71 | System.out.println("smith made tools"); 72 | VirtualThread.sleep(5000); 73 | } 74 | } 75 | } 76 | }); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src-test/net/indiespot/continuations/test/game3/TestVirtualThreadsGame3.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012, Enhanced Four 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are 7 | * met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * * Neither the name of 'Enhanced Four' nor the names of its contributors 17 | * may be used to endorse or promote products derived from this software 18 | * without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | package net.indiespot.continuations.test.game3; 34 | 35 | import net.indiespot.continuations.test.game.Game; 36 | import net.indiespot.continuations.test.game.Misc; 37 | import net.indiespot.continuations.test.game1.*; 38 | import net.indiespot.continuations.test.game2.*; 39 | 40 | public class TestVirtualThreadsGame3 { 41 | public static void main(String[] args) throws Exception { 42 | Game.init(new Runnable() { 43 | @Override 44 | public void run() { 45 | // add trees 46 | for (int i = 0; i < 128; i++) { 47 | Tree tree = new Tree(); 48 | tree.position.x = Misc.randomBase(128, 96); 49 | tree.position.y = Misc.randomBase(128, 96); 50 | Game.addItem(tree); 51 | } 52 | for (int i = 0; i < 128; i++) { 53 | Tree tree = new Tree(); 54 | tree.position.x = Misc.randomBase(512, 96); 55 | tree.position.y = Misc.randomBase(256, 96); 56 | Game.addItem(tree); 57 | } 58 | 59 | // add storages 60 | for (int i = 0; i < 3; i++) { 61 | Storage storage = new Storage(); 62 | storage.position.x = Misc.randomBase(256, 256); 63 | storage.position.y = Misc.randomBase(512, 64); 64 | Game.addItem(storage); 65 | } 66 | 67 | // add lumberjacks 68 | for (int i = 0; i < 20; i++) { 69 | Lumberjack lumberjack = new Lumberjack(); 70 | lumberjack.position.x = Misc.random(32, 1024 - 32); 71 | lumberjack.position.y = Misc.random(32, 768 - 32); 72 | Game.addItem(lumberjack); 73 | } 74 | 75 | // add water 76 | for (int i = 0; i < 25; i++) { 77 | Well water = new Well(); 78 | water.position.x = Misc.random(32, 1024 - 32); 79 | water.position.y = Misc.random(32, 768 - 32); 80 | Game.addItem(water); 81 | } 82 | 83 | // --- 84 | 85 | // add woodshops 86 | for (int i = 0; i < 3; i++) { 87 | WoodShop woodShop = new WoodShop(); 88 | woodShop.position.x = Misc.randomBase(750, 200); 89 | woodShop.position.y = Misc.randomBase(400, 125); 90 | Game.addItem(woodShop); 91 | } 92 | 93 | // add smith 94 | for (int i = 0; i < 3; i++) { 95 | Smith smith = new Smith(); 96 | smith.position.x = Misc.randomBase(700, 256); 97 | smith.position.y = Misc.randomBase(130, 128); 98 | Game.addItem(smith); 99 | } 100 | 101 | // add transporter 102 | for (int i = 0; i < 4; i++) { 103 | Transporter transporter = new Transporter(); 104 | transporter.position.x = Misc.random(32, 256); 105 | transporter.position.y = Misc.random(32, 256); 106 | Game.addItem(transporter); 107 | } 108 | } 109 | }); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src-test/net/indiespot/continuations/test/game3/WoodShop.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012, Enhanced Four 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are 7 | * met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * * Neither the name of 'Enhanced Four' nor the names of its contributors 17 | * may be used to endorse or promote products derived from this software 18 | * without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | package net.indiespot.continuations.test.game3; 34 | 35 | import static net.indiespot.continuations.test.game.ResourceType.*; 36 | 37 | import java.awt.*; 38 | 39 | import net.indiespot.continuations.*; 40 | import net.indiespot.continuations.test.game.GameItem; 41 | import net.indiespot.continuations.test.game.ResourceConversion; 42 | import net.indiespot.continuations.test.game.ResourceHolder; 43 | import de.matthiasmann.continuations.*; 44 | 45 | public class WoodShop extends GameItem { 46 | 47 | @SuppressWarnings("serial") 48 | public WoodShop() { 49 | this.name = "woodshop"; 50 | this.color = Color.ORANGE; 51 | 52 | this.consumingResources.register(TOOL, new ResourceHolder(20, 20)); 53 | this.consumingResources.register(LOG, new ResourceHolder(100)); 54 | this.producingResources.register(PLANK, new ResourceHolder(250)); 55 | 56 | final ResourceConversion makePlanks = new ResourceConversion() { 57 | { 58 | this.consume(TOOL, 1); 59 | this.consume(LOG, 1); 60 | this.produce(PLANK, 8); 61 | } 62 | }; 63 | 64 | this.spawn(new VirtualRunnable() { 65 | @Override 66 | public void run() throws SuspendExecution { 67 | while (true) { 68 | VirtualThread.sleep(1250); 69 | 70 | if (makePlanks.convert(WoodShop.this)) { 71 | System.out.println("woodshop made planks!"); 72 | VirtualThread.sleep(5000); 73 | } 74 | } 75 | } 76 | }); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src-test/net/indiespot/continuations/test/game4/Commander.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012, Enhanced Four 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are 7 | * met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * * Neither the name of 'Enhanced Four' nor the names of its contributors 17 | * may be used to endorse or promote products derived from this software 18 | * without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | package net.indiespot.continuations.test.game4; 34 | 35 | import java.awt.*; 36 | import java.util.*; 37 | import java.util.List; 38 | import java.util.concurrent.*; 39 | 40 | import net.indiespot.continuations.*; 41 | import net.indiespot.continuations.test.game1.*; 42 | import net.indiespot.dependencies.CircularArrayList; 43 | import net.indiespot.dependencies.Vec2; 44 | import de.matthiasmann.continuations.*; 45 | 46 | public class Commander extends Human { 47 | public Commander() { 48 | this.name = "commander"; 49 | this.color = Color.RED; 50 | } 51 | 52 | public void addSoldier(Soldier soldier) { 53 | if(soldier.commander != null) { 54 | throw new IllegalStateException(); 55 | } 56 | if(this.soldiers.contains(soldier)) { 57 | throw new IllegalStateException(); 58 | } 59 | 60 | soldier.commander = this; 61 | this.soldiers.add(soldier); 62 | } 63 | 64 | public void removeSoldier(Soldier soldier) { 65 | if(soldier.commander != this) { 66 | throw new IllegalStateException(); 67 | } 68 | if(!this.soldiers.contains(soldier)) { 69 | throw new IllegalStateException(); 70 | } 71 | 72 | soldier.commander = null; 73 | this.soldiers.remove(soldier); 74 | } 75 | 76 | public final List soldiers = new CopyOnWriteArrayList<>(); 77 | public final CircularArrayList goToQueue = new CircularArrayList<>(); 78 | public final CircularArrayList goToForwards = new CircularArrayList<>(); 79 | 80 | @Override 81 | public void ai() throws SuspendExecution { 82 | final float spacing = 32.0f; 83 | 84 | while (true) { 85 | Vec2 goTo = goToQueue.pollFirst(); 86 | if(goTo == null) { 87 | this.task = "idling"; 88 | VirtualThread.sleep(1000); 89 | this.survive(); 90 | continue; 91 | } 92 | boolean isForward = goToForwards.removeFirst().booleanValue(); 93 | 94 | this.task = "calling..."; 95 | this.requestLayout(this.position, spacing, goTo, isForward); 96 | VirtualThread.sleep(1000); 97 | 98 | this.task = "waiting..."; 99 | this.waitForSoldiersArrived(); 100 | 101 | this.task = "line up platoon..."; 102 | this.requestLayout(goTo, spacing, new Vec2(goTo).sub(this.position).add(goTo), isForward); 103 | 104 | this.task = "marching!"; 105 | this.moveTo(goTo); 106 | } 107 | } 108 | 109 | @Override 110 | public void onRemove() { 111 | for(Soldier soldier : soldiers) { 112 | this.removeSoldier(soldier); 113 | } 114 | 115 | super.onRemove(); 116 | } 117 | 118 | private void requestLayout(Vec2 origin, float spacing, Vec2 target, boolean isForward) { 119 | List positions = this.calcLayout(origin, spacing, target, isForward); 120 | if(positions == null) { 121 | return; 122 | } 123 | 124 | for(int i = 0; i < soldiers.size(); i++) { 125 | soldiers.get(i).requestMoveTo(positions.get(i)); 126 | } 127 | } 128 | 129 | private List calcLayout(Vec2 origin, float spacing, Vec2 target, boolean isForward) { 130 | int count = this.soldiers.size(); 131 | if(count == 0) { 132 | return null; 133 | } 134 | 135 | int w = (int) Math.ceil(Math.sqrt(count) * 0.50f); 136 | int h = (int) Math.ceil(count / (float) w); 137 | 138 | float angle = (float) Math.toDegrees(Math.atan2(origin.y - target.y, origin.x - target.x)); 139 | if(!isForward) { 140 | angle += 180.0f; 141 | } 142 | 143 | float sin = (float) Math.sin(Math.toRadians(angle)); 144 | float cos = (float) Math.cos(Math.toRadians(angle)); 145 | 146 | List layout = new ArrayList<>(); 147 | for(int i = 0; i < count; i++) { 148 | int x = i % w; 149 | int y = i / w; 150 | 151 | float px = (x - w * 0.5f + 0.5f) * spacing; 152 | float py = (y - h * 0.5f + 0.5f) * spacing; 153 | px -= 48; 154 | float px2 = cos * px - sin * py; 155 | float py2 = sin * px + cos * py; 156 | 157 | layout.add(new Vec2(px2, py2).add(origin)); 158 | } 159 | 160 | return layout; 161 | } 162 | 163 | private void waitForSoldiersArrived() throws SuspendExecution { 164 | System.out.println(this + " waiting for soldiers"); 165 | for(Soldier soldier : soldiers) { 166 | while (soldier.isAlive() && !soldier.moveToRequests.isEmpty()) { 167 | VirtualThread.sleep(250); 168 | this.survive(); 169 | } 170 | } 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /src-test/net/indiespot/continuations/test/game4/Soldier.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012, Enhanced Four 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are 7 | * met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * * Neither the name of 'Enhanced Four' nor the names of its contributors 17 | * may be used to endorse or promote products derived from this software 18 | * without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | package net.indiespot.continuations.test.game4; 34 | 35 | import net.indiespot.continuations.*; 36 | import net.indiespot.continuations.test.game.Misc; 37 | import net.indiespot.continuations.test.game1.*; 38 | import net.indiespot.dependencies.CircularArrayList; 39 | import net.indiespot.dependencies.Vec2; 40 | import de.matthiasmann.continuations.*; 41 | 42 | public class Soldier extends Human { 43 | public Commander commander; 44 | 45 | public Soldier() { 46 | this.name = "soldier"; 47 | this.displayLabels = false; 48 | } 49 | 50 | @Override 51 | public void ai() throws SuspendExecution { 52 | while (true) { 53 | if (commander == null) { 54 | this.task = "bored!"; 55 | VirtualThread.sleep(1000); 56 | this.survive(); 57 | continue; 58 | } 59 | 60 | Vec2 requestMoveTo = moveToRequests.peekFirst(); 61 | if (requestMoveTo == null) { 62 | this.task = "idling..."; 63 | VirtualThread.sleep(100); 64 | 65 | if (this.isThirsty()) { 66 | // desert from the army! 67 | Commander commander = this.commander; 68 | if (commander != null) { 69 | commander.removeSoldier(this); 70 | } 71 | { 72 | this.survive(); 73 | } 74 | // join the ranks again 75 | if (commander != null && commander.isAlive()) { 76 | commander.addSoldier(this); 77 | } 78 | } 79 | 80 | Vec2 pos = new Vec2(this.position); 81 | pos.x = Misc.randomBase(pos.x, 0.25f); 82 | pos.y = Misc.randomBase(pos.y, 0.25f); 83 | this.moveTo(pos); 84 | continue; 85 | } 86 | 87 | this.task = "moving to requested location"; 88 | this.moveTo(requestMoveTo); 89 | moveToRequests.removeFirst(); 90 | } 91 | } 92 | 93 | @Override 94 | public void onRemove() { 95 | if (commander != null) { 96 | commander.removeSoldier(this); 97 | } 98 | 99 | super.onRemove(); 100 | } 101 | 102 | public final CircularArrayList moveToRequests = new CircularArrayList<>(); 103 | 104 | public void requestMoveTo(Vec2 pos) { 105 | moveToRequests.addLast(pos); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src-test/net/indiespot/continuations/test/game4/TestVirtualThreadsGame4.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012, Enhanced Four 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are 7 | * met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * * Neither the name of 'Enhanced Four' nor the names of its contributors 17 | * may be used to endorse or promote products derived from this software 18 | * without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | package net.indiespot.continuations.test.game4; 34 | 35 | import java.awt.event.*; 36 | 37 | import net.indiespot.continuations.test.game.Game; 38 | import net.indiespot.continuations.test.game.GameCanvas; 39 | import net.indiespot.continuations.test.game.Misc; 40 | import net.indiespot.continuations.test.game.ResourceType; 41 | import net.indiespot.continuations.test.game1.*; 42 | import net.indiespot.dependencies.Vec2; 43 | 44 | public class TestVirtualThreadsGame4 { 45 | 46 | static Commander commander; 47 | 48 | public static void main(String[] args) throws Exception { 49 | GameCanvas canvas = Game.init(new Runnable() { 50 | @Override 51 | public void run() { 52 | // add water 53 | for (int i = 0; i < 7; i++) { 54 | Well water = new Well(); 55 | water.position.x = Misc.random(32, 1024 - 32); 56 | water.position.y = Misc.random(32, 768 - 32); 57 | Game.addItem(water); 58 | } 59 | 60 | // add commander 61 | { 62 | commander = new Commander(); 63 | commander.speed = Misc.random(30, 35); // fat bastard 64 | commander.position.x = 1024 / 2; 65 | commander.position.y = 768 / 2; 66 | commander.consumingResources.get(ResourceType.WATER).grow(50); 67 | commander.consumingResources.get(ResourceType.WATER).fill(); 68 | Game.addItem(commander); 69 | } 70 | 71 | // add soldiers 72 | for (int i = 0; i < 23; i++) { 73 | Soldier soldier = new Soldier(); 74 | soldier.speed = Misc.random(50, 60); // slim bastards 75 | // soldier.consumingResources.get(ResourceType.WATER).grow(50); 76 | soldier.consumingResources.get(ResourceType.WATER).fill(); 77 | soldier.position.x = Misc.randomBase(1024 / 2, 256); 78 | soldier.position.y = Misc.randomBase(768 / 2, 256); 79 | Game.addItem(soldier); 80 | 81 | commander.addSoldier(soldier); 82 | } 83 | } 84 | }); 85 | 86 | canvas.addMouseListener(new MouseAdapter() { 87 | @Override 88 | public void mousePressed(MouseEvent e) { 89 | Vec2 p = new Vec2(e.getX(), e.getY()); 90 | 91 | commander.goToQueue.addLast(p); 92 | commander.goToForwards.addLast(Boolean.valueOf(e.getButton() == 1)); 93 | } 94 | }); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src-test/net/indiespot/continuations/test/nio/VirtualThreadNIO.java: -------------------------------------------------------------------------------- 1 | package net.indiespot.continuations.test.nio; 2 | 3 | import java.io.IOException; 4 | import java.net.InetSocketAddress; 5 | import java.net.SocketAddress; 6 | import java.net.SocketTimeoutException; 7 | import java.nio.ByteBuffer; 8 | import java.nio.channels.ServerSocketChannel; 9 | import java.nio.channels.SocketChannel; 10 | 11 | import net.indiespot.continuations.VirtualProcessor; 12 | import net.indiespot.continuations.VirtualRunnable; 13 | import net.indiespot.continuations.VirtualThread; 14 | import de.matthiasmann.continuations.SuspendExecution; 15 | 16 | public class VirtualThreadNIO { 17 | @SuppressWarnings("serial") 18 | public static void main(String[] args) { 19 | 20 | final VirtualProcessor processor = new VirtualProcessor(); 21 | 22 | // create virtual threads (or green threads, if you will) 23 | 24 | new VirtualThread(new VirtualRunnable() { 25 | @Override 26 | public void run() throws SuspendExecution { 27 | try { 28 | ServerSocketChannel ssc = ServerSocketChannel.open(); 29 | ssc.configureBlocking(false); 30 | ssc.bind(new InetSocketAddress("127.0.0.1", 8282), 50); 31 | System.out.println("listening: " + ssc); 32 | 33 | handleServerSocket(ssc); 34 | } 35 | catch (IOException exc) { 36 | exc.printStackTrace(); 37 | } 38 | } 39 | }).start(); 40 | 41 | long lastSecond = now(); 42 | int runsLastSecond = 0; 43 | do { 44 | runsLastSecond += processor.tick(now()); 45 | 46 | if(now() > lastSecond + 1000) { 47 | System.out.println("VirtualProcessor: " + runsLastSecond + " runs / sec"); 48 | 49 | runsLastSecond = 0; 50 | lastSecond += 1000L; 51 | } 52 | 53 | try { 54 | Thread.sleep(1); 55 | } 56 | catch (InterruptedException exc) { 57 | // ignore 58 | } 59 | } 60 | while (processor.hasPendingTasks()); 61 | } 62 | 63 | @SuppressWarnings("serial") 64 | static void handleServerSocket(ServerSocketChannel serverSocket) throws SuspendExecution, IOException { 65 | 66 | while (true) { 67 | SocketChannel sc = accept(serverSocket); 68 | System.out.println("accepted: " + sc); 69 | 70 | sc.configureBlocking(false); 71 | 72 | final SocketChannel socket = sc; 73 | new VirtualThread(new VirtualRunnable() { 74 | @Override 75 | public void run() throws SuspendExecution { 76 | handleSocket(socket); 77 | } 78 | }).start(); 79 | } 80 | } 81 | 82 | static void handleSocket(SocketChannel socket) throws SuspendExecution { 83 | ByteBuffer bb = ByteBuffer.allocateDirect(64 * 1024); 84 | 85 | SocketAddress id = null; 86 | byte[] httpHeaderEnd = Text.ascii("\r\n\r\n"); 87 | 88 | try { 89 | id = socket.getRemoteAddress(); 90 | 91 | while (true) { 92 | int got = read(socket, bb, 5000); 93 | if(got == -1) { 94 | break; 95 | } 96 | 97 | // ends with "\r\n\r\n" 98 | if(bb.position() < httpHeaderEnd.length) { 99 | continue; 100 | } 101 | for(int i = 0; i < httpHeaderEnd.length; i++) { 102 | if(bb.get(bb.position() - httpHeaderEnd.length + i) != '\r') { 103 | continue; 104 | } 105 | } 106 | 107 | // bb.flip(); 108 | // byte[] data = new byte[bb.remaining()]; 109 | // bb.get(data); 110 | // System.out.print(Text.ascii(data)); 111 | 112 | bb.clear(); 113 | bb.put(Text.ascii("HTTP/1.1 200 OK\r\n")); 114 | bb.put(Text.ascii("Content-Type: text.plain\r\n")); 115 | bb.put(Text.ascii("Transfer-Encoding: chunked\r\n")); 116 | bb.put(Text.ascii("\r\n")); 117 | bb.put(Text.ascii("4\r\n")); 118 | bb.put(Text.ascii("w00t\r\n")); 119 | bb.put(Text.ascii("0\r\n")); 120 | bb.put(Text.ascii("\r\n")); 121 | bb.flip(); 122 | write(socket, bb); 123 | bb.clear(); 124 | } 125 | } 126 | catch (IOException exc) { 127 | System.err.println("i/o error: " + exc.getClass().getName() + ": " + exc.getMessage()); 128 | } 129 | finally { 130 | System.out.println("diconnected: " + id); 131 | 132 | try { 133 | socket.close(); // TODO: this is blocking 134 | } 135 | catch (IOException exc) { 136 | // ignore 137 | } 138 | } 139 | } 140 | 141 | static SocketChannel accept(ServerSocketChannel serverSocket) throws SuspendExecution, IOException { 142 | for(int sleep = 0; true; sleep = incSleep(sleep)) { 143 | SocketChannel sc = serverSocket.accept(); 144 | if(sc != null) { 145 | return sc; 146 | } 147 | 148 | VirtualThread.sleep(sleep); 149 | } 150 | } 151 | 152 | static int read(SocketChannel socket, ByteBuffer bb, int timeout) throws SuspendExecution, IOException { 153 | if(!bb.hasRemaining()) { 154 | throw new IllegalStateException(); 155 | } 156 | 157 | int duration = 0; 158 | for(int sleep = 0; true; sleep = incSleep(sleep)) { 159 | int got = socket.read(bb); 160 | if(got != 0) { 161 | return got; 162 | } 163 | 164 | if(duration + sleep > timeout) { 165 | sleep = timeout - duration; 166 | } 167 | 168 | VirtualThread.sleep(sleep); 169 | duration += sleep; 170 | 171 | if(duration >= timeout) { 172 | throw new SocketTimeoutException(); 173 | } 174 | } 175 | } 176 | 177 | static void write(SocketChannel socket, ByteBuffer bb) throws SuspendExecution, IOException { 178 | if(!bb.hasRemaining()) { 179 | throw new IllegalStateException(); 180 | } 181 | 182 | for(int sleep = 0; bb.hasRemaining(); sleep = incSleep(sleep)) { 183 | int got = socket.write(bb); 184 | if(got == 0) { 185 | VirtualThread.sleep(sleep); 186 | } 187 | else { 188 | sleep = 0; 189 | } 190 | } 191 | } 192 | 193 | private static int incSleep(int sleep) { 194 | return Math.min(25 + (int) (sleep * 1.25f), 1000); 195 | } 196 | 197 | private static class Text { 198 | public static byte[] ascii(String s) { 199 | char[] c = s.toCharArray(); 200 | byte[] b = new byte[c.length]; 201 | for(int i = 0; i < c.length; i++) 202 | b[i] = (byte) c[i]; 203 | return b; 204 | } 205 | } 206 | 207 | static long now() { 208 | return System.nanoTime() / 1_000_000L; 209 | } 210 | } 211 | -------------------------------------------------------------------------------- /src/de/matthiasmann/continuations/CoIterator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2008-2013, Matthias Mann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * * Neither the name of Matthias Mann nor the names of its 14 | * contributors may be used to endorse or promote products derived from 15 | * this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | * POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | package de.matthiasmann.continuations; 30 | 31 | import java.io.Serializable; 32 | import java.util.Iterator; 33 | import java.util.NoSuchElementException; 34 | 35 | /** 36 | * A Coroutine based iterator 37 | * 38 | * @param the element class that the Iterator returns 39 | * @author Matthias Mann 40 | */ 41 | public abstract class CoIterator implements Iterator, Serializable { 42 | 43 | private static final long serialVersionUID = 351278561539L; 44 | 45 | private final Coroutine co; 46 | 47 | private E element; 48 | private boolean hasElement; 49 | 50 | protected CoIterator() { 51 | co = new Coroutine(new DelegateExecute()); 52 | } 53 | 54 | public boolean hasNext() { 55 | while(!hasElement && co.getState() != Coroutine.State.FINISHED) { 56 | co.run(); 57 | } 58 | return hasElement; 59 | } 60 | 61 | public E next() { 62 | if(!hasNext()) { 63 | throw new NoSuchElementException(); 64 | } 65 | E result = element; 66 | hasElement = false; 67 | element = null; 68 | return result; 69 | } 70 | 71 | /** 72 | * Always throws UnsupportedOperationException. 73 | * @throws java.lang.UnsupportedOperationException always 74 | */ 75 | public void remove() throws UnsupportedOperationException { 76 | throw new UnsupportedOperationException("Not supported"); 77 | } 78 | 79 | /** 80 | * Produces the next value to be returned by the {@link #next} method. 81 | * 82 | * @param element The value that should be returned by {@link #next} 83 | * @throws de.matthiasmann.continuations.SuspendExecution This method will suspend the execution 84 | */ 85 | protected void produce(E element) throws SuspendExecution { 86 | if(hasElement) { 87 | throw new IllegalStateException("hasElement = true"); 88 | } 89 | this.element = element; 90 | hasElement = true; 91 | Coroutine.yield(); 92 | } 93 | 94 | /** 95 | *

This is the body of the Iterator. This method is executed as a 96 | * {@link Coroutine} to {@link #produce} the values of the Iterator.

97 | * 98 | *

Note that this method is suspended each time it calls produce. And if 99 | * the consumer does not consume all values of the Iterator then this 100 | * method does not get the change to finish it's execution. This also 101 | * includes the finally blocks.

102 | * 103 | *

This method must only suspend by calling produce. Any other reason 104 | * for suspension will cause a busy loop in the Iterator.

105 | * 106 | * @throws de.matthiasmann.continuations.SuspendExecution 107 | */ 108 | protected abstract void run() throws SuspendExecution; 109 | 110 | private class DelegateExecute implements CoroutineProto, Serializable { 111 | private static final long serialVersionUID = 12784529515412L; 112 | 113 | public void coExecute() throws SuspendExecution { 114 | CoIterator.this.run(); 115 | } 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/de/matthiasmann/continuations/CoroutineProto.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2008, Matthias Mann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * * Neither the name of Matthias Mann nor the names of its 14 | * contributors may be used to endorse or promote products derived from 15 | * this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | * POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | package de.matthiasmann.continuations; 30 | 31 | /** 32 | * A class that implements this interface can be run as a Coroutine. 33 | * 34 | * @see Coroutine 35 | * @author Matthias Mann 36 | */ 37 | public interface CoroutineProto { 38 | 39 | /** 40 | * Entry point for Coroutine execution. 41 | * 42 | * This method should never be called directly. 43 | * 44 | * @see Coroutine#Coroutine(de.matthiasmann.continuations.CoroutineProto) 45 | * @see Coroutine#run() 46 | * @see SuspendExecution 47 | * @throws de.matthiasmann.continuations.SuspendExecution This exception should never be cought 48 | */ 49 | public void coExecute() throws SuspendExecution; 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/de/matthiasmann/continuations/SomeInterface.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this template, choose Tools | Templates 3 | * and open the template in the editor. 4 | */ 5 | 6 | package de.matthiasmann.continuations; 7 | 8 | /** 9 | * A dummy interface used for the InterfaceTest 10 | * 11 | * @author Elias Naur 12 | */ 13 | public interface SomeInterface { 14 | 15 | void doStuff() throws SuspendExecution; 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/de/matthiasmann/continuations/SuspendExecution.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2008, Matthias Mann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * * Neither the name of Matthias Mann nor the names of its 14 | * contributors may be used to endorse or promote products derived from 15 | * this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | * POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | package de.matthiasmann.continuations; 30 | 31 | /** 32 | *

An exception used to initiate the control transfer.

33 | *

It does not support stack traces.

34 | * 35 | *

Methods which are declared to throw this exception are "suspendable". This 36 | * exception must always be propagated and never be caught.

37 | * 38 | *

Generic try/catch handlers are allowed:
39 | * {@code try{ doSomething(); } catch(Throwable ex) { handleException(ex); } }

40 | * 41 | *

The instrumentation ANT task will enhance the bytecode of these methods to 42 | * support suspension and continuation of their execution.

43 | * 44 | * @author Matthias Mann 45 | */ 46 | @SuppressWarnings("serial") 47 | public final class SuspendExecution extends Exception { 48 | 49 | static final SuspendExecution instance = new SuspendExecution(); 50 | 51 | private SuspendExecution() { 52 | } 53 | 54 | @Override 55 | public Throwable fillInStackTrace() { 56 | return this; 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/de/matthiasmann/continuations/Util.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2008, Matthias Mann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * * Neither the name of Matthias Mann nor the names of its 14 | * contributors may be used to endorse or promote products derived from 15 | * this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | * POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | package de.matthiasmann.continuations; 30 | 31 | /** 32 | * 33 | * @author Matthias Mann 34 | */ 35 | public class Util { 36 | 37 | public static int[] copyOf(int[] src, int size) { 38 | int[] dst = new int[size]; 39 | System.arraycopy(src, 0, dst, 0, Math.min(src.length, size)); 40 | return dst; 41 | } 42 | 43 | public static long[] copyOf(long[] src, int size) { 44 | long[] dst = new long[size]; 45 | System.arraycopy(src, 0, dst, 0, Math.min(src.length, size)); 46 | return dst; 47 | } 48 | 49 | public static Object[] copyOf(Object[] src, int size) { 50 | Object[] dst = new Object[size]; 51 | System.arraycopy(src, 0, dst, 0, Math.min(src.length, size)); 52 | return dst; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/de/matthiasmann/continuations/instrument/AlreadyInstrumented.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2008, Matthias Mann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * * Neither the name of Matthias Mann nor the names of its 14 | * contributors may be used to endorse or promote products derived from 15 | * this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | * POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | package de.matthiasmann.continuations.instrument; 30 | 31 | import java.lang.annotation.ElementType; 32 | import java.lang.annotation.Retention; 33 | import java.lang.annotation.RetentionPolicy; 34 | import java.lang.annotation.Target; 35 | 36 | /** 37 | * An annotation used to mark a class as instrumented. 38 | * It must never be used in Java source code. 39 | * 40 | * @author Matthias Mann 41 | */ 42 | @Target(ElementType.TYPE) 43 | @Retention(RetentionPolicy.RUNTIME) 44 | public @interface AlreadyInstrumented { 45 | } 46 | -------------------------------------------------------------------------------- /src/de/matthiasmann/continuations/instrument/CheckInstrumentationVisitor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2008-2013, Matthias Mann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * * Neither the name of Matthias Mann nor the names of its 14 | * contributors may be used to endorse or promote products derived from 15 | * this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | * POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | package de.matthiasmann.continuations.instrument; 30 | 31 | import de.matthiasmann.continuations.SuspendExecution; 32 | import de.matthiasmann.continuations.instrument.MethodDatabase.ClassEntry; 33 | import org.objectweb.asm.AnnotationVisitor; 34 | import org.objectweb.asm.ClassVisitor; 35 | import org.objectweb.asm.MethodVisitor; 36 | import org.objectweb.asm.Opcodes; 37 | import org.objectweb.asm.Type; 38 | 39 | /** 40 | * Check if a class contains suspendable methods. 41 | * Basicly this class checks if a method is declared to throw {@link SuspendExecution}. 42 | * 43 | * @author Matthias Mann 44 | */ 45 | public class CheckInstrumentationVisitor extends ClassVisitor { 46 | 47 | static final String EXCEPTION_NAME = Type.getInternalName(SuspendExecution.class); 48 | static final String EXCEPTION_DESC = Type.getDescriptor(SuspendExecution.class); 49 | 50 | private String className; 51 | private ClassEntry classEntry; 52 | private boolean hasSuspendable; 53 | private boolean alreadyInstrumented; 54 | 55 | public CheckInstrumentationVisitor() { 56 | super(Opcodes.ASM4); 57 | } 58 | 59 | public boolean needsInstrumentation() { 60 | return hasSuspendable; 61 | } 62 | 63 | ClassEntry getClassEntry() { 64 | return classEntry; 65 | } 66 | 67 | public String getName() { 68 | return className; 69 | } 70 | 71 | public boolean isAlreadyInstrumented() { 72 | return alreadyInstrumented; 73 | } 74 | 75 | @Override 76 | public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { 77 | this.className = name; 78 | this.classEntry = new ClassEntry(superName); 79 | } 80 | 81 | @Override 82 | public AnnotationVisitor visitAnnotation(String desc, boolean visible) { 83 | if(desc.equals(InstrumentClass.ALREADY_INSTRUMENTED_NAME)) { 84 | alreadyInstrumented = true; 85 | } 86 | return null; 87 | } 88 | 89 | @Override 90 | public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { 91 | boolean suspendable = checkExceptions(exceptions); 92 | if(suspendable) { 93 | hasSuspendable = true; 94 | // synchronized methods can't be made suspendable 95 | if((access & Opcodes.ACC_SYNCHRONIZED) == Opcodes.ACC_SYNCHRONIZED) { 96 | throw new UnableToInstrumentException("synchronized method", className, name, desc); 97 | } 98 | } 99 | classEntry.set(name, desc, suspendable); 100 | return null; 101 | } 102 | 103 | public static boolean checkExceptions(String[] exceptions) { 104 | if(exceptions != null) { 105 | for(String ex : exceptions) { 106 | if(ex.equals(EXCEPTION_NAME)) { 107 | return true; 108 | } 109 | } 110 | } 111 | return false; 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/de/matthiasmann/continuations/instrument/DBClassWriter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2008-2013, Matthias Mann 3 | * 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * * Neither the name of Matthias Mann nor the names of its contributors may 15 | * be used to endorse or promote products derived from this software 16 | * without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 22 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 23 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 25 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 26 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 27 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | package de.matthiasmann.continuations.instrument; 31 | 32 | import org.objectweb.asm.ClassReader; 33 | import org.objectweb.asm.ClassWriter; 34 | 35 | /** 36 | * 37 | * @author Matthias Mann 38 | */ 39 | public class DBClassWriter extends ClassWriter { 40 | 41 | private final MethodDatabase db; 42 | 43 | public DBClassWriter(MethodDatabase db, ClassReader classReader) { 44 | super(classReader, COMPUTE_FRAMES | COMPUTE_MAXS); 45 | this.db = db; 46 | } 47 | 48 | @Override 49 | protected String getCommonSuperClass(String type1, String type2) { 50 | return db.getCommonSuperClass(type1, type2); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/de/matthiasmann/continuations/instrument/ExtractSuperClass.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2008-2012, Matthias Mann 3 | * 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * * Neither the name of Matthias Mann nor the names of its contributors may 15 | * be used to endorse or promote products derived from this software 16 | * without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 22 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 23 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 25 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 26 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 27 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | package de.matthiasmann.continuations.instrument; 31 | 32 | import org.objectweb.asm.ClassVisitor; 33 | import org.objectweb.asm.Opcodes; 34 | 35 | /** 36 | * 37 | * @author Matthias Mann 38 | */ 39 | public class ExtractSuperClass extends ClassVisitor { 40 | 41 | String superClass; 42 | 43 | public ExtractSuperClass() { 44 | super(Opcodes.ASM4); 45 | } 46 | 47 | @Override 48 | public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { 49 | this.superClass = superName; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/de/matthiasmann/continuations/instrument/InstrumentClass.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2008-2013, Matthias Mann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * * Neither the name of Matthias Mann nor the names of its 14 | * contributors may be used to endorse or promote products derived from 15 | * this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | * POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | package de.matthiasmann.continuations.instrument; 30 | 31 | import de.matthiasmann.continuations.Coroutine; 32 | import de.matthiasmann.continuations.instrument.MethodDatabase.ClassEntry; 33 | 34 | import java.util.ArrayList; 35 | import java.util.List; 36 | 37 | import org.objectweb.asm.AnnotationVisitor; 38 | import org.objectweb.asm.ClassVisitor; 39 | import org.objectweb.asm.MethodVisitor; 40 | import org.objectweb.asm.Opcodes; 41 | import org.objectweb.asm.Type; 42 | import org.objectweb.asm.tree.MethodNode; 43 | import org.objectweb.asm.tree.analysis.AnalyzerException; 44 | 45 | /** 46 | * Instrument a class by instrumenting all suspendable methods and copying the 47 | * others. 48 | * 49 | * @author Matthias Mann 50 | */ 51 | @SuppressWarnings("all") 52 | public class InstrumentClass extends ClassVisitor { 53 | 54 | static final String COROUTINE_NAME = Type.getInternalName(Coroutine.class); 55 | static final String ALREADY_INSTRUMENTED_NAME = Type.getDescriptor(AlreadyInstrumented.class); 56 | 57 | private final MethodDatabase db; 58 | private final boolean forceInstrumentation; 59 | private String className; 60 | private ClassEntry classEntry; 61 | private boolean alreadyInstrumented; 62 | private ArrayList methods; 63 | 64 | public InstrumentClass(ClassVisitor cv, MethodDatabase db, boolean forceInstrumentation) { 65 | super(Opcodes.ASM4, cv); 66 | 67 | this.db = db; 68 | this.forceInstrumentation = forceInstrumentation; 69 | } 70 | 71 | @Override 72 | public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { 73 | this.className = name; 74 | this.classEntry = new ClassEntry(superName); 75 | 76 | // need atleast 1.5 for annotations to work 77 | if(version < Opcodes.V1_5) { 78 | version = Opcodes.V1_5; 79 | } 80 | 81 | super.visit(version, access, name, signature, superName, interfaces); 82 | } 83 | 84 | @Override 85 | public AnnotationVisitor visitAnnotation(String desc, boolean visible) { 86 | if(desc.equals(InstrumentClass.ALREADY_INSTRUMENTED_NAME)) { 87 | alreadyInstrumented = true; 88 | } 89 | return super.visitAnnotation(desc, visible); 90 | } 91 | 92 | @Override 93 | public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { 94 | boolean suspendable = CheckInstrumentationVisitor.checkExceptions(exceptions); 95 | classEntry.set(name, desc, suspendable); 96 | 97 | if(suspendable && checkAccess(access) && !(className.equals(COROUTINE_NAME) && name.equals("yield"))) { 98 | if(db.isDebug()) { 99 | db.log(LogLevel.INFO, "Instrumenting method %s#%s", className, name); 100 | } 101 | 102 | if(methods == null) { 103 | methods = new ArrayList(); 104 | } 105 | 106 | MethodNode mn = new MethodNode(access, name, desc, signature, exceptions); 107 | methods.add(mn); 108 | return mn; 109 | } 110 | return super.visitMethod(access, name, desc, signature, exceptions); 111 | } 112 | 113 | @Override 114 | @SuppressWarnings("CallToThreadDumpStack") 115 | public void visitEnd() { 116 | db.recordSuspendableMethods(className, classEntry); 117 | 118 | if(methods != null) { 119 | if(alreadyInstrumented && !forceInstrumentation) { 120 | for(MethodNode mn : methods) { 121 | mn.accept(makeOutMV(mn)); 122 | } 123 | } 124 | else { 125 | if(!alreadyInstrumented) { 126 | super.visitAnnotation(ALREADY_INSTRUMENTED_NAME, true); 127 | } 128 | 129 | for(MethodNode mn : methods) { 130 | MethodVisitor outMV = makeOutMV(mn); 131 | try { 132 | InstrumentMethod im = new InstrumentMethod(db, className, mn); 133 | if(im.collectCodeBlocks()) { 134 | if(mn.name.charAt(0) == '<') { 135 | throw new UnableToInstrumentException("special method", className, mn.name, mn.desc); 136 | } 137 | im.accept(outMV); 138 | } 139 | else { 140 | mn.accept(outMV); 141 | } 142 | } 143 | catch (AnalyzerException ex) { 144 | ex.printStackTrace(); 145 | throw new InternalError(ex.getMessage()); 146 | } 147 | } 148 | } 149 | } 150 | super.visitEnd(); 151 | } 152 | 153 | private MethodVisitor makeOutMV(MethodNode mn) { 154 | return super.visitMethod(mn.access, mn.name, mn.desc, mn.signature, toStringArray(mn.exceptions)); 155 | } 156 | 157 | private static boolean checkAccess(int access) { 158 | return (access & (Opcodes.ACC_ABSTRACT | Opcodes.ACC_NATIVE)) == 0; 159 | } 160 | 161 | private static String[] toStringArray(List l) { 162 | if(l.isEmpty()) { 163 | return null; 164 | } 165 | return l.toArray(new String[l.size()]); 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /src/de/matthiasmann/continuations/instrument/Log.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2008, Matthias Mann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * * Neither the name of Matthias Mann nor the names of its 14 | * contributors may be used to endorse or promote products derived from 15 | * this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | * POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | package de.matthiasmann.continuations.instrument; 30 | 31 | /** 32 | * Allow access to the ANT logging routines 33 | * 34 | * @author Matthias Mann 35 | */ 36 | public interface Log { 37 | 38 | public void log(LogLevel level, String msg, Object ... args); 39 | 40 | public void error(String msg, Exception ex); 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/de/matthiasmann/continuations/instrument/LogLevel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2008-2013, Matthias Mann 3 | * 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * * Neither the name of Matthias Mann nor the names of its contributors may 15 | * be used to endorse or promote products derived from this software 16 | * without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 22 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 23 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 25 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 26 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 27 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | package de.matthiasmann.continuations.instrument; 31 | 32 | /** 33 | * 34 | * @author Matthias Mann 35 | */ 36 | public enum LogLevel { 37 | DEBUG, 38 | INFO, 39 | WARNING 40 | } 41 | -------------------------------------------------------------------------------- /src/de/matthiasmann/continuations/instrument/NewValue.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2008-2013, Matthias Mann 3 | * 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * * Neither the name of Matthias Mann nor the names of its contributors may 15 | * be used to endorse or promote products derived from this software 16 | * without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 22 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 23 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 25 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 26 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 27 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | package de.matthiasmann.continuations.instrument; 31 | 32 | import org.objectweb.asm.Opcodes; 33 | import org.objectweb.asm.Type; 34 | import org.objectweb.asm.tree.AbstractInsnNode; 35 | import org.objectweb.asm.tree.TypeInsnNode; 36 | import org.objectweb.asm.tree.analysis.BasicValue; 37 | 38 | /** 39 | * 40 | * @author Matthias Mann 41 | */ 42 | public class NewValue extends BasicValue { 43 | 44 | public final boolean isDupped; 45 | public final AbstractInsnNode insn; 46 | public boolean omitted; 47 | 48 | public NewValue(Type type, boolean isDupped, AbstractInsnNode insn) { 49 | super(type); 50 | this.isDupped = isDupped; 51 | this.insn = insn; 52 | } 53 | 54 | String formatInsn() { 55 | switch (insn.getOpcode()) { 56 | case Opcodes.NEW: 57 | return "NEW " + ((TypeInsnNode)insn).desc; 58 | case Opcodes.DUP: 59 | return "DUP"; 60 | default: 61 | return "UNEXPECTED INSTRUCTION: " + insn.getOpcode(); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/de/matthiasmann/continuations/instrument/OmittedInstruction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2008-2013, Matthias Mann 3 | * 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * * Neither the name of Matthias Mann nor the names of its contributors may 15 | * be used to endorse or promote products derived from this software 16 | * without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 22 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 23 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 25 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 26 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 27 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | package de.matthiasmann.continuations.instrument; 31 | 32 | import java.util.Map; 33 | 34 | import org.objectweb.asm.MethodVisitor; 35 | import org.objectweb.asm.tree.AbstractInsnNode; 36 | 37 | /** 38 | * 39 | * @author matthias 40 | */ 41 | public class OmittedInstruction extends AbstractInsnNode { 42 | 43 | private final AbstractInsnNode orgInsn; 44 | 45 | public OmittedInstruction(AbstractInsnNode orgInsn) { 46 | super(orgInsn.getOpcode()); 47 | this.orgInsn = orgInsn; 48 | } 49 | 50 | @Override 51 | public int getType() { 52 | return orgInsn.getType(); 53 | } 54 | 55 | @Override 56 | public void accept(MethodVisitor cv) { 57 | } 58 | 59 | @Override 60 | @SuppressWarnings("rawtypes") 61 | public AbstractInsnNode clone(Map labels) { 62 | return new OmittedInstruction(orgInsn.clone(labels)); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/de/matthiasmann/continuations/instrument/TypeAnalyzer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2008-2013, Matthias Mann 3 | * 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * * Neither the name of Matthias Mann nor the names of its contributors may 15 | * be used to endorse or promote products derived from this software 16 | * without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 22 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 23 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 25 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 26 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 27 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | package de.matthiasmann.continuations.instrument; 31 | 32 | import org.objectweb.asm.Opcodes; 33 | import org.objectweb.asm.Type; 34 | import org.objectweb.asm.tree.AbstractInsnNode; 35 | import org.objectweb.asm.tree.MethodInsnNode; 36 | import org.objectweb.asm.tree.analysis.Analyzer; 37 | import org.objectweb.asm.tree.analysis.AnalyzerException; 38 | import org.objectweb.asm.tree.analysis.BasicValue; 39 | import org.objectweb.asm.tree.analysis.Frame; 40 | import org.objectweb.asm.tree.analysis.Interpreter; 41 | import org.objectweb.asm.tree.analysis.Value; 42 | 43 | /** 44 | * 45 | * @author matthias 46 | */ 47 | public class TypeAnalyzer extends Analyzer { 48 | 49 | public TypeAnalyzer(MethodDatabase db) { 50 | super(new TypeInterpreter(db)); 51 | } 52 | 53 | @Override 54 | protected Frame newFrame(int nLocals, int nStack) { 55 | return new TypeFrame(nLocals, nStack); 56 | } 57 | 58 | @Override 59 | protected Frame newFrame(Frame src) { 60 | return new TypeFrame(src); 61 | } 62 | 63 | /** 64 | * Computes the number of arguments 65 | * Returns the same result as {@code Type.getArgumentTypes(desc).length } 66 | * just with no memory allocations 67 | */ 68 | static int getNumArguments(String methodDesc) { 69 | int off = 1; 70 | int size = 0; 71 | for(;;) { 72 | char car = methodDesc.charAt(off++); 73 | if (car == ')') { 74 | return size; 75 | } 76 | if (car != '[') { 77 | ++size; 78 | if (car == 'L') { 79 | off = methodDesc.indexOf(';', off) + 1; 80 | } 81 | } 82 | } 83 | } 84 | 85 | static class TypeFrame extends Frame { 86 | TypeFrame(int nLocals, int nStack) { 87 | super(nLocals, nStack); 88 | } 89 | 90 | TypeFrame(Frame src) { 91 | super(src); 92 | } 93 | 94 | @Override 95 | public void execute(AbstractInsnNode insn, Interpreter interpreter) throws AnalyzerException { 96 | switch (insn.getOpcode()) { 97 | case Opcodes.INVOKEVIRTUAL: 98 | case Opcodes.INVOKESPECIAL: 99 | case Opcodes.INVOKESTATIC: 100 | case Opcodes.INVOKEINTERFACE: { 101 | String desc = ((MethodInsnNode)insn).desc; 102 | for(int i=getNumArguments(desc) ; i>0 ; --i) { 103 | pop(); 104 | } 105 | if (insn.getOpcode() != Opcodes.INVOKESTATIC) { 106 | pop(); 107 | if(insn.getOpcode() == Opcodes.INVOKESPECIAL && getStackSize() > 0) { 108 | if("".equals(((MethodInsnNode)insn).name)) { 109 | Value value = pop(); 110 | if(value instanceof NewValue) { 111 | value = new BasicValue(((NewValue)value).getType()); 112 | } 113 | push(value); 114 | } 115 | } 116 | } 117 | Type returnType = Type.getReturnType(desc); 118 | if (returnType != Type.VOID_TYPE) { 119 | push(interpreter.newValue(returnType)); 120 | } 121 | break; 122 | } 123 | default: 124 | super.execute(insn, interpreter); 125 | } 126 | } 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /src/de/matthiasmann/continuations/instrument/UnableToInstrumentException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2008-2013, Matthias Mann 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * * Neither the name of Matthias Mann nor the names of its 14 | * contributors may be used to endorse or promote products derived from 15 | * this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | * POSSIBILITY OF SUCH DAMAGE. 28 | */ 29 | package de.matthiasmann.continuations.instrument; 30 | 31 | /** 32 | *

This exception is thrown when an unsupported construct was found in a class 33 | * that must be instrumented for suspension.

34 | * 35 | *

Note: this needs to be a RuntimeException - otherwise it can't be thrown 36 | * from {@link CheckInstrumentationVisitor}.

37 | * 38 | * @author Matthias Mann 39 | */ 40 | @SuppressWarnings("serial") 41 | public class UnableToInstrumentException extends RuntimeException { 42 | 43 | private final String reason; 44 | private final String className; 45 | private final String methodName; 46 | private final String methodDesc; 47 | 48 | public UnableToInstrumentException(String reason, String className, String methodName, String methodDesc) { 49 | super(String.format("Unable to instrument class %s#%s%s because of %s", className, methodName, methodDesc, reason)); 50 | this.reason = reason; 51 | this.className = className; 52 | this.methodName = methodName; 53 | this.methodDesc = methodDesc; 54 | } 55 | 56 | public String getClassName() { 57 | return className; 58 | } 59 | 60 | public String getMethodName() { 61 | return methodName; 62 | } 63 | 64 | public String getMethodDesc() { 65 | return methodDesc; 66 | } 67 | 68 | public String getReason() { 69 | return reason; 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /src/de/matthiasmann/continuations/instrument/UnresolvedValue.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2008-2012, Matthias Mann 3 | * 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright 12 | * notice, this list of conditions and the following disclaimer in the 13 | * documentation and/or other materials provided with the distribution. 14 | * * Neither the name of Matthias Mann nor the names of its contributors may 15 | * be used to endorse or promote products derived from this software 16 | * without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 22 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 23 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 25 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 26 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 27 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | package de.matthiasmann.continuations.instrument; 31 | 32 | import org.objectweb.asm.Type; 33 | import org.objectweb.asm.tree.analysis.BasicValue; 34 | 35 | /** 36 | * 37 | * @author Matthias Mann 38 | */ 39 | public class UnresolvedValue extends BasicValue { 40 | 41 | final BasicValue v; 42 | final BasicValue w; 43 | 44 | public UnresolvedValue(BasicValue v, BasicValue w) { 45 | super(Type.VOID_TYPE); 46 | this.v = v; 47 | this.w = w; 48 | } 49 | 50 | @Override 51 | public int getSize() { 52 | return 0; 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/de/matthiasmann/continuations/instrument/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | *

Coroutine library instrumentation ANT task

3 | *
 4 |  * Copyright (c) 2008, Matthias Mann
 5 |  * All rights reserved.
 6 |  *
 7 |  * Redistribution and use in source and binary forms, with or without
 8 |  * modification, are permitted provided that the following conditions are met:
 9 |  * 
10 |  *     * Redistributions of source code must retain the above copyright notice,
11 |  *       this list of conditions and the following disclaimer.
12 |  *     * Redistributions in binary form must reproduce the above copyright
13 |  *       notice, this list of conditions and the following disclaimer in the
14 |  *       documentation and/or other materials provided with the distribution.
15 |  *     * Neither the name of Matthias Mann nor the names of its
16 |  *       contributors may be used to endorse or promote products derived from
17 |  *       this software without specific prior written permission.
18 |  *
19 |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 |  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23 |  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 |  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 |  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 |  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 |  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 |  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 |  * POSSIBILITY OF SUCH DAMAGE.
30 |  * 
31 | * 32 | * @see de.matthiasmann.continuations.instrument.InstrumentationTask 33 | */ 34 | package de.matthiasmann.continuations.instrument; 35 | -------------------------------------------------------------------------------- /src/de/matthiasmann/continuations/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | *

Continuations Library for Coroutine support in Java.

3 | *
 4 |  * Copyright (c) 2008, Matthias Mann
 5 |  * All rights reserved.
 6 |  *
 7 |  * Redistribution and use in source and binary forms, with or without
 8 |  * modification, are permitted provided that the following conditions are met:
 9 |  * 
10 |  *     * Redistributions of source code must retain the above copyright notice,
11 |  *       this list of conditions and the following disclaimer.
12 |  *     * Redistributions in binary form must reproduce the above copyright
13 |  *       notice, this list of conditions and the following disclaimer in the
14 |  *       documentation and/or other materials provided with the distribution.
15 |  *     * Neither the name of Matthias Mann nor the names of its
16 |  *       contributors may be used to endorse or promote products derived from
17 |  *       this software without specific prior written permission.
18 |  *
19 |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 |  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23 |  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 |  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 |  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 |  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 |  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 |  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 |  * POSSIBILITY OF SUCH DAMAGE.
30 |  * 
31 | * 32 | *

This package contains the runtime of the Continuations library.

33 | * 34 | * @see de.matthiasmann.continuations.Coroutine 35 | * @author Matthias Mann 36 | */ 37 | package de.matthiasmann.continuations; 38 | -------------------------------------------------------------------------------- /src/net/indiespot/continuations/VirtualRunnable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012, Enhanced Four 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are 7 | * met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * * Neither the name of 'Enhanced Four' nor the names of its contributors 17 | * may be used to endorse or promote products derived from this software 18 | * without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | package net.indiespot.continuations; 34 | 35 | import java.io.Serializable; 36 | 37 | import de.matthiasmann.continuations.SuspendExecution; 38 | 39 | public interface VirtualRunnable extends Serializable { 40 | 41 | public void run() throws SuspendExecution; 42 | } 43 | -------------------------------------------------------------------------------- /src/net/indiespot/continuations/VirtualThreadLocal.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012, Enhanced Four 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are 7 | * met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * * Neither the name of 'Enhanced Four' nor the names of its contributors 17 | * may be used to endorse or promote products derived from this software 18 | * without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | package net.indiespot.continuations; 34 | 35 | import java.io.Serializable; 36 | import java.util.IdentityHashMap; 37 | import java.util.Map; 38 | 39 | 40 | @SuppressWarnings("serial") 41 | public class VirtualThreadLocal implements Serializable { 42 | 43 | protected T initialValue() { 44 | return null; 45 | } 46 | 47 | @SuppressWarnings("unchecked") 48 | public final void set(T value) { 49 | this.locals().put(this, value == null ? (T) NULL_VALUE : value); 50 | } 51 | 52 | public final T get() { 53 | Map, T> locals = this.locals(); 54 | 55 | T got = (T) locals.get(this); 56 | if (got == NULL_VALUE) { 57 | return null; 58 | } 59 | 60 | if (got == null) { 61 | locals.put(this, got = this.initialValue()); 62 | } 63 | 64 | return got; 65 | } 66 | 67 | @SuppressWarnings("unchecked") 68 | private Map, T> locals() { 69 | VirtualThread self = VirtualThread.currentThread(); 70 | if (self.locals == null) { 71 | self.locals = new IdentityHashMap<>(); 72 | } 73 | return self.locals; 74 | } 75 | 76 | private static final Object NULL_VALUE = new Object(); 77 | } 78 | -------------------------------------------------------------------------------- /src/net/indiespot/continuations/VirtualThreadQueue.java: -------------------------------------------------------------------------------- 1 | package net.indiespot.continuations; 2 | 3 | import java.util.AbstractQueue; 4 | import java.util.ArrayList; 5 | import java.util.Collection; 6 | import java.util.Comparator; 7 | import java.util.Iterator; 8 | import java.util.List; 9 | import java.util.PriorityQueue; 10 | 11 | class VirtualThreadQueue extends AbstractQueue { 12 | private final VirtualProcessor proc; 13 | private final Comparator comp; 14 | private final PriorityQueue head; 15 | private ArrayList[] buckets; 16 | private int bucketsMask; 17 | private ArrayList tail, tailNext; 18 | 19 | private long bucketDuration; 20 | private long headTime; 21 | private int size; 22 | 23 | @SuppressWarnings("unchecked") 24 | public VirtualThreadQueue(VirtualProcessor proc, long bucketDuration) { 25 | if (bucketDuration <= 0) { 26 | throw new IllegalArgumentException(); 27 | } 28 | this.proc = proc; 29 | this.bucketDuration = bucketDuration; 30 | this.comp = new VirtualProcessor.VirtualThreadComparator(); 31 | 32 | headTime = proc.getCurrentTime(); 33 | 34 | head = new PriorityQueue<>(11, comp); 35 | buckets = new ArrayList[1 << 3]; // must be POT 36 | bucketsMask = buckets.length - 1; // will be bit-mask 37 | for (int i = 0; i < buckets.length; i++) { 38 | buckets[i] = new ArrayList<>(4); 39 | } 40 | tail = new ArrayList<>(); 41 | tailNext = new ArrayList<>(); 42 | } 43 | 44 | @SuppressWarnings("unchecked") 45 | private void addBuckets() { 46 | ArrayList[] curr = buckets; 47 | ArrayList[] next = new ArrayList[curr.length << 1]; 48 | for (int i = 0; i < curr.length; i++) { 49 | next[i] = curr[reindex(i)]; 50 | } 51 | bucketsMask = next.length - 1; 52 | bucketOffset = 0; 53 | for (int i = curr.length; i < next.length; i++) { 54 | next[i] = new ArrayList<>(4); 55 | } 56 | buckets = next; 57 | 58 | // redistribute tail elements over new buckets (and tail) 59 | List copy = tail; 60 | tail = new ArrayList<>(); 61 | this.addAll(copy); 62 | } 63 | 64 | public boolean isEmpty() { 65 | return size == 0; 66 | } 67 | 68 | @Override 69 | public VirtualThread peek() { 70 | this.sync(); 71 | 72 | return head.peek(); 73 | } 74 | 75 | @Override 76 | public VirtualThread poll() { 77 | this.sync(); 78 | 79 | VirtualThread got = head.poll(); 80 | if (got != null) 81 | size--; 82 | return got; 83 | } 84 | 85 | private int bucketOffset; 86 | 87 | private int reindex(int index) { 88 | return (bucketOffset + index) & bucketsMask; 89 | } 90 | 91 | @Override 92 | public boolean offer(VirtualThread thread) { 93 | this.sync(); 94 | 95 | // insert VirtualThread into head, bucket or tail 96 | int bucketIndex = (int) ((thread.wakeUpAt - headTime) / bucketDuration); 97 | if (bucketIndex <= 0) { 98 | head.add(thread); 99 | } else { 100 | bucketIndex -= 1; 101 | 102 | if (bucketIndex < buckets.length) { 103 | buckets[reindex(bucketIndex)].add(thread); 104 | } else { 105 | tail.add(thread); 106 | 107 | while (this.isTailSplitNeeded()) { 108 | this.addBuckets(); 109 | } 110 | } 111 | } 112 | 113 | size++; 114 | 115 | return true; 116 | } 117 | 118 | @Override 119 | public boolean remove(Object obj) { 120 | VirtualThread thread = (VirtualThread) obj; 121 | 122 | this.sync(); 123 | 124 | // remove VirtualThread from head, bucket or tail 125 | int bucketIndex = (int) ((thread.wakeUpAt - headTime) / bucketDuration); 126 | if (bucketIndex <= 0) { 127 | boolean got = head.remove(thread); 128 | if (got) { 129 | size--; 130 | } 131 | return got; 132 | } 133 | 134 | bucketIndex -= 1; 135 | if (bucketIndex < buckets.length) { 136 | boolean got = buckets[reindex(bucketIndex)].remove(thread); 137 | if (got) { 138 | size--; 139 | } 140 | return got; 141 | } 142 | 143 | boolean got = tail.remove(thread); 144 | if (got) { 145 | size--; 146 | } 147 | return got; 148 | } 149 | 150 | protected boolean isTailSplitNeeded() { 151 | if (buckets.length > 10_000) { 152 | // prevent extreme growth 153 | return false; 154 | } 155 | if (tail.size() < 256) { 156 | // no need to split yet 157 | return false; 158 | } 159 | return true; 160 | } 161 | 162 | private long sync() { 163 | long procTime = proc.getCurrentTime(); 164 | 165 | while (procTime >= headTime + bucketDuration) { 166 | headTime += bucketDuration; 167 | 168 | // move first bucket into 'head' 169 | ArrayList first = buckets[reindex(0)]; 170 | first.trimToSize(); // shrink to typical size 171 | head.addAll(first); 172 | first.clear(); 173 | 174 | ArrayList last = first; 175 | bucketOffset++; 176 | 177 | if (tail.isEmpty()) { 178 | continue; 179 | } 180 | 181 | // split 'tail' into new tail and last bucket 182 | long tailThreshold = headTime + bucketDuration * (buckets.length + 1); 183 | tail.trimToSize(); // shrink to typical size 184 | 185 | for (VirtualThread elem : tail) { 186 | if (elem.wakeUpAt < tailThreshold) { 187 | last.add(elem); 188 | } else { 189 | tailNext.add(elem); 190 | } 191 | } 192 | tail.clear(); 193 | 194 | // swap 195 | ArrayList temp = tail; 196 | tail = tailNext; 197 | tailNext = temp; 198 | } 199 | 200 | return procTime; 201 | } 202 | 203 | @Override 204 | public int size() { 205 | return size; 206 | } 207 | 208 | @Override 209 | public boolean contains(Object o) { 210 | throw new UnsupportedOperationException(); 211 | } 212 | 213 | @Override 214 | public boolean containsAll(Collection c) { 215 | throw new UnsupportedOperationException(); 216 | } 217 | 218 | @Override 219 | public Iterator iterator() { 220 | throw new UnsupportedOperationException(); 221 | } 222 | } 223 | -------------------------------------------------------------------------------- /src/net/indiespot/continuations/VirtualThreadState.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012, Enhanced Four 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are 7 | * met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * * Neither the name of 'Enhanced Four' nor the names of its contributors 17 | * may be used to endorse or promote products derived from this software 18 | * without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | package net.indiespot.continuations; 34 | 35 | public enum VirtualThreadState { 36 | NEW, RUNNABLE, YIELDED, SLEEPING, SUSPENDED, TERMINATED 37 | } 38 | -------------------------------------------------------------------------------- /src/net/indiespot/continuations/VirtualUncaughtExceptionHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012, Enhanced Four 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are 7 | * met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * * Neither the name of 'Enhanced Four' nor the names of its contributors 17 | * may be used to endorse or promote products derived from this software 18 | * without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | package net.indiespot.continuations; 34 | 35 | import java.io.Serializable; 36 | 37 | public interface VirtualUncaughtExceptionHandler extends Serializable { 38 | public void uncaughtException(VirtualThread thread, Throwable uncaught); 39 | } 40 | -------------------------------------------------------------------------------- /src/net/indiespot/continuations/libcontinuations.mf: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Premain-Class: de.matthiasmann.continuations.instrument.JavaAgent 3 | 4 | -------------------------------------------------------------------------------- /src/net/indiespot/continuations/util/VirtualCondition.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012, Enhanced Four 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are 7 | * met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * * Neither the name of 'Enhanced Four' nor the names of its contributors 17 | * may be used to endorse or promote products derived from this software 18 | * without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | package net.indiespot.continuations.util; 34 | 35 | import java.io.Serializable; 36 | 37 | import net.indiespot.continuations.VirtualThread; 38 | import net.indiespot.dependencies.CircularArrayList; 39 | import de.matthiasmann.continuations.*; 40 | 41 | @SuppressWarnings("serial") 42 | public class VirtualCondition implements Serializable { 43 | private final VirtualLock attachedToLock; 44 | private final CircularArrayList waiting; 45 | 46 | public VirtualCondition() { 47 | this(null); 48 | } 49 | 50 | VirtualCondition(VirtualLock lock) { 51 | this.attachedToLock = lock; 52 | this.waiting = new CircularArrayList<>(1); 53 | } 54 | 55 | public void await() throws SuspendExecution { 56 | VirtualThread self = VirtualThread.currentThread(); 57 | 58 | if(attachedToLock != null) { 59 | // release the lock before suspending 60 | attachedToLock.unlock(); 61 | } 62 | 63 | waiting.addLast(self); 64 | VirtualThread.suspend(); 65 | 66 | if(attachedToLock != null) { 67 | // acquire the lock before continuing 68 | attachedToLock.lock(); 69 | } 70 | } 71 | 72 | public void await(long timeout) throws SuspendExecution { 73 | VirtualThread self = VirtualThread.currentThread(); 74 | 75 | if(attachedToLock != null) { 76 | // release the lock before suspending 77 | attachedToLock.unlock(); 78 | } 79 | 80 | waiting.addLast(self); 81 | VirtualThread.sleep(timeout); // can be woken 82 | 83 | if(attachedToLock != null) { 84 | // acquire the lock before continuing 85 | attachedToLock.lock(); 86 | } 87 | } 88 | 89 | public void signal() { 90 | VirtualThread self = VirtualThread.peekCurrentThread(); 91 | 92 | if(attachedToLock != null && self != null) { 93 | if(attachedToLock.holder() != self) { 94 | throw new IllegalMonitorStateException(); 95 | } 96 | } 97 | 98 | // resume one virtual thread 99 | if(!waiting.isEmpty()) { 100 | this.nudge(waiting.removeFirst()); 101 | } 102 | } 103 | 104 | public void signalAll() { 105 | VirtualThread self = VirtualThread.peekCurrentThread(); 106 | 107 | if(attachedToLock != null && self != null) { 108 | if(attachedToLock.holder() != self) { 109 | throw new IllegalMonitorStateException(); 110 | } 111 | } 112 | 113 | // resume all virtual threads 114 | while (!waiting.isEmpty()) { 115 | this.nudge(waiting.removeFirst()); 116 | } 117 | } 118 | 119 | private void nudge(VirtualThread thread) { 120 | switch (thread.getState()) { 121 | case SUSPENDED: 122 | thread.resume(); 123 | break; 124 | 125 | case SLEEPING: 126 | thread.wake(); 127 | break; 128 | 129 | default: 130 | throw new IllegalThreadStateException("state: " + thread.getState()); 131 | } 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /src/net/indiespot/continuations/util/VirtualExchanger.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012, Enhanced Four 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are 7 | * met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * * Neither the name of 'Enhanced Four' nor the names of its contributors 17 | * may be used to endorse or promote products derived from this software 18 | * without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | package net.indiespot.continuations.util; 34 | 35 | import java.io.Serializable; 36 | 37 | import net.indiespot.continuations.VirtualThread; 38 | import net.indiespot.dependencies.CircularArrayList; 39 | import de.matthiasmann.continuations.*; 40 | 41 | @SuppressWarnings("serial") 42 | public class VirtualExchanger implements Serializable { 43 | private final VirtualCondition queueNotEmpty; 44 | private final CircularArrayList> queue; 45 | 46 | public VirtualExchanger() { 47 | queueNotEmpty = new VirtualCondition(); 48 | queue = new CircularArrayList<>(1); 49 | } 50 | 51 | public T exchange(T item) throws SuspendExecution { 52 | VirtualThread self = VirtualThread.currentThread(); 53 | 54 | queue.addLast(new Slot(item)); 55 | queueNotEmpty.signalAll(); 56 | 57 | for(;;) { 58 | while (queue.isEmpty()) { 59 | queueNotEmpty.await(); 60 | } 61 | 62 | if(queue.peekFirst().producer != self) { 63 | return queue.pollFirst().value; 64 | } 65 | 66 | queueNotEmpty.await(); 67 | } 68 | } 69 | 70 | private static class Slot { 71 | public final T value; 72 | public final VirtualThread producer; 73 | 74 | public Slot(T value) { 75 | this.value = value; 76 | this.producer = VirtualThread.currentThread(); 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/net/indiespot/continuations/util/VirtualLock.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012, Enhanced Four 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are 7 | * met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * * Neither the name of 'Enhanced Four' nor the names of its contributors 17 | * may be used to endorse or promote products derived from this software 18 | * without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | package net.indiespot.continuations.util; 34 | 35 | import java.io.Serializable; 36 | 37 | import net.indiespot.continuations.VirtualThread; 38 | import de.matthiasmann.continuations.SuspendExecution; 39 | 40 | @SuppressWarnings("serial") 41 | public class VirtualLock implements Serializable { 42 | 43 | private final VirtualCondition unlockedCondition; 44 | private VirtualThread holder; 45 | 46 | public VirtualLock() { 47 | unlockedCondition = new VirtualCondition(null); 48 | } 49 | 50 | VirtualThread holder() { 51 | return holder; 52 | } 53 | 54 | public void lock() throws SuspendExecution { 55 | VirtualThread self = VirtualThread.currentThread(); 56 | 57 | if (holder == null) { 58 | // lock 59 | holder = self; 60 | } else if (self == holder) { 61 | // nested lock 62 | throw new IllegalStateException("lock already held"); 63 | } else { 64 | // wait for the lock 65 | unlockedCondition.await(); 66 | 67 | // it should be unlocked now 68 | if (holder != null) { 69 | throw new IllegalStateException(); 70 | } 71 | 72 | // lock 73 | holder = self; 74 | } 75 | } 76 | 77 | public boolean tryLock() throws SuspendExecution { 78 | VirtualThread self = VirtualThread.currentThread(); 79 | 80 | if (holder == null) { 81 | // lock 82 | holder = self; 83 | } else if (self == holder) { 84 | // nested lock 85 | throw new IllegalStateException("lock already held"); 86 | } else { 87 | return false; 88 | } 89 | 90 | return true; 91 | } 92 | 93 | public void unlock() throws SuspendExecution { 94 | VirtualThread self = VirtualThread.currentThread(); 95 | 96 | if (holder != self) { 97 | throw new IllegalMonitorStateException(); 98 | } 99 | 100 | // unlock 101 | holder = null; 102 | unlockedCondition.signal(); 103 | // at most 1 virtual thread will grab the lock and move on 104 | } 105 | 106 | public VirtualCondition newCondition() { 107 | return new VirtualCondition(this); 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /src/net/indiespot/continuations/util/VirtualMessage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012, Enhanced Four 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are 7 | * met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * * Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * * Neither the name of 'Enhanced Four' nor the names of its contributors 17 | * may be used to endorse or promote products derived from this software 18 | * without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | */ 32 | 33 | package net.indiespot.continuations.util; 34 | 35 | import net.indiespot.continuations.VirtualThread; 36 | 37 | public class VirtualMessage { 38 | 39 | public VirtualMessage(Object message) { 40 | this.author = VirtualThread.currentThread(); 41 | this.message = message; 42 | } 43 | 44 | // 45 | 46 | private final VirtualThread author; 47 | 48 | public VirtualThread author() { 49 | return author; 50 | } 51 | 52 | // 53 | 54 | private final Object message; 55 | 56 | public Object message() { 57 | return message; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/net/indiespot/continuations/util/VirtualMessageQueue.java: -------------------------------------------------------------------------------- 1 | package net.indiespot.continuations.util; 2 | 3 | import net.indiespot.dependencies.CircularArrayList; 4 | import de.matthiasmann.continuations.SuspendExecution; 5 | 6 | public class VirtualMessageQueue { 7 | private final VirtualCondition messageQueueNotEmpty; 8 | private final CircularArrayList messageQueue; 9 | 10 | public VirtualMessageQueue() { 11 | messageQueue = new CircularArrayList<>(1); 12 | messageQueueNotEmpty = new VirtualCondition(); 13 | } 14 | 15 | public VirtualMessage pollMessage() { 16 | return messageQueue.pollFirst(); 17 | } 18 | 19 | public VirtualMessage awaitMessage() throws SuspendExecution { 20 | while (messageQueue.isEmpty()) { 21 | messageQueueNotEmpty.await(); 22 | } 23 | return messageQueue.removeFirst(); 24 | } 25 | 26 | public void passMessage(Object message) { 27 | messageQueue.addLast(new VirtualMessage(message)); 28 | messageQueueNotEmpty.signalAll(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/net/indiespot/dependencies/CircularArrayList.java: -------------------------------------------------------------------------------- 1 | package net.indiespot.dependencies; 2 | 3 | import java.io.Serializable; 4 | import java.util.*; 5 | 6 | public class CircularArrayList implements Serializable { 7 | private static final long serialVersionUID = -377269371668702946L; 8 | 9 | private T[] backing; 10 | private int offsetIndex; 11 | private int size; 12 | 13 | public CircularArrayList() { 14 | this(10); 15 | } 16 | 17 | @SuppressWarnings("unchecked") 18 | public CircularArrayList(int initialCapacity) { 19 | backing = (T[]) new Object[Math.max(1, initialCapacity)]; 20 | } 21 | 22 | // common operations 23 | 24 | public int size() { 25 | return this.size; 26 | } 27 | 28 | public boolean isEmpty() { 29 | return this.size == 0; 30 | } 31 | 32 | public void clear() { 33 | for (int i = 0; i < size; i++) { 34 | this.set(i, null); 35 | } 36 | size = 0; 37 | } 38 | 39 | public T get(int index) { 40 | return backing[this.realIndexOf(index)]; 41 | } 42 | 43 | public T set(int index, T value) { 44 | int realIndex = this.realIndexOf(index); 45 | T got = backing[realIndex]; 46 | backing[realIndex] = value; 47 | return got; 48 | } 49 | 50 | // add 51 | 52 | public void addFirst(T value) { 53 | if (size == backing.length) { 54 | this.grow(); 55 | } 56 | offsetIndex = wrapNearZero(offsetIndex - 1); 57 | backing[realIndexOf(0)] = value; 58 | size++; 59 | } 60 | 61 | public void addLast(T value) { 62 | if (size == backing.length) { 63 | this.grow(); 64 | } 65 | backing[readIndexOfEnd()] = value; 66 | size++; 67 | } 68 | 69 | // remove 70 | 71 | public T removeFirst() throws NoSuchElementException { 72 | if (this.size == 0) { 73 | throw new NoSuchElementException(); 74 | } 75 | 76 | int index = this.realIndexOf(0); 77 | T value = backing[index]; 78 | backing[index] = null; 79 | 80 | size--; 81 | 82 | offsetIndex = wrapPos(offsetIndex + 1); 83 | return value; 84 | } 85 | 86 | public T removeLast() throws NoSuchElementException { 87 | if (this.size == 0) { 88 | throw new NoSuchElementException(); 89 | } 90 | size--; 91 | 92 | int index = this.readIndexOfEnd(); 93 | T value = backing[index]; 94 | backing[index] = null; 95 | 96 | return value; 97 | } 98 | 99 | // 100 | 101 | public boolean contains(T item) { 102 | return this.indexOf(item) != -1; 103 | } 104 | 105 | public int indexOf(T item) { 106 | for (int i = 0; i < this.size; i++) { 107 | if (backing[this.realIndexOf(i)] == item) { 108 | return i; 109 | } 110 | } 111 | return -1; 112 | } 113 | 114 | public boolean remove(T item) { 115 | int index = this.indexOf(item); 116 | if (index == -1) { 117 | return false; 118 | } 119 | 120 | // shift one slot to the left 121 | for (int k = index; k < this.size - 1; k++) { 122 | backing[this.realIndexOf(k)] = backing[this.realIndexOf(k + 1)]; 123 | } 124 | backing[this.realIndexOf(this.size - 1)] = null; 125 | 126 | this.size--; 127 | return true; 128 | } 129 | 130 | // peek 131 | 132 | public T peekFirst() { 133 | return this.isEmpty() ? null : this.get(0); 134 | } 135 | 136 | public T peekLast() { 137 | return this.isEmpty() ? null : this.get(this.size - 1); 138 | } 139 | 140 | // poll 141 | 142 | public T pollFirst() { 143 | return this.isEmpty() ? null : this.removeFirst(); 144 | } 145 | 146 | public T pollLast() { 147 | return this.isEmpty() ? null : this.removeLast(); 148 | } 149 | 150 | // 151 | 152 | private void grow() { 153 | T[] newArray = Arrays.copyOf(backing, backing.length << 1); 154 | for (int i = 0; i < size; i++) { 155 | newArray[i] = backing[wrapPos(offsetIndex + i)]; 156 | } 157 | 158 | offsetIndex = 0; 159 | backing = newArray; 160 | } 161 | 162 | private final int realIndexOf(int index) { 163 | if (index < 0 || index >= size) { 164 | throw new IndexOutOfBoundsException(); 165 | } 166 | return wrapPos(offsetIndex + index); 167 | } 168 | 169 | private final int readIndexOfEnd() { 170 | return wrapPos(offsetIndex + size); 171 | } 172 | 173 | private final int wrapPos(int value) { 174 | return value % backing.length; 175 | } 176 | 177 | private final int wrapNearZero(int value) { 178 | return (value + backing.length) % backing.length; 179 | } 180 | 181 | // private final int wrapAny(int value) { 182 | // return ((value % backing.length) + backing.length) % backing.length; 183 | // } 184 | } -------------------------------------------------------------------------------- /src/net/indiespot/dependencies/Filter.java: -------------------------------------------------------------------------------- 1 | package net.indiespot.dependencies; 2 | 3 | public interface Filter { 4 | public boolean accept(T t); 5 | } 6 | -------------------------------------------------------------------------------- /src/net/indiespot/dependencies/IntList.java: -------------------------------------------------------------------------------- 1 | package net.indiespot.dependencies; 2 | 3 | import java.util.Arrays; 4 | 5 | public class IntList { 6 | private int[] array; 7 | private int size; 8 | 9 | public IntList() { 10 | this.array = new int[16]; 11 | } 12 | 13 | public void clear() { 14 | this.size = 0; 15 | } 16 | 17 | public boolean isEmpty() { 18 | return this.size == 0; 19 | } 20 | 21 | public int size() { 22 | return this.size; 23 | } 24 | 25 | public int removeLast() { 26 | return this.array[--this.size]; 27 | } 28 | 29 | public void add(int b) { 30 | if(this.size == this.array.length) { 31 | this.array = Arrays.copyOf(this.array, this.array.length * 2); 32 | } 33 | this.array[this.size++] = b; 34 | } 35 | 36 | public int get(int index) { 37 | if(index >= this.size) { 38 | throw new IndexOutOfBoundsException(); 39 | } 40 | return this.array[index]; 41 | } 42 | 43 | public int[] toArray() { 44 | return Arrays.copyOf(this.array, this.size); 45 | } 46 | 47 | public void fillArray(int[] dst, int off, int len) { 48 | if(len != this.size) { 49 | throw new IllegalStateException(); 50 | } 51 | System.arraycopy(this.array, 0, dst, off, len); 52 | } 53 | } -------------------------------------------------------------------------------- /src/net/indiespot/dependencies/Vec2.java: -------------------------------------------------------------------------------- 1 | package net.indiespot.dependencies; 2 | 3 | import java.nio.FloatBuffer; 4 | 5 | public class Vec2 { 6 | public float x, y; 7 | 8 | // 9 | 10 | public Vec2() { 11 | load(0.0f); 12 | } 13 | 14 | public Vec2(float xy) { 15 | load(xy); 16 | } 17 | 18 | public Vec2(float x, float y) { 19 | load(x, y); 20 | } 21 | 22 | public Vec2(float[] v, int pos) { 23 | load(v, pos); 24 | } 25 | 26 | public Vec2(Vec2 v) { 27 | load(v); 28 | } 29 | 30 | /** 31 | * LOAD 32 | */ 33 | 34 | public Vec2 load(Vec2 v) { 35 | x = v.x; 36 | y = v.y; 37 | 38 | return this; 39 | } 40 | 41 | public Vec2 load(float val) { 42 | x = val; 43 | y = val; 44 | 45 | return this; 46 | } 47 | 48 | public Vec2 load(float x, float y) { 49 | this.x = x; 50 | this.y = y; 51 | 52 | return this; 53 | } 54 | 55 | public Vec2 load(float[] arr, int pos) { 56 | x = arr[pos + 0]; 57 | y = arr[pos + 1]; 58 | 59 | return this; 60 | } 61 | 62 | public Vec2 load(FloatBuffer buf) { 63 | x = buf.get(); 64 | y = buf.get(); 65 | 66 | return this; 67 | } 68 | 69 | public Vec2 load(FloatBuffer buf, int pos) { 70 | x = buf.get(pos + 0); 71 | y = buf.get(pos + 1); 72 | 73 | return this; 74 | } 75 | 76 | /** 77 | * STORE 78 | */ 79 | 80 | public final void store(float[] arr, int off) { 81 | arr[off + 0] = x; 82 | arr[off + 1] = y; 83 | } 84 | 85 | public final void store(FloatBuffer buf) { 86 | buf.put(x); 87 | buf.put(y); 88 | } 89 | 90 | public final void store(FloatBuffer buf, int pos) { 91 | buf.put(pos + 0, x); 92 | buf.put(pos + 1, y); 93 | } 94 | 95 | /** 96 | * CALC 97 | */ 98 | 99 | public float squaredLength() { 100 | return (x * x + y * y); 101 | } 102 | 103 | public float length() { 104 | return (float) Math.sqrt(this.squaredLength()); 105 | } 106 | 107 | public Vec2 length(float val) { 108 | float li = val / (float) Math.sqrt(this.squaredLength()); 109 | 110 | x = (x * li); 111 | y = (y * li); 112 | 113 | return this; 114 | } 115 | 116 | public Vec2 normalize() { 117 | float li = 1.0f / (float) Math.sqrt(this.squaredLength()); 118 | 119 | x = (x * li); 120 | y = (y * li); 121 | 122 | return this; 123 | } 124 | 125 | public Vec2 inv() { 126 | x = (-x); 127 | y = (-y); 128 | 129 | return this; 130 | } 131 | 132 | public Vec2 abs() { 133 | if(x < 0.0F) 134 | x = (-x); 135 | if(y < 0.0F) 136 | y = (-y); 137 | 138 | return this; 139 | } 140 | 141 | // 142 | 143 | public Vec2 add(float x, float y) { 144 | this.x += x; 145 | this.y += y; 146 | 147 | return this; 148 | } 149 | 150 | public Vec2 sub(float x, float y) { 151 | this.x -= x; 152 | this.y -= y; 153 | 154 | return this; 155 | } 156 | 157 | public Vec2 mul(float x, float y) { 158 | this.x *= x; 159 | this.y *= y; 160 | 161 | return this; 162 | } 163 | 164 | public Vec2 div(float x, float y) { 165 | this.x /= x; 166 | this.y /= y; 167 | 168 | return this; 169 | } 170 | 171 | // 172 | 173 | public Vec2 add(float xy) { 174 | return add(xy, xy); 175 | } 176 | 177 | public Vec2 sub(float xy) { 178 | return sub(xy, xy); 179 | } 180 | 181 | public Vec2 mul(float xy) { 182 | return mul(xy, xy); 183 | } 184 | 185 | public Vec2 div(float xy) { 186 | return div(xy, xy); 187 | } 188 | 189 | // 190 | 191 | public Vec2 add(Vec2 vec) { 192 | return add(vec.x, vec.y); 193 | } 194 | 195 | public Vec2 sub(Vec2 vec) { 196 | return sub(vec.x, vec.y); 197 | } 198 | 199 | public Vec2 mul(Vec2 vec) { 200 | return mul(vec.x, vec.y); 201 | } 202 | 203 | public Vec2 div(Vec2 vec) { 204 | return div(vec.x, vec.y); 205 | } 206 | 207 | // 208 | 209 | public Vec2 min(Vec2 vec) { 210 | if(vec.x < x) 211 | x = (vec.x); 212 | if(vec.y < y) 213 | y = (vec.y); 214 | 215 | return this; 216 | } 217 | 218 | public Vec2 max(Vec2 vec) { 219 | if(vec.x > x) 220 | x = (vec.x); 221 | if(vec.y > y) 222 | y = (vec.y); 223 | 224 | return this; 225 | } 226 | 227 | public int hashCode() { 228 | int xi = (int) (this.x * 1000); 229 | int yi = (int) (this.y * 1000); 230 | 231 | return xi ^ yi; 232 | } 233 | 234 | public static float distanceSquared(Vec2 a, Vec2 b) { 235 | float dx = a.x - b.x; 236 | float dy = a.y - b.y; 237 | return dx * dx + dy * dy; 238 | } 239 | 240 | public static float distance(Vec2 a, Vec2 b) { 241 | return (float) Math.sqrt(distanceSquared(a, b)); 242 | } 243 | } --------------------------------------------------------------------------------