Anteckning
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Biblioteket asynkrona agenter (eller bara agentbiblioteket) tillhandahåller en programmeringsmodell som gör att du kan öka robustheten i samtidighetsaktiverad programutveckling. Agentbiblioteket är ett C++-mallbibliotek som höjer upp en aktörsbaserad programmeringsmodell och pågående meddelandeöverföring för grovkorniga dataflöden och pipelining-uppgifter. Agentbiblioteket bygger på komponenterna schemaläggning och resurshantering i Concurrency Runtime.
Programmeringsmodell
Agentbiblioteket tillhandahåller alternativ till delat tillstånd genom att du kan ansluta isolerade komponenter via en asynkron kommunikationsmodell som baseras på dataflöde i stället för kontrollflöde. Dataflöde refererar till en programmeringsmodell där beräkningar görs när alla nödvändiga data är tillgängliga. kontrollflöde refererar till en programmeringsmodell där beräkningar görs i en fördefinierad ordning.
Programmeringsmodellen för dataflöde är relaterad till begreppet meddelandepassering, där oberoende komponenter kommunicerar med varandra i ett program genom att skicka meddelanden.
Agentbiblioteket består av tre komponenter: asynkrona agenter, asynkrona meddelandeblock och funktioner för meddelandeöverföring. Agenter underhåller tillstånd och använder meddelandeblock och meddelandeöverföringsfunktioner för att kommunicera med varandra och med externa komponenter. Med funktioner för meddelandeöverföring kan agenter skicka och ta emot meddelanden till och från de externa komponenterna. Asynkrona meddelandeblock innehåller meddelanden och gör det möjligt för agenter att kommunicera på ett synkroniserat sätt.
Följande bild visar hur två agenter använder meddelandeblock och meddelandeöverföringsfunktioner för att kommunicera. I denna illustration skickar agent1 ett meddelande till agent2 med hjälp av funktionen concurrency::send och ett objekt av typen concurrency::unbounded_buffer.
agent2 använder funktionen concurrency::receive för att läsa meddelandet.
agent2 använder samma metod för att skicka ett meddelande till agent1. Streckade pilar representerar dataflödet mellan agenter. Solida pilar ansluter agenterna till de meddelandeblock som de skriver till eller läser från.
Ett kodexempel som implementerar den här bilden visas senare i det här avsnittet.
Agentprogrammeringsmodellen har flera fördelar jämfört med andra samtidighets- och synkroniseringsmekanismer, till exempel händelser. En fördel är att du genom att använda meddelandeöverföring för att överföra tillståndsändringar mellan objekt kan isolera åtkomst till delade resurser och därmed förbättra skalbarheten. En fördel med meddelandeöverföring är att den kopplar synkronisering till data i stället för att koppla den till ett externt synkroniseringsobjekt. Detta förenklar dataöverföringen mellan komponenter och kan eliminera programmeringsfel i dina program.
När agentbiblioteket ska användas
Använd biblioteket Agenter när du har flera åtgärder som måste kommunicera med varandra asynkront. Med meddelandeblock och funktioner för meddelandeöverföring kan du skriva parallella program utan att kräva synkroniseringsmekanismer som lås. På så sätt kan du fokusera på programlogik.
Agentprogrammeringsmodellen används ofta för att skapa datapipelines eller nätverk. En datapipeline är en serie komponenter som var och en utför en specifik uppgift som bidrar till ett större mål. Varje komponent i en dataflödespipeline utför arbete när den tar emot ett meddelande från en annan komponent. Resultatet av det arbetet skickas till andra komponenter i pipelinen eller nätverket. Komponenterna kan använda mer detaljerade samtidighetsfunktioner från andra bibliotek, till exempel PPL (Parallel Patterns Library).
Exempel
I följande exempel implementeras bilden som visades tidigare i det här avsnittet.
// 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);
}
Det här exemplet genererar följande utdata:
agent1: sending request...
agent2: received 'request'.
agent2: sending response...
agent1: received '42'.
I följande avsnitt beskrivs de funktioner som används i det här exemplet.
Relaterade ämnen
Asynkrona agenter
Beskriver asynkrona agenters roll för att lösa större databehandlingsuppgifter.
Asynkrona meddelandeblock
Beskriver de olika typer av meddelandeblock som tillhandahålls av agentbiblioteket.
Funktioner för meddelandeöverföring
Beskriver de olika rutiner för meddelandeöverföring som tillhandahålls av agentbiblioteket.
Anvisningar: Implementera olika Producer-Consumer mönster
Beskriver hur du implementerar producent-konsument-mönstret i ditt program.
Anvisningar: Tillhandahålla arbetsfunktioner till anrops- och transformeringsklasserna
Illustrerar flera sätt att tillhandahålla arbetsfunktioner till samtidighet::anrop-klassen och samtidighet::transformer-klassen.
Anvisningar: Använda transformator i en datapipeline
Visar hur du använder klassen concurrency::transformer i en datapipeline.
Anvisningar: Välj bland slutförda uppgifter
Visar hur du använder concurrency::choice och concurrency::join klasserna för att välja den första uppgiften som ska fullborda en sökalgoritm.
Anvisningar: Skicka ett meddelande med ett regelbundet intervall
Visar hur du använder klassen concurrency::timer för att skicka ett meddelande med jämna mellanrum.
Anvisningar: Använd ett filter för meddelandeblockering
Visar hur du använder ett filter för att aktivera ett asynkront meddelandeblock för att acceptera eller avvisa meddelanden.
PPL (Parallel Patterns Library)
Beskriver hur du använder olika parallella mönster, till exempel parallella algoritmer, i dina program.
Samtidighetskörning
Beskriver Concurrency Runtime, som förenklar parallell programmering och innehåller länkar till relaterade ämnen.