[e-lang] Seeking event loop concurrent solution to challenge problem
Kevin Reid
kpreid at mac.com
Thu Sep 24 08:17:22 EDT 2009
On Sep 24, 2009, at 0:27, ihab.awad at gmail.com wrote:
> A lot of us are fans of shared-nothing event loop concurrency, so we
> thought about using HTML5's "workers" as our starting point. However,
> it seems that using these requires a bunch of boilerplate, some of
> which may be automated, and some of which may not. I'd love to see
> someone code the solution in E, say, and we could backtrack from
> there.
Well, there are two levels of "event loop concurrency" to me, so I
think it's best to be a bit more specific:
1. Multiple tasks being performed within a single event loop: they are
interleaved but not parallel.
2. Multiple event loops in seaparate threads -- "communicating event
loops" -- which pass messages.
Since you mention "multi threaded" I assume you want the latter.
> Problem: A multi threaded Web server that serves up a hit count for a
> single page.
>
> Kris Zyp's shared memory solution, from the email thread, is:
>
> var hits = 0;
> var lock = new (require("concurrency")).Lock(); // This just loads a
> module
> function incrementAndGetHits(){
> lock.lock();
> hits++;
> lock.unlock();
> return hits;
> }
> exports.app = function(env) { // Exported function that worker
> threads run
> return {
> status:200,
> headers:{"content-type":"text/plain"},
> body: "This page has been hit " + incrementAndGetHits() + "
> times";
> };
> }
>
> Given that E was essentially built for shared-nothing event loop
> concurrency, what does it look like in E?
OK, so I see that this has nothing for e.g. accepting incoming
connections. We assume the thread pool (vat pool) exists and something
distributes requests among them.
Now, the absolute most straightforward solution would just be to
translate that code above, and strip out the locking. As a plain
function, 'app' just becomes a far reference when passed to the worker
vats, so it is safe and functions as intended. But I assume that we
should consider the 'app' function to be expensive, i.e. it should be
run in multiple threads and only incrementAndGetHits is shared.
Then, the primary practical question is how the app function gets
instantiated in the worker threads.
var hits := 0
def incrementAndGetHits() {
hits += 1
return hits
}
def app implements pbc { # pass-by-construction
# Still a function object, just with extra methods
to run() {
when (def hitsNow := incrementAndGetHits <- ()) -> {
return [
"status" => 200,
"headers" => ["Content-Type": "text/plain"],
"body" => `This page has been hit $hitsNow times`,
]
} catch p {
# This will be executed if the above block has an unexpected
# error OR if the cross-vat incrementAndGetHits request fails
# somehow (e.g. origin vat died).
traceln("Error in handling request: ", p)
return [
"status" => 500,
"headers" => ["Content-Type": "text/plain"],
"body" => `An oopsie happened!`,
]
}
}
to __optUncall() {
# __eval isn't actually implemented yet (MarkM: Why? What's the
# holdup? Is it the unshadowable-names thing? If so, I think we can
# drop it now that we're definitely going GBA), but my
understanding
# is that something like this is the plan.
#
# There are also slight differences in the meta-operations, but
# this can still be done in E-as-it-is-now with slightly different
# spelling and a helper function.
return [__eval, "run", [meta.context(app).getSource(),
meta.getEnv(app),
false,
[].asMap()]]
}
}
(With regard to the length of the above code, please note that it's
mostly comments, fancy formatting, and an extra bit of error handling.)
This makes "app" a _mobile code object_ which is copied into any vat
it is sent to. In any vat but its origin, incrementAndGetHits will be
a far reference, so it is invoked with "<-" rather than ".".
Another way would be for the uncall method to specify "make an app
worker function" by name to the receiving vat; this assumes that all
the vats have access to the same library, which is probably true for a
single web server system.
Either way, the key is that incrementAndGetHits is itself the event-
loop-spanning reference.
--
Kevin Reid <http://switchb.org/kpreid/>
More information about the e-lang
mailing list