GoRoutines y Canales en C#

Published on Author lopezLeave a comment

En post anteriores:

Canales y GoRoutines en AjSharp (Part 1)
Canales y GoRoutines en AjSharp (Part 2)

describí la implementación de gorutinas (goroutines, como en el lenguaje Go de Google), y canales en mi intérprete AjSharp. Al final del año que pasó, escribí una prueba rápida, implementando los mismos conceptos, pero para ser consumidos esta vez desde C# directamente. Pueden ver el código en

http://code.google.com/p/ajcodekatas/source/browse/#svn/trunk/AjConcurr

Primero, porté la clase Channel:

public class Channel
{
    private AutoResetEvent sethandle = new AutoResetEvent(false);
    private AutoResetEvent gethandle = new AutoResetEvent(false);
    private object value;

    public void Send(object value)
    {
        this.gethandle.WaitOne();
        this.value = value;
        this.sethandle.Set();
    }

    public object Receive()
    {
        this.gethandle.Set();
        this.sethandle.WaitOne();
        object result = this.value;
        return result;
    }
}

El código tiene una clase estática GoRoutines, con métodos como:

public static void Go(Action action)
{
    Thread thread = new Thread(new ParameterizedThreadStart(GoRoutines.RunAction));
    thread.IsBackground = true;
    thread.Start(action);
    //ThreadPool.QueueUserWorkItem(new WaitCallback(RunAction), action);
}

public static void Go(ITask task)
{
    Thread thread = new Thread(new ParameterizedThreadStart(GoRoutines.RunTask));
    thread.IsBackground = true;
    thread.Start(task);
    //ThreadPool.QueueUserWorkItem(new WaitCallback(RunTask), task);
}

Pueden lanzar una Action (lo que es en el framework delegate System.Action<>), en un nuevo thread (traté de hacerlo poniendo la tarea en la cola de ThreadPool, pero, no sé por qué, el rendimiento pasó a ser muy bajo; mi intento quedó en comentarios del código de arriba).

Cuando una acción recibe parámetros, se encapsulan los dos en una Task<>, como esta que recibe dos parámetros:

public class Task<T1, T2> : ITask
{
    private Action<T1, T2> action;
    private T1 parameter1;
    private T2 parameter2;

    public Task(Action<T1, T2> action, T1 parameter1, T2 parameter2)
    {
        this.action = action;
        this.parameter1 = parameter1;
        this.parameter2 = parameter2;
    }

    public void Run()
    {
        this.action(this.parameter1, this.parameter2);
    }
}

(hay clases Task para uno, dos o tres parámetros).

Pueden invocar GoRoutines.Go directamente, especificando una acción y sus parámetros:

public static void Go<T1, T2>(Action<T1, T2> action, T1 parameter1, T2 parameter2)
{
    Go(new Task<T1, T2>(action, parameter1, parameter2));
}

Podemos escribir esta invocación usando expresiones lambda:

[TestMethod]
public void RunGoRoutineWithTwoParameters()
{
    int i = 0;
    AutoResetEvent handle = new AutoResetEvent(false);
    GoRoutines.Go((x, y) => { i = x + y; handle.Set(); }, 2, 3);
    handle.WaitOne();
    Assert.AreEqual(5, i);
}

Con todo esto implementado, escribí una aplicación de consola  AjConcurr.Primes, reimplementando el ejemplo de números primos de mi anterior post:

Channel numbers = new Channel();
GoRoutines.Go(() => { for (int k = 2; ; k++) numbers.Send(k);  });
Channel channel = numbers;
int prime = 0;
while (prime < 1000)
{
    prime = (int)channel.Receive();
    Console.WriteLine(prime);
    Channel newchannel = new Channel();
    GoRoutines.Go((input, output, p) =>
    {
       while (true)
       {
           int number = (int)input.Receive();
           if ((number % p) != 0)
               output.Send(number);
       }
    }, channel, newchannel, prime);
    channel = newchannel;
}

Me gusta ver este código formateado en pastie:

http://pastie.org/761916

Próximos pasos:

– Mejorar Channel para soportar múltiples productores y consumidores de valores que operan de forma simultánea sobre el mismo canal.

– Agregar soporte de Futures

– Agregar características de reactive programming (sé que está el Reactive Framework, quería experimentar algo con código propio).

Nos leemos!

Angel “Java” Lopez

http://www.ajlopez.com

http://twitter.com/ajlopez

Leave a Reply

Your email address will not be published. Required fields are marked *