Getting Started: How to Pause a Retlang Process Context

Well, in the words of Scott Hanselman “We’ll see how long this lasts.”.  Anyway, I should start as I mean to go on by providing some code that’s actually useful.

I’ve been using Mike Rettig‘s Retlang library a fair bit recently, and have nothing but praise for it.  I’ll go into more detail about why it’s great at a later date, but here I’ll just detail a problem that I encountered and how to solve it.

Let’s say that you’ve got a system that writes to the database and you need to bring the database down.  You need to stop your Retlang-using service from processing (or at least certain process contexts). 

Luckily, Retlang is a very well designed system with lots of injection points.  Here, we use the fact that each process context has an executor associated with it that actually processes the commands and we pause that.  There are the following design decisions worth understanding:

  • Retlang is heading increasingly towards a thread pool model, and that this code only works with the original “one thread per context” model.  If you used this in a thread pool model, it would not only pause the contexts you wanted to pause, but any contexts sharing the thread.
  • Batched commands are paused halfway through.  This behaviour is what I required, but it’s easy to change.
  • Existing running commands will complete.  This is desirable, since any process that could be paused mid-command could also be split into separate commands.
  • There’s no way to tell when the currently running commands complete.  This is unlikely to be a problem for you.

To use it, just create the context with this executor.  As you can see, the HaltingExecutor passes its commands onto an underlying executor.  This allows you to add logging or your own custom logic that you’ve already implemented.

using Retlang;
using System.Threading;

namespace ColourCoding.Parallel
{
public class HaltableExecutor : ICommandExecutor
{
ManualResetEvent _block = new ManualResetEvent(true);
ICommandExecutor _underlying;
bool _isHalted = false;

public HaltableExecutor()
{
_underlying = new Retlang.CommandExecutor();
}

public HaltableExecutor(ICommandExecutor underlying)
{
_underlying = underlying;
}

public void ExecuteAll(Command[] toExecute)
{
foreach (Command command in toExecute)
{
if (_block.WaitOne())
{
_underlying.ExecuteAll(new Command[] { command });
}
}
}

public void Halt()
{
lock (_block)
{
_isHalted = true;
_block.Reset();
}
}

public void Resume()
{
lock (_block)
{
_isHalted = false;
_block.Set();
}
}

public bool IsHalted
{
get
{
lock (_block)
{
return _isHalted;
}
}
}
}
}
Technorati Tags: ,

Published by

Julian Birch

Full time dad, does a bit of coding on the side.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s