Compartilhar via


Biblioteca de Agentes Assíncronos

A biblioteca assíncrona de agentes (ou simplesmente a biblioteca dos agentes) fornecem um modelo de programação que permite aumentar a robustez do desenvolvimento de aplicativos simultaneidade- habilitado. A biblioteca dos agentes é a biblioteca de modelo criando c que promove uma programação baseada ator- modelo e a mensagem em processo que passa para o fluxo de dados de alta granularidade e que canaliza tarefas. A biblioteca dos agentes é baseada nos componentes de programação e gerenciamento de recursos de tempo de execução de simultaneidade.

Modelo de Programação

A biblioteca dos agentes fornece alternativas para estado compartilhado deixando o conectar componentes isolados através de um modelo de comunicação assíncrona que é baseado no fluxo de dados em vez de fluxo de controle. O fluxo de dados se refere a um modelo de programação em que as computações são feitas quando todos os dados necessários estão disponíveis; o fluxo de controle se refere a um modelo de programação em que as computações sejam feitas em uma ordem índice.

O modelo de programação de fluxo de dados está relacionado ao conceito de mensagem que transmite, onde os componentes independentes de um programa se comunicam um com o outro enviando mensagens.

A biblioteca dos agentes é composto de três componentes: agentes assíncronas, blocos assíncronas da mensageme, mensagem- passar funções. Os agentes mantêm o estado, os blocos e da mensagem de uso e as funções mensagem- passar para se comunicar um com o outro e com os componentes externos. Mensagem- passando as funções permitem que os agentes para enviar e receber mensagens ao e os componentes externos. Os blocos assíncronas de mensagem mantêm mensagens e habilita agentes para se comunicar em uma forma sincronizada.

A ilustração a seguir mostra como dois blocos agentes da mensagem de uso e funções mensagem- passar para se comunicar. Nesta ilustração, os envios de agent1 uma mensagem a agent2 usando a função de concurrency::send e um concurrency::unbounded_buffer objeto. agent2 usa a função de concurrency::receive para ler a mensagem. agent2 usam o mesmo método para enviar uma mensagem a agent1. As setas tracejadas representam o fluxo de dados entre agentes. As setas contínuas conectam os agentes aos blocos da mensagem que gravam ou lido.

Os componentes da biblioteca de agentes

Um exemplo de código que implementa esta ilustração é mostrado mais adiante neste tópico.

O modelo de programação do agente tem várias vantagens sobre outros mecanismos de simultaneidade e de sincronização, por exemplo, eventos. Uma vantagem é que o uso da mensagem que transmite para passar as alterações de estado entre objetos, você poderá isolar o acesso a recursos compartilhados, e assim melhorar a escalabilidade. Uma vantagem de passar da mensagem é ligado a sincronização dos dados em vez de cadeia de caracteres a um objeto externo de sincronização. Isso simplifica a transmissão de dados entre os componentes e pode eliminar erros de programação em seus aplicativos.

Quando Usar a Biblioteca de Agentes

Use a biblioteca dos agentes quando você tiver várias operações que devem se comunicar um com o outro de forma assíncrona. Os bloqueios da mensagem e as funções mensagem- passar permitem escrever aplicativos paralelos sem exigir mecanismos de sincronização como bloqueios. Isso permite que você se concentre na lógica do aplicativo.

O modelo de programação do agente normalmente é usado para criar pipelines de dados ou redes. Um pipeline de dados é uma série de componentes, que executa uma tarefa específica que contribui para uma meta maior. Cada componente em um pipeline de fluxo de dados executa o trabalho quando o recebe uma mensagem de outro componente. O resultado desse trabalho é passado para outros componentes no pipeline ou na rede. Componentes podem usar uma funcionalidade mais refinado de simultaneidade de outras bibliotecas, por exemplo, Biblioteca de padrões paralelos (PPL).

Exemplo

O exemplo a seguir implementa a ilustração mostrada anteriormente neste tópico.

// 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 exemplo gera a seguinte saída:

  

Os tópicos a seguir descrevem a funcionalidade usada neste exemplo.

Tópicos relacionados