¿Le resultó útil esta página?
Sus comentarios sobre este contenido son muy importantes. Háganos saber su opinión.
¿Tiene comentarios adicionales?
Caracteres restantes: 1500
Exportar (0) Imprimir
Expandir todo
Este artículo se tradujo de forma manual. Mueva el puntero sobre las frases del artículo para ver el texto original. Más información.
Traducción
Original

Biblioteca de agentes asincrónicos

La Biblioteca de agentes asincrónicos (o simplemente Biblioteca de agentes) proporciona un modelo de programación que permite mejorar la solidez del desarrollo de aplicaciones con la simultaneidad habilitada. La biblioteca de agentes es una biblioteca de plantillas de C++ que promueve un modelo de programación basado en actores y el paso de mensajes en proceso para tareas genéricas de flujo de datos y canalización. La Biblioteca de agentes se basa en los componentes de programación y administración de recursos del Runtime de simultaneidad.

La biblioteca de agentes proporciona alternativas al estado compartido ya que permite conectar componentes aislados a través de un modelo de comunicación asincrónica basado en el flujo de datos y no en el flujo de control. El término flujo de datos hace referencia a un modelo de programación donde se realizan los cálculos cuando están disponibles todos los datos necesarios; el término flujo de control hace referencia a un modelo de programación donde los cálculos se realizan en un orden predeterminado.

El modelo de programación basado en el flujo de datos está relacionado con el concepto paso de mensajes, donde los componentes independientes de un programa comunican entre sí enviándose mensajes.

La Biblioteca de agentes consta de tres componentes: agentes asincrónicos, bloques de mensajes asincrónicos y funciones de paso de mensajes. Los agentes mantienen el estado y utilizan bloques de mensajes así como funciones de paso de mensajes para comunicarse entre sí y con componentes externos. Las funciones de paso de mensajes permiten a los agentes enviar y recibir mensajes de los componentes externos. Los bloques de mensajes asincrónicos contienen mensajes y permiten a los agentes comunicar de manera sincronizada.

En la siguiente ilustración, se muestra cómo dos agentes utilizan bloques de mensajes y funciones de paso de mensajes para comunicar. En esta ilustración, agent1 envía un mensaje a agent2 mediante la función concurrency::send y un objeto concurrency::unbounded_buffer. agent2 usa la función concurrency::receive para leer el mensaje. agent2 utiliza el mismo método para enviar un mensaje a agent1. Las flechas de líneas discontinuas representan el flujo de datos entre los agentes. Las flechas de líneas continuas conectan los agentes con los bloques de mensajes en los que escriben o que leen.

Los componentes de la Biblioteca de agentes

Más adelante en este tema figura un ejemplo de código en el que se implementa esta ilustración.

El modelo de programación basado en agentes ofrece varias ventajas con respecto a otros mecanismos de simultaneidad y sincronización, como eventos. Una de las ventajas consiste en que, al usar el paso de mensajes para transmitir los cambios de estado de un objeto a otro, se puede aislar el acceso a los recursos compartidos y, de este modo, mejorar la escalabilidad. El paso de mensajes ofrece como ventaja que vincula la sincronización a los datos en lugar de vincularla a un objeto de sincronización externo. De este modo, se simplifica la transmisión de datos entre los componentes y se pueden eliminar los errores de programación de las aplicaciones.

Utilice la Biblioteca de agentes en el caso de varias operaciones que deben comunicar entre sí de forma asincrónica. Los bloques de mensajes y las funciones de paso de mensajes permiten escribir aplicaciones paralelas sin necesidad de mecanismos de sincronización, como bloqueos. De este modo, el usuario podrá centrarse en la lógica de la aplicación.

El modelo de programación basado en agentes suele usarse para crear canalizaciones de datos o redes. Una canalización de datos es una serie de componentes, cada uno de los cuales realiza una tarea concreta que contribuye a lograr un objetivo mayor. Cada componente de una canalización de flujo de datos realiza un determinado trabajo cuando recibe un mensaje de otro componente. El resultado de ese trabajo se pasa a otros componentes de la canalización o red. Los componentes pueden utilizar la funcionalidad de simultaneidad más específica de otras bibliotecas, como la Parallel Patterns Library (PPL).

En el siguiente ejemplo, se implementa la ilustración que se muestra anteriormente en este tema.

// basic-agents.cpp 
// compile with: /EHsc
#include <agents.h>
#include <string>
#include <iostream>
#include <sstream>

using namespace concurrency;
using namespace std;

// This agent writes a string to its target and reads an integer 
// from its source. 
class agent1 : public agent 
{
public:
   explicit agent1(ISource<int>& source, ITarget<wstring>& target)
      : _source(source)
      , _target(target)
   {
   }

protected:
   void run()
   {
      // Send the request.
      wstringstream ss;
      ss << L"agent1: sending request..." << endl;
      wcout << ss.str();

      send(_target, wstring(L"request"));

      // Read the response. 
      int response = receive(_source);

      ss = wstringstream();
      ss << L"agent1: received '" << response << L"'." << endl;
      wcout << ss.str();

      // Move the agent to the finished state.
      done();
   }

private:   
   ISource<int>& _source;
   ITarget<wstring>& _target;
};

// This agent reads a string to its source and then writes an integer 
// to its target. 
class agent2 : public agent 
{
public:
   explicit agent2(ISource<wstring>& source, ITarget<int>& target)
      : _source(source)
      , _target(target)
   {
   }

protected:
   void run()
   {
      // Read the request.
      wstring request = receive(_source);

      wstringstream ss;
      ss << L"agent2: received '" << request << L"'." << endl;
      wcout << ss.str();

      // Send the response.
      ss = wstringstream();
      ss << L"agent2: sending response..." << endl;
      wcout << ss.str();

      send(_target, 42);

      // Move the agent to the finished state.
      done();
   }

private:   
   ISource<wstring>& _source;
   ITarget<int>& _target;
};

int wmain()
{
   // Step 1: Create two message buffers to serve as communication channels 
   // between the agents. 

   // The first agent writes messages to this buffer; the second 
   // agents reads messages from this buffer.
   unbounded_buffer<wstring> buffer1;

   // The first agent reads messages from this buffer; the second 
   // agents writes messages to this buffer.
   overwrite_buffer<int> buffer2;

   // Step 2: Create the agents.
   agent1 first_agent(buffer2, buffer1);
   agent2 second_agent(buffer1, buffer2);

   // Step 3: Start the agents. The runtime calls the run method on 
   // each agent.
   first_agent.start();
   second_agent.start();

   // Step 4: Wait for both agents to finish.
   agent::wait(&first_agent);
   agent::wait(&second_agent);
}

Este ejemplo produce el siguiente resultado:

              
                agent1: sending request...
agent2: received 'request'.
agent2: sending response...
agent1: received '42'.
              
            

En los siguientes temas, se describe la funcionalidad que se usa en este ejemplo.

Agentes asincrónicos

Se describe el rol de los agentes asincrónicos a la hora de resolver tareas de computación mayores.

Bloques de mensajes asincrónicos

Se describen los diversos tipos de bloques de mensajes proporcionados por la Biblioteca de agentes.

Funciones que pasan mensajes

Se describen las diversas rutinas de paso de mensajes proporcionadas por la Biblioteca de agentes.

Cómo: Implementar varios modelos productor-consumidor

Se describe cómo se implementa el modelo productor-consumidor en la aplicación.

Cómo: Proporcionar funciones de trabajo a las clases call y transformer

Ilustra varias maneras de proporcionar funciones de trabajo a las clases concurrency::call y concurrency::transformer.

Cómo: Usar la clase transformer en una canalización de datos

Muestra cómo usar la clase concurrency::transformer en una canalización de datos.

Cómo: Seleccionar tareas completadas

Muestra cómo usar las clases concurrency::choice y concurrency::join para seleccionar la primera tarea para completar un algoritmo de búsqueda.

Cómo: Enviar un mensaje a intervalos periódicos

Muestra cómo se usa la clase concurrency::timer para enviar un mensaje de manera periódica.

Cómo: Utilizar un filtro de bloque de mensaje

Muestra cómo usar un filtro para permitir que un bloque de mensajes asincrónicos para aceptar o rechazar los mensajes.

Parallel Patterns Library (PPL)

Se describe cómo utilizar diferentes modelos paralelos, como los algoritmos paralelos, en las aplicaciones.

Runtime de simultaneidad

Se describe el Runtime de simultaneidad, que simplifica la programación en paralelo, y contiene vínculos a temas relacionados.

Adiciones de comunidad

Mostrar:
© 2015 Microsoft