January 16, 2008 11:42 AM
Threads in javascript and actionscript are non-existent. However, the runtime (browser or flash respectively) is in most cases multi-threaded. Even this does not imply that multiple actionscript functions can get called simultaneously. What confuses1 developers though is the fact that if there are multiple events, your callback function may get called multiple times and these will execute serially but before the screen updates. This can be mistook for what may seem like multi-threaded behavior especially if there is some constraint dependent upon the screen refreshing.

Usually when you want to simulate or fake multi-thread behavior2, you split your work into chunks and defer processing of the next chunk after a screen update so that the UI doesn't block when you are doing CPU intensive tasks. This situation is pretty common and necessary for the application to be responsive.

Alex Harui has generalized this into PseudoThread and it basically uses the stage's RENDER event to defer processing. His code performs as much Actionscript computation as possible limited by the time needed to maintain the frame rate.

Interestingly, I ran into a mutex implementation in javascript which uses a variant of a mutual exclusion algorithm intended for a system of multiple threads when the only communication between them is shared memory. More details are present in the link. The idea of the algorithm is that all critical section pieces are given a unique number. Each section waits for jobs that were registered before them to complete. In Javascript, this is done via setTimeout(). That is, all methods run, wait for methods before them to complete via setTimeout() and then run it's code.

Basically, this "mutex" enforces ordered execution of logical blocks.

Using the above logic, I have written an actionscript class called "PseudoMutex" which complements PseudoThread. Note that this mutex is actually only useful to order the execution of logical units between different threads3. It doesn't actually provide mutual exclusion, instead provides an illusion of ordering execution of code within our existing context switching code. If there was no pseudo thread, there would be no need for pseudo mutex.

The example (view source enabled) below tries to illustrate visually the working of the pseudo mutex:

PseudoMutex Example

PseudoMutex Example

There are 2 demos in the example. Both of them have 3 textarea components being updated with data (incremented counter from a shared source) via 3 pseudo thread functions. Pseudo mutexes are used to ensure the order in which the pseudo thread slices control to each thread function.

  1. The barrier demo shows how the pseudo mutex can be used to ensure that one thread checks for a shared value before the other. Thread 3 waits for thread 2 to reach a particular count and thread 1 only starts checking for a higher count once thread 3 has completed it's critical section.
  2. The ordering demo uses pseudo mutexes to ensure that the third thread gets first control (i.e number 1 from shared data source) and then control is passed to the first thread and finally to the thread. This order is entirely dependent on the order in which the critical sections were registered with the mutex.

Note: The pseudo thread code has been modified so that only one computation happens before a screen update. This is for demo purposes only.

Working

The pseudo thread calls the registered thread function till the function returns a value indicating that they have completed. The order in which the thread functions execute depends upon the order in which the constructor of pseudo thread was called. Apart from this, we have no control over when a particular thread function should get called. This is the deficiency that the pseudo mutex attempts to address.

The pseudo mutex returns false when it is not the right time for it to execute it's code. Then, the function in the pseudo thread also returns true indicating that the thread wants to yield. This is continued till the critical section is executed after which the pseudo thread can yield and resume work in it's own style.

Multiple mutexes are supported and each will have it's own queue of critical sections which get executed in order.

Visualizing the critical section in this is so drastically different from how you think of it in C or C++ that I'm not sure about how useful this code will be. Any feedback is appreciated.

CategoryFlex Comment(s)


[1] Another common cause for confusion is dispatchEvent(). Some developers don't realize that your event handlers will get called immediately when a dispatchEvent() is called.
[2] This sort of fake multi-threading was even possible in the old days of DOS C code. You could save your point in code using a setjmp() call and do a non-local jump back to the same point via longjmp() saving and restoring all the registers along the way.
[3] Thread = Pseudo Thread.

Copyright © 2004-2011 Anirudh Sasikumar. All rights reserved.
Last Updated: January 17, 2008 3:41 PM