Megosztás:


Aszinkron ügynökök könyvtára

Az Aszinkron ügynökök tára (vagy csak az Ügynökök tára) egy olyan programozási modellt biztosít, amely lehetővé teszi az egyidejűség-kompatibilis alkalmazásfejlesztés robusztusságának növelését. Az Agents Library egy C++ sablontár, amely támogatja az aktoralapú programozási modellt, és lehetővé teszi a folyamaton belüli üzenetküldést durva szemcsés adatáramlási és csővezeték feladatokhoz. Az Ügynökkódtár az egyidejűségi futtatókörnyezet ütemezési és erőforrás-kezelési összetevőire épül.

Programozási modell

Az Ügynökök tára alternatív megoldásokat kínál a megosztott állapotok helyett, ha lehetővé teszi az izolált összetevők összekapcsolását egy adatfolyamon alapuló aszinkron kommunikációs modellel a vezérlési folyamat helyett. Az adatfolyam egy olyan programozási modellre utal, amelyben számításokat végeznek, ha minden szükséges adat rendelkezésre áll; a vezérlési folyamat olyan programozási modellre utal, amely előre meghatározott sorrendben végez számításokat.

Az adatfolyam-programozási modell az üzenetátadás fogalmához kapcsolódik, ahol a program független összetevői üzenetek küldésével kommunikálnak egymással.

Az Ügynökkódtár három összetevőből áll: aszinkron ügynökökből, aszinkron üzenetblokkokból és üzenetátadási függvényekből. Az ügynökök fenntartják az állapotot, és üzenetblokkok és üzenetátadási függvények használatával kommunikálnak egymással és külső összetevőkkel. Az üzenetátadási függvények lehetővé teszik az ügynökök számára, hogy üzeneteket küldjenek és fogadjanak a külső összetevőkről. Az aszinkron üzenetblokkok üzeneteket tárolnak, és lehetővé teszik az ügynökök számára, hogy szinkronizált módon kommunikáljanak.

Az alábbi ábra bemutatja, hogyan használja két ügynök az üzenetblokkokat és az üzenetátadó függvényeket a kommunikációhoz. Ebben az ábrán agent1 üzenetet küld agent2 részére a concurrency::send függvény és a concurrency::unbounded_buffer objektum használatával. agent2 a concurrency::receive függvény használatával olvassa el az üzenetet. agent2 Ugyanazt a metódust használja az üzenet elküldéséhez agent1. A szaggatott nyilak az ügynökök közötti adatáramlást jelölik. A folytonos nyilak összekapcsolják az ügynököket azokkal az üzenetblokkokkal, amelyekbe írnak, vagy amelyekből olvasnak.

Az Ügynökkódtár összetevői.

Az ábrát megvalósító kód példája a jelen témakör későbbi részében jelenik meg.

Az ügynök programozási modell számos előnnyel rendelkezik más egyidejűségi és szinkronizálási mechanizmusokkal, például az eseményekkel szemben. Az egyik előnye, hogy az állapotváltozások objektumok közötti továbbítására szolgáló üzenetátadással elkülönítheti a megosztott erőforrásokhoz való hozzáférést, és ezáltal javíthatja a méretezhetőséget. Az üzenetátadás előnye, hogy nem külső szinkronizálási objektumhoz, hanem adatszinkronizáláshoz kapcsolódik. Ez leegyszerűsíti az összetevők közötti adatátvitelt, és kiküszöbölheti az alkalmazások programozási hibáit.

Mikor érdemes használni az ügynökkódtárat?

Az Ügynökök kódtárat akkor használja, ha több olyan művelettel rendelkezik, amelyeknek aszinkron módon kell kommunikálniuk egymással. Az üzenetblokkok és az üzenetátadási függvények lehetővé teszik párhuzamos alkalmazások írását szinkronizálási mechanizmusok, például zárolások nélkül. Így az alkalmazáslogikára összpontosíthat.

Az ügynök programozási modelljét gyakran használják adatfolyamok vagy hálózatok létrehozásához. Az adatfolyamok összetevők sorozata, amelyek mindegyike egy adott feladatot hajt végre, amely hozzájárul egy nagyobb cél eléréséhez. Az adatfolyam-folyamat minden összetevője működik, amikor üzenetet kap egy másik összetevőtől. A munka eredménye a folyamat vagy a hálózat más összetevőinek lesz átadva. Az összetevők részletesebb egyidejűségi funkciókat használhatnak más kódtárakból, például a párhuzamos minták kódtárából (PPL).

példa

Az alábbi példa a jelen témakörben korábban bemutatott ábrát valósítja meg.

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

Ez a példa a következő kimenetet hozza létre:

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

Az alábbi témakörök az ebben a példában használt funkciókat ismertetik.

Aszinkron ügynökök
Az aszinkron ügynökök szerepét ismerteti a nagyobb számítási feladatok megoldásában.

Aszinkron üzenetblokkok
Az Ügynökök tára által biztosított különböző üzenetblokk-típusokat ismerteti.

Üzenetátadási függvények
Az ügynökkódtár által biztosított különböző üzenetátadási rutinokat ismerteti.

Útmutató: Különböző Producer-Consumer minták implementálása
Ismerteti, hogyan implementálhatja a gyártó-fogyasztó mintát az alkalmazásban.

Útmutató: Munkahelyi függvények biztosítása a hívási és transzformátorosztályok számára
Számos módját szemlélteti a munkafüggvények biztosításának a concurrency::call és concurrency::transformer osztályok számára.

Útmutató: Transzformátor használata adatfolyamban
Bemutatja, hogyan használható a párhuzamosság::transformer osztály az adatfolyamban.

Útmutató: Kiválasztás a befejezett tevékenységek között
Bemutatja, hogyan használható az concurrency::choice és concurrency::join osztály a keresési algoritmus befejezéséhez szükséges első feladat kiválasztásához.

Útmutató: Üzenet küldése rendszeres időközönként
A következő példa megmutatja, hogyan lehet a concurrency::timer osztályt használni arra, hogy rendszeres időközönként üzenetet küldjön.

Útmutató: Üzenetblokkszűrő használata
Bemutatja, hogyan használható szűrő az aszinkron üzenetblokkok elfogadására vagy elutasítására.

Párhuzamos minták kódtára (PPL)
Ismerteti, hogyan használhat különböző párhuzamos mintákat, például párhuzamos algoritmusokat az alkalmazásokban.

Párhuzamossági futtatókörnyezet
Az egyidejűségi futtatókörnyezetet ismerteti, amely leegyszerűsíti a párhuzamos programozást, és kapcsolódó témakörökre mutató hivatkozásokat tartalmaz.