A minimal actor framework

time to read 3 min | 506 words

Originally posted at 4/29/2011

For one of our projects, we need the ability to asynchronously push changes through a socket, since we actually care about the order of actions, we realized that we couldn’t really use purely async IO. For example, consider the following actions:

connection.Send(“abc”);
connection.Send(“def”);

I care that abc will be sent before def, and I care that all of abc will be sent before anything else is sent through that connection. What I don’t care about is whatever I have anything else sent between abc and def.

All of that can be had using:

public class Actor<TState>
{
    public TState State { get; set; }

    private readonly ConcurrentQueue<Action<TState>> actions = new ConcurrentQueue<Action<TState>>();
    private Task activeTask;

    public void Act(Action<TState> action)
    {
        actions.Enqueue(action);

        if (activeTask != null) 
            return;

        lock(this)
        {
            if (activeTask != null) 
                return;
            activeTask = Task.Factory.StartNew(ExecuteActions);
        }
    }

    private void ExecuteActions()
    {
        Action<TState> action;
        while (actions.TryDequeue(out action))
        {
            action(State);
        }
        lock(this)
        {
            activeTask = null;
        }
    }
}

The actions will execute synchronously for each actor, and it satisfy my requirement for how to deal with this quite nicely, even if I say so myself Smile

In truth, the code above isn’t really good. Can you consider ways to improve this?