Canales y GoRoutines en AjSharp (Parte 1)

Hace dos años ya, estuve explorando Microsoft Robotics, y su librería CCR (Concurrency and Coordination). Esta tiene la implementación una port: podemos enviar un objeto por el port, y recibirlo y procesarlo en otra pieza de código, que puede ejecutarse en otro hilo de ejecución. También tiene la capacidad de ejecutar ambas partes en diferentes máquinas, una forma de conectar aplicaciones distribuidas. Yo escribí sobre el tema en:

Distributed Agents using DSS/VPL
Agentes Distribuidos usando DSS/VPL
Agentes Distribuidos y Fractales usando DSS/VPL
Genetic Algorithms with AjAgents and Concurrency and Coordination Runtime (CCR)
Algoritmos Genéticos con AjAgents y Concurrency and Coordination Runtime (CCR)
CCR posts (English)
Posts sobre CCR en español

Todo esto, me llevó a encontrarme con el concepto de canal: Channel programming (Wikipedia) y este año, leí sobre el nuevo lenguaje de Google, el lenguaje Go: http://golang.org. Pueden leer sobre Go y sus capacidades de manejo de concurrencia (go routines, channels) en: http://golang.org/doc/go_tutorial.html#tmp_346

También comencé a leer sobre proyecto Axum de Microsoft: http://en.wikipedia.org/wiki/Axum_%28programming_language%29

Con toda esta base, el último sábado agregué soporte de canales y goroutines en mi intérprete AjSharp (otros posts AjSharp interpreter). Pueden bajar y ver la versión actual desde http://code.google.com/p/ajcodekatas en trunk/AjLanguage

Primero, agregué un tipo nativo .NET Channel (a mejorar: agregar soporte para que el canal pueda soportar varios send y receive desde más de un thread):

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;
    }
}


Cuando se envía un objeto a un canal, el thread que lo envía se bloquea hasta que otro thread lea el canal (pienso agregar un QueueChannel, donde se puedan enviar varios objetos, a guardar en una cola, sin para los threads; supongo que la cola tendrá un tamaño limitado, para ir auto-coordinando los productores y consumidores de objetos del canal).



Siguiendo las ideas de goroutines en el lenguaje Go, agregué un nuevo comando en AjSharp: go <command> (ok, no mucha creatividad aquí… ;-)… igual hay que aclarar que los goruotines en Go tienen muchas más características que las que implemento acá). Esta nueva palabra lanza el comando en un thread separado, que comparte las variables del original, como en este ejemplo (recordemos que AjSharp tiene acceso a los objetos y clases nativas de .NET):



handle = new System.Threading.AutoResetEvent(false);
one = 0;
go { one = 1; handle.Set(); }
handle.WaitOne();
result = one;


Todo esto se agregó a la máquina de ejecución de AjSharp (por ejemplo, Channel es un tipo ya declarado dentro de la máquina, sin necesidad de usar el namespace completo), podemos usar entonces:



channel = new Channel();
go channel.Send(10);
result = channel.Receive();


Luego de tener esto andando, modifiqué algo más. Fue simple agregar “syntax sugar” al parser de AjSharp para que



<- channel



sea igual a



channel.Receive()



y que



channel <- value;



sea una forma de escribir:



channel.Send(value);



Entonces, el ejemplo anterior se puede escribir como:



channel = new Channel();
go channel <- 10;
result = <- channel;


En otro post, describiré algunos usos de estas características, con algún detalle de implementación. Ver el código actual en:



http://code.google.com/p/ajcodekatas/source/browse/#svn/trunk/AjLanguage
Nos leemos!



Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez

This entry was posted in 1389, 1390, 8926. Bookmark the permalink.

3 Responses to Canales y GoRoutines en AjSharp (Parte 1)

  1. Propongo una sintáxis más distintiva para Send y Receive:

    channel = new Channel();
    go 10 -> channel;
    result = <- channel;

    Y ya que estamos: ¿necesitás el operador “new”? Algo que me gusta mucho de Python es que las instancias se crean llamando derecho al constructor:

    channel = Channel();

    ¿Hay algún otro contexto en que necesites llamar al constructor?

    Cada vez me gusta más AjSharp. En algún momento debería tomarme una semana sabática para dedicarle al proyecto (quiero correrlo en Mono, entre otras cosas, para usarlo para correr scripts en Mac OS).

  2. lopez says:

    Gracias, gente, por comentar!

    @MartinSalias… hmmm… necesito el new porque AjSharp es no tipado. Podria agregarle tipos a las variables, pero por ahora no lo necesite.

    Use el operador < - para seguir la notacion de Go original (por si alguien quiere adoptar algo de Go a esto, no tenga que pelear tanto). Tengo pensado usar -> para

    port -> ejecutar algo

    es decir, en vez de un canal normal, poner esto:

    port < - valor // deja algo en la port

    port -> hacer1
    port -> hacer2 // por cada valor en port ejecutar hacer1 y hacer 2

    tipo como evento, varios observer sobre el port.

    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 *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>