Skip to content

Commit 4ff96d5

Browse files
committed
first commit
0 parents  commit 4ff96d5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+7743
-0
lines changed

Diff for: Makefile

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
2+
# https://www.gnu.org/software/make/manual/make.html#Automatic-Variables
3+
4+
# requires: pandoc 1.16 or higher
5+
6+
# https://github.com/freebroccolo/docker-haskell/blob/a396f0d9b35cabeb60920abd87a8b2612530cb1b/7.10/Dockerfile
7+
# https://github.com/jagregory/pandoc-docker/blob/master/Dockerfile
8+
9+
# docker images
10+
# docker run --rm -t -i --entrypoint="/bin/bash" pandoc
11+
# docker run --rm -e "userid=$(id -u):$(id -g)" -t -i --entrypoint="/bin/bash" pandoc
12+
13+
# https://github.com/docker/docker/issues/3206
14+
# http://stackoverflow.com/questions/27925006/using-host-environment-variables-with-dockerfile
15+
16+
docker-image-cleanup:
17+
docker rmi -f $(docker images | grep "<none>" | awk "{print \$3}")
18+
19+
index.html: header.md body.md
20+
touch $@ && docker run --rm -e "userid=$$(id -u):$$(id -g)" -t -v `pwd`:/source jagregory/pandoc --standalone -S --highlight-style pygments --toc -c pandoc.css -f markdown+link_attributes -t html5 --self-contained -o $@ $^
21+

Diff for: README.md

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
2+
See here for details.
3+
4+
You can rebuild the document locally by executing:
5+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.bash}
6+
> rm index.html
7+
> make index.html
8+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9+
10+
Keyword List: Control Structures and Paradigms:
11+
12+
* Parallel Universe: Quasar Library: Continuations for Core Java and the JVM
13+
* Continuations, Coroutines, Generators
14+
* Continuation Passing Style (CPS)
15+
* Flow-Based Programming (FBP)
16+
* Communicating Sequential Processes (CSP)
17+
* Clojure core.async
18+
* Complex Event Processing (CEP)
19+
* Actors
20+
* "Let it crash" vs. try-catch-finally
21+
* Incremental Computing
22+
* Functional Reactive Programming (FRP)
23+
* Reactive Extension (Rx)
24+
* Propagators
25+
* Self-Adjusting Computation
26+
* Bidirectional Programming (Lenses)
27+
* Fiber, Green Threads, Light-Weight Thread, Cooperative Multi-Tasking
28+
* Push vs. Pull, Polarity of Pipelines
29+
* Thread Based vs. Event Driven
30+
* Cooperative Multi-Tasking vs. Pre-Emptive Multi-Tasking
31+
* (pull, fiber/stack-based and lazy) form a unit and (push, event-driven and eager) form a unit
32+
* Cooperative Task Management without Manual Stack Management, avoiding “call-back hell” and “stack ripping” in single threaded applications
33+
* Event Sourced Architectures, CQRS
34+
35+
Core Message
36+
37+
The core of the message that I want to share with you is that event-driven or fiber style programming are from a performance perspective equivalent.
38+
39+
Actually event-driven, fiber-style, reactive programming, data-flow programming, complex event processing or communicating-sequential-processes are all from a performance perspective equivalent. There exist mechanical transformations between the one style of programming into the other style. These mechanical transformations can be performed under the hood via compiler technology, e.g. via byte code manipulation.
40+
41+
If from a performance perspective all of these programming styles are equivalent then the choice of which style to use should be based on factors like how well the code is understandable, e.g. in a static set-up as code visible in your IDE without running the program. Here the fiber style is much better suited for us humans to understand than the event-driven style!

Diff for: body.md

+2,362
Large diffs are not rendered by default.

Diff for: control-structures/pom.xml

+336
Large diffs are not rendered by default.

Diff for: control-structures/set-up-links.sh

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#!/bin/bash
2+
mkdir -p $HOME/.m2/repository/co/paralleluniverse/quasar-core/0.7.5
3+
ln -s $HOME/.m2/repository/co/paralleluniverse/quasar-core/0.7.5/quasar-core-0.7.5-sources.jar $HOME/.m2/repository/co/paralleluniverse/quasar-core/0.7.5/quasar-core-0.7.5-jdk8-sources.jar
4+
ln -s $HOME/.m2/repository/co/paralleluniverse/quasar-core/0.7.5/quasar-core-0.7.5-javadoc.jar $HOME/.m2/repository/co/paralleluniverse/quasar-core/0.7.5/quasar-core-0.7.5-jdk8-javadoc.jar
5+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package control.structures;
2+
3+
/**
4+
* Hello world!
5+
*
6+
*/
7+
public class App
8+
{
9+
public static void main( String[] args )
10+
{
11+
System.out.println( "Hello World!" );
12+
}
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
package control.structures.continuations;
2+
3+
import java.io.Serializable;
4+
import java.util.Iterator;
5+
import java.util.NoSuchElementException;
6+
7+
import co.paralleluniverse.fibers.SuspendExecution;
8+
import co.paralleluniverse.strands.Strand.State;
9+
import co.paralleluniverse.strands.SuspendableCallable;
10+
11+
public abstract class CoIterator<E> implements Iterator<E>, Serializable {
12+
13+
private static final long serialVersionUID = 351278561539L;
14+
15+
private final Coroutine co;
16+
17+
private E element;
18+
private boolean hasElement;
19+
20+
protected CoIterator() {
21+
co = new Coroutine((SuspendableCallable<Void>)() -> {run(); return null;});
22+
}
23+
24+
public boolean hasNext() {
25+
while(!hasElement && co.getState() != State.TERMINATED) {
26+
co.run();
27+
}
28+
return hasElement;
29+
}
30+
31+
public E next() {
32+
if(!hasNext()) {
33+
throw new NoSuchElementException();
34+
}
35+
E result = element;
36+
hasElement = false;
37+
element = null;
38+
return result;
39+
}
40+
41+
/**
42+
* Always throws UnsupportedOperationException.
43+
* @throws java.lang.UnsupportedOperationException always
44+
*/
45+
public void remove() throws UnsupportedOperationException {
46+
throw new UnsupportedOperationException("Not supported");
47+
}
48+
49+
/**
50+
* Produces the next value to be returned by the {@link #next} method.
51+
*
52+
* @param element The value that should be returned by {@link #next}
53+
* @throws de.matthiasmann.continuations.SuspendExecution This method will suspend the execution
54+
*/
55+
protected void produce(E element) throws SuspendExecution {
56+
if(hasElement) {
57+
throw new IllegalStateException("hasElement = true");
58+
}
59+
this.element = element;
60+
hasElement = true;
61+
co.yield();
62+
}
63+
64+
/**
65+
* <p>This is the body of the Iterator. This method is executed as a
66+
* {@link Coroutine} to {@link #produce} the values of the Iterator.</p>
67+
*
68+
* <p>Note that this method is suspended each time it calls produce. And if
69+
* the consumer does not consume all values of the Iterator then this
70+
* method does not get the change to finish it's execution. This also
71+
* includes the finally blocks.</p>
72+
*
73+
* <p>This method must only suspend by calling produce. Any other reason
74+
* for suspension will cause a busy loop in the Iterator.</p>
75+
*
76+
* @throws de.matthiasmann.continuations.SuspendExecution
77+
*/
78+
protected abstract void run() throws SuspendExecution;
79+
80+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package control.structures.continuations;
2+
3+
import java.io.Serializable;
4+
import java.util.concurrent.ExecutionException;
5+
6+
import co.paralleluniverse.fibers.Fiber;
7+
import co.paralleluniverse.fibers.FiberExecutorScheduler;
8+
import co.paralleluniverse.fibers.FiberScheduler;
9+
import co.paralleluniverse.fibers.SuspendExecution;
10+
import co.paralleluniverse.strands.SuspendableCallable;
11+
import co.paralleluniverse.strands.Strand.State;
12+
13+
public class Coroutine implements Serializable {
14+
15+
private static final long serialVersionUID = 357144399321567101L;
16+
17+
private static final FiberScheduler myFiberScheduler = new FiberExecutorScheduler("my-scheduler", new MyExecutor());
18+
private final Fiber<Void> fiber;
19+
20+
public Coroutine(SuspendableCallable<Void> proto) {
21+
this(proto, Fiber.DEFAULT_STACK_SIZE);
22+
}
23+
24+
public Coroutine(SuspendableCallable<Void> proto, int stackSize) {
25+
fiber = new Fiber<>(myFiberScheduler, () -> { Fiber.park(); proto.run();});
26+
fiber.start();
27+
}
28+
29+
30+
public void yield() throws SuspendExecution {
31+
Fiber.park();
32+
}
33+
34+
// as long as I am single threaded and as long as I am sticking to the protocol of alternating calls to yield() and run()
35+
// I don't need to throw the SuspendExecution exception here, because this channel should never suspend.
36+
public void run() {
37+
Fiber.unpark(fiber);
38+
}
39+
40+
public State getState() {
41+
return fiber.getState();
42+
}
43+
44+
public void join() throws ExecutionException, InterruptedException {
45+
fiber.join();
46+
}
47+
48+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package control.structures.continuations;
2+
3+
import java.util.concurrent.Executor;
4+
5+
public class MyExecutor implements Executor {
6+
7+
@Override
8+
public void execute(Runnable command) {
9+
command.run();
10+
}
11+
12+
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package control.structures.dataflow;
2+
3+
import java.io.Serializable;
4+
5+
import co.paralleluniverse.fibers.SuspendExecution;
6+
7+
public interface DataflowVariable<T extends Serializable> extends ResponseVariable<T> {
8+
9+
public void bind(T value) throws AlreadyBoundToIncompatibleValueException;
10+
public T get() throws SuspendExecution, InterruptedException;
11+
12+
public ResponseVariable<T> response();
13+
14+
public boolean isDone();
15+
16+
public static class AlreadyBoundToIncompatibleValueException extends RuntimeException {
17+
private static final long serialVersionUID = 6396210388354647161L;
18+
public AlreadyBoundToIncompatibleValueException() {
19+
super();
20+
}
21+
public AlreadyBoundToIncompatibleValueException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
22+
super(message, cause, enableSuppression, writableStackTrace);
23+
}
24+
public AlreadyBoundToIncompatibleValueException(String message, Throwable cause) {
25+
super(message, cause);
26+
}
27+
public AlreadyBoundToIncompatibleValueException(String message) {
28+
super(message);
29+
}
30+
public AlreadyBoundToIncompatibleValueException(Throwable cause) {
31+
super(cause);
32+
}
33+
}
34+
35+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
package control.structures.dataflow;
2+
3+
import java.io.Serializable;
4+
import java.util.function.Supplier;
5+
6+
import org.slf4j.Logger;
7+
import org.slf4j.LoggerFactory;
8+
9+
import co.paralleluniverse.fibers.SuspendExecution;
10+
import co.paralleluniverse.strands.dataflow.Val;
11+
import control.structures.utils.InfrastructureUtils;
12+
13+
14+
public class QuasarVarDataflowVariableRepository {
15+
16+
private static final Logger logger = LoggerFactory.getLogger(QuasarVarDataflowVariableRepository.class);
17+
18+
private final static class DV<T extends Serializable> implements DataflowVariable<T>, Serializable {
19+
20+
private static final long serialVersionUID = -7384576069381176916L;
21+
private final Val<T> val = new Val<T>();
22+
private final String variableName;
23+
24+
private DV(String variableName) {
25+
this.variableName = variableName;
26+
}
27+
28+
@Override
29+
public void bind(T value) throws DataflowVariable.AlreadyBoundToIncompatibleValueException {
30+
logger.debug("DV<T>.bind(): '" + variableName + "' : '" + InfrastructureUtils.truncate(value) + "'");
31+
val.set(value);
32+
}
33+
34+
@Override
35+
public T get() throws SuspendExecution, InterruptedException {
36+
logger.debug("DV<T>.get(): '" + variableName + "' : before");
37+
T v = val.get();
38+
logger.debug("DV<T>.get(): '" + variableName + "' : after");
39+
return v;
40+
}
41+
42+
@Override
43+
public String toString() {
44+
T value = null;
45+
if(val.isDone())
46+
try {
47+
value = val.get();
48+
} catch (InterruptedException e) {
49+
// ignore
50+
}
51+
52+
return "DV<T>: '" + variableName + "' val bound?: '" + val.isDone() + "' value: '" + InfrastructureUtils.truncate(value) + "'";
53+
}
54+
55+
@Override
56+
public ResponseVariable<T> response() {
57+
logger.debug("DV<T>.response(): '" + variableName + "'");
58+
return this;
59+
}
60+
61+
@Override
62+
public boolean isDone() {
63+
return val.isDone();
64+
}
65+
}
66+
67+
public static <S extends Serializable> DataflowVariable<S> createReference(Supplier<S> constructor, String name) {
68+
DV<S> dv = new DV<S>(name);
69+
logger.debug("createReference(): " + dv);
70+
return dv;
71+
}
72+
73+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package control.structures.dataflow;
2+
3+
import java.io.Serializable;
4+
5+
public interface ResponseVariable<T extends Serializable> extends Serializable {
6+
7+
public void bind(T value);
8+
9+
}

0 commit comments

Comments
 (0)