Atomic Counters in ActionScript

Our primary mechanism for managing state in ActionScript is through event-driven programming and object properties. However, there are scenarios where we need to handle concurrent operations. In this example, we’ll look at using atomic operations for counters accessed by multiple threads.

package {
    import flash.display.Sprite;
    import flash.utils.setTimeout;
    import flash.system.Worker;
    import flash.system.WorkerDomain;
    import flash.system.MessageChannel;
    import flash.events.Event;

    public class AtomicCounters extends Sprite {
        private var ops:uint = 0;
        private var workerCount:int = 50;
        private var workersCompleted:int = 0;

        public function AtomicCounters() {
            if (Worker.current.isPrimordial) {
                createWorkers();
            } else {
                incrementCounter();
            }
        }

        private function createWorkers():void {
            for (var i:int = 0; i < workerCount; i++) {
                var worker:Worker = WorkerDomain.current.createWorker(Worker.current.loaderInfo.bytes);
                var channel:MessageChannel = Worker.current.createMessageChannel(worker);
                worker.setSharedProperty("channel", channel);
                worker.start();
            }

            Worker.current.setSharedProperty("mainChannel", Worker.current.createMessageChannel(Worker.current));
            Worker.current.sharedProperty("mainChannel").addEventListener(Event.CHANNEL_MESSAGE, onWorkerComplete);
        }

        private function incrementCounter():void {
            for (var c:int = 0; c < 1000; c++) {
                // In ActionScript, we don't have built-in atomic operations
                // So we simulate it by using a single thread (worker) for each counter
                ops++;
            }
            Worker.current.sharedProperty("channel").send("done");
        }

        private function onWorkerComplete(event:Event):void {
            workersCompleted++;
            if (workersCompleted == workerCount) {
                trace("ops:", ops);
            }
        }
    }
}

In this ActionScript example, we’re simulating atomic operations using Workers (similar to threads). Each worker increments the counter 1000 times.

We create 50 workers, each of which will increment the counter exactly 1000 times.

To simulate atomic incrementation, each worker operates on the counter independently, and we collect the results at the end.

After all workers have completed, we print the final value of the counter.

Note that ActionScript doesn’t have built-in atomic operations like Go does. In a real-world scenario, you might need to implement more sophisticated synchronization mechanisms or use third-party libraries for true atomic operations in ActionScript.

To run this program:

  1. Compile the ActionScript code into a SWF file.
  2. Run the SWF file in a Flash Player or AIR runtime environment.

The output should be:

ops: 50000

We expect to get exactly 50,000 operations. This approach simulates atomic operations by using separate workers, each incrementing their own counter, and then combining the results at the end.

Next, we could look at other synchronization mechanisms in ActionScript for managing shared state in multi-threaded scenarios.