Queue Channels en AjSharp

Hace una semanas, implementé channels en mi intérprete AjSharp. Pueden leer sobre el tema en:

Channels and GoRoutines in AjSharp (part 1)
Channels and GoRoutines in AjSharp (part 2)

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

Si uno lee el valor de un canal, y no hay valor disponible, el thread que está tratando de leer se bloquea hasta que el valor esté disponible. Esta es una manera de sincronizar consumidores y productores que operan sobre el canal. Pero algunas veces queremos poner un valor en un canal y continua, sin bloqueo. Para eso, agregué una “queue channel” (podría llamarla queued channel): pueden poner N valores en el canal sin bloqueo, porque se van guardando en una cola interna. El tamaño de la cola se determina en un parámetro en el constructor. La cola está limitada en tamaño para poder preservar sus capacidades de sincronizació.

El nombre de la nueva clase es QueueChannel. Un test:

        [TestMethod]
        public void CreateAndUseQueueChannelWithTenElements()
        {
            QueueChannel channel = new QueueChannel(10);
            for (int k = 1; k <= 10; k++)
                channel.Send(k);
            for (int k = 1; k <= 10; k++)
                Assert.AreEqual(k, channel.Receive());
        }


El canal recibe 10 valores sin bloquearse. Si enviamos más valores, debemos usar otro thread:



        [TestMethod]
        public void CreateAndUseQueueChannelWithMoreEntriesThanSize()
        {
            QueueChannel channel = new QueueChannel(10);
            Thread thread = new Thread(new ThreadStart(delegate()
            {
                for (int k = 1; k <= 20; k++)
                    channel.Send(k);
            }));
            thread.Start();
            for (int k = 1; k <= 20; k++)
                Assert.AreEqual(k, channel.Receive());
        }


Para probarlo en un ejemplo, reescribí el ejemplo de números primos usando queue channels:



numbers = new QueueChannel(10);
running = true;
k = 1;
go while(running) { k++; numbers <- k; }
function filter(in, out, prime)
{
  while (true) 
  {
    value = <-in;
    if (value % prime)
      out <- value;
  }
}
function makefilter(channel, number)
{
  newchannel = new QueueChannel(10);
  go filter(channel, newchannel, number);
  return newchannel;
}
channel = numbers;
number = <-channel;
while (number < 1000) 
{
  PrintLine("Prime " + number);
  
  channel = makefilter(channel, number);
  
  number = <-channel;
}
running = false;


El código está en mi Google code project:



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



Mi motivación para un queue channel apareció en ejemplo de algoritmo genético en paralelo, que sufría de demasiados bloqueos. Veo que un buen algoritmo no necesitaría colas, pero si uno tiene muchos consumidores y productores, y un thread produce valores para ser colocados en más de un canal, podría pasar que al colocar el valor en el canal A, no lleguemos a entregar el valor en el canal B, por bloqueo en la primera operación. Una forma de evitar el bloqueo es usando el comando go:



go channel <- newvalue;


Pero me parece que es demasiado lanzar una goroutine solamente para alimentar un canal.



Tendría que presentar el algoritmo genético en paralelo (que ya hace unos meses presenté), y escribir algunas ideas para implementar un actor model en AjSharp, y usar agentes distribuidos.



Nos leemos!



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

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

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>