To demonstrate how easy this is, check out the code:
entrypoint : () -> (){ task(asyncjob1) { debugwritestring(concat("First: ", cast(string, pi(10000.0)))) } task(asyncjob2) { debugwritestring(concat("Second: ", cast(string, pi(50000.0)))) } debugwritestring("Please wait, async tasks running...")}pi : (real(denominator_limit)) -> (real(retval, 0.0)){ real(denominator, 1.0) boolean(isplus, true) do { real(div, 0.0) assign(div, divide(4.0, denominator)) if(equal(isplus, true)) { assign(retval, add(retval, div)) assign(isplus, false) } else { assign(retval, subtract(retval, div)) assign(isplus, true) } assign(denominator, add(denominator, 2.0)) } while(less(denominator, denominator_limit))}
That's it. Creating a thread and spinning off work is literally the matter of adding one keyword to a code block. Behind the scenes, the Epoch VM does all the threading magic, and away you go.
The next important piece is preventing access to global state from within tasks. In Epoch, the sole way to get data in and out of a task is to use message passing. I plan on implementing a simple lockless queue for this purpose; assuming that works as intended, the threading implementation will be 100% lock free.
Right now there's still a few lingering bugs in the thread splitting logic, especially related to tracking metadata for lexical scopes. That should prove interesting to solve.
But for now, it's time to go see Watchmen. Epoch can rest for a few hours [smile]
Cant wait to see more of this stuff. Keep it up!!!