Re: Web workers: synchronously handling events

On Wed, Dec 29, 2010 at 4:56 AM, Jonas Sicking <jonas@sicking.cc> wrote:
> I definitely agree that workers need more features to take advantage
> of the fact that they are running on their own event loop. One of
> which is the one you are asking for.
>
> We could add something like:
>
> boolean checkPendingMessages();
>
> which would return true if there are pending messages. The script
> running in the worker could use this information to return to the
> event loop to process these messages only when needed. One downside
> with this API is that there is a risk that people could write:

Is there a problem with synchronously delivering the next pending
message event, rather than having to return all the way out to allow
it to run?  Code shouldn't need to be engineered to allow returning
and resuming in order to receive messages, as if we're still in a UI
thread.

Note that it's critical that this run only events from a specific
message port, so only targetted messages are run and not unrelated
ones.

I've used this approach with C++ worker threads and it works very
well; it allows thread work to be cancelled at specific, predetermined
points, without exposing significant threadsafety issues to the thread
itself, and allowing deeply nested algorithm code to handle
cancellation in a consistent way:

var checkForCancellation()
{
    // run all waiting messages from this port
    while(cancellationPort.runPendingMessage())
        ;
    // if a message set cancellation, stop working
    if(cancel)
        throw "Operation cancelled";
}

try {
    checkForCancellation();
    doStuff();
    while(var i = 0; i < longRunningLoop; ++i)
    {
        checkForCancellation();
        doMoreWork();
    }
} catch...

> An alternative solution would be something like:
>
> MessageInfo getMessageIfExists();
>
> which would return an object containing the message data if a message
> was pending and remove the message from the queue of pending messages.
> If there are no pending messages null is returned and the message
> queue remains empty. This makes it significantly harder to write code
> like the above. However it might make coding somewhat more awkward
> since you likely will have to deal with messages arriving two ways,
> through the normal event loop and through getMessageIfExists.

I avoided that in my suggestion, since it seems likely to cause
confusing bugs and it's hard to think of when this behavior would
really be wanted.  If it was, you could do something like this, I
think:

function getPendingMessageWithoutDelivery(port)
{
    var onmessage = port.onmessage;
    try {
        port.onmessage = null;
        return port.runPendingMessage(); // returns the handled
message or null if none
    } finally {
        port.onmessage = onmessage;
    }
}

-- 
Glenn Maynard

Received on Wednesday, 29 December 2010 18:34:24 UTC