非同步代理程式程式庫
非同步代理程式程式庫 (或簡稱為「代理程式程式庫」(Agents Library)) 所提供的程式設計模型,可讓您具有並行功能的應用程式開發更為健全。 代理程式程式庫是 C++ 範本程式庫,可提升以動作項目為基礎的程式設計模型,以及針對粗略資料流程和管線工作所傳遞的同處理序訊息。 代理程式程式庫建置於並行執行階段的排程及資源管理元件上。
程式設計模型
代理程式程式庫可讓您透過以資料流程 (而非控制流程) 為基礎的非同步通訊模型連接隔離的元件,以共用狀態以外的形式作業。 「資料流程」(Dataflow) 是指會在所有必要資料皆可用的情況下執行計算的程式設計模型;「控制流程」(Control Flow) 則是指以預先決定的順序執行計算的程式設計模型。
資料流程程式設計模型與「訊息傳遞」(Message Passing) 的概念有關;在此模型中,程式的獨立元件可藉由訊息傳送相互通訊。
代理程式程式庫由三項元件所組成:「非同步代理程式」(Asynchronous Agent)、「非同步訊息區」(Asynchronous Message Block) 和「訊息傳遞函式」(Message-passing Function)。 代理程式可維護狀態,並使用訊息區和訊息傳遞函式相互通訊以及與外部元件通訊。 訊息傳遞函式可讓代理程式傳送和接收進出於外部元件的訊息。 非同步訊息區可保存郵件,並可讓代理程式以同步方式進行通訊。
下圖說明兩個代理程式如何使用訊息區和訊息傳遞函式進行通訊。 在此圖例中,agent1 使用 Concurrency::send 函式和 Concurrency::unbounded_buffer 物件將訊息傳送至 agent2。 agent2 使用 Concurrency::receive 函式讀取訊息。 agent2 使用相同的方法將訊息傳送至 agent1。 虛線箭號表示代理程式之間的資料流程。 實心箭號會將代理程式連接至它們所寫入或讀取的訊息區。
本主題稍後將顯示實作此圖例的程式碼範例。
與其他並行和同步處理機制 (例如事件) 相較,代理程式的程式設計模型有幾項優點。 其中一個優點是,使用訊息傳遞藉以傳輸物件之間的狀態變更,可讓您隔離共用資源的存取,進而提升延展性。 訊息傳遞的好處在於,它會將同步處理繫結到資料,而不是繫結到外部同步處理物件。 這簡化了元件之間的資料傳輸,並且可以消除您應用程式中的程式設計錯誤。
使用代理程式程式庫的時機
當您有多個必須以非同步方式相互通訊的作業時,請使用代理程式程式庫。 訊息區和訊息傳遞函式可讓您直接撰寫平行應用程式,而無須使用同步處理機制 (例如鎖定)。 這可以讓您專注於應用程式邏輯上。
代理程式的程式設計模型通常用來建立「資料管線」(Data Pipeline) 或「網路」(Network)。 資料管線是一系列的元件,各個元件分別執行一項特定工作,進而完成較大的目標。 資料流程管線中的每項元件接收到來自其他元件的訊息時,就會開始執行工作。 該工作的結果會傳遞至管線或網路中的其他元件。 這些元件可以使用其他程式庫中更為精細的並行功能,例如 平行模式程式庫 (PPL)。
範例
下列範例會實作本主題先前所顯示的圖例。
// 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);
}
這個範例會產生下列輸出:
agent1: sending request...
agent2: received 'request'.
agent2: sending response...
agent1: received '42'.
下列主題將說明此範例中所使用的功能。
相關主題
非同步代理程式
說明用以執行較大運算工作的非同步代理程式角色。非同步訊息區
說明代理程式程式庫所提供的各種訊息區類型。訊息傳遞函式
說明代理程式程式庫所提供的各種訊息傳遞常式。HOW TO:實作各種生產者-消費者模式
說明如何在您的應用程式中實作生產者-消費者模式。HOW TO:為呼叫和轉換程式類別提供工作函式
說明許多將工作函式提供給 Concurrency::call 和 Concurrency::transformer 類別的方式。HOW TO:在資料管線中使用轉換程式
說明如何在資料管線中使用 Concurrency::transformer 類別。HOW TO:在已完成的工作之中選取
說明如何使用 Concurrency::choice 和 Concurrency::join 類別,選取第一項要完成搜尋演算法的工作。HOW TO:定期傳送訊息
說明如何使用 Concurrency::timer 類別來定期傳送訊息。HOW TO:使用訊息區篩選條件
示範如何使用篩選條件,讓非同步訊息區塊接受或拒絕訊息。平行模式程式庫 (PPL)
說明如何在您的應用程式中使用各種平行模式,例如平行演算法。並行執行階段
描述「並行執行階段」,它可以簡化平行程式設計工作,而且包含相關主題的連結。