Stateful Goroutines in ActionScript

import flash.utils.Dictionary;
import flash.events.TimerEvent;
import flash.utils.Timer;

class ReadOp {
    public var key:int;
    public var resp:Function;
    
    public function ReadOp(key:int, resp:Function) {
        this.key = key;
        this.resp = resp;
    }
}

class WriteOp {
    public var key:int;
    public var val:int;
    public var resp:Function;
    
    public function WriteOp(key:int, val:int, resp:Function) {
        this.key = key;
        this.val = val;
        this.resp = resp;
    }
}

public class StatefulWorker {
    private var state:Dictionary = new Dictionary();
    private var readOps:uint = 0;
    private var writeOps:uint = 0;
    
    public function StatefulWorker() {
        var timer:Timer = new Timer(1000, 1);
        timer.addEventListener(TimerEvent.TIMER_COMPLETE, onTimerComplete);
        timer.start();
        
        for (var r:int = 0; r < 100; r++) {
            startReadWorker();
        }
        
        for (var w:int = 0; w < 10; w++) {
            startWriteWorker();
        }
    }
    
    private function startReadWorker():void {
        var readTimer:Timer = new Timer(1);
        readTimer.addEventListener(TimerEvent.TIMER, function(e:TimerEvent):void {
            var read:ReadOp = new ReadOp(
                int(Math.random() * 5),
                function(value:int):void {
                    readOps++;
                }
            );
            handleRead(read);
        });
        readTimer.start();
    }
    
    private function startWriteWorker():void {
        var writeTimer:Timer = new Timer(1);
        writeTimer.addEventListener(TimerEvent.TIMER, function(e:TimerEvent):void {
            var write:WriteOp = new WriteOp(
                int(Math.random() * 5),
                int(Math.random() * 100),
                function(success:Boolean):void {
                    writeOps++;
                }
            );
            handleWrite(write);
        });
        writeTimer.start();
    }
    
    private function handleRead(read:ReadOp):void {
        read.resp(state[read.key] || 0);
    }
    
    private function handleWrite(write:WriteOp):void {
        state[write.key] = write.val;
        write.resp(true);
    }
    
    private function onTimerComplete(e:TimerEvent):void {
        trace("readOps:", readOps);
        trace("writeOps:", writeOps);
    }
}

This example demonstrates a stateful worker in ActionScript that manages concurrent read and write operations. Here’s an explanation of the code:

  1. We define ReadOp and WriteOp classes to encapsulate read and write operations.

  2. The StatefulWorker class manages the state and operations:

    • It uses a Dictionary to store the state.
    • It starts 100 read workers and 10 write workers.
    • Each worker runs on a Timer to simulate continuous operations.
  3. Read operations:

    • Generate a random key.
    • Call handleRead which retrieves the value from the state.
    • Increment the readOps counter.
  4. Write operations:

    • Generate random key and value.
    • Call handleWrite which updates the state.
    • Increment the writeOps counter.
  5. After one second, the program prints the total number of read and write operations performed.

This ActionScript implementation uses Timers and event listeners to simulate concurrent operations, as ActionScript doesn’t have built-in support for true concurrency like goroutines in Go.

To run this program:

  1. Create a new ActionScript project in your preferred IDE or text editor.
  2. Copy this code into a file named StatefulWorker.as.
  3. Compile and run the project.

The output will show the number of read and write operations performed in one second, similar to:

readOps: 71708
writeOps: 7177

This approach demonstrates how to manage shared state and perform concurrent-like operations in ActionScript, even though it doesn’t have true concurrency support like Go.