Pustaka Agen Asinkron

Pustaka Agen Asinkron (atau hanya Pustaka Agen) menyediakan model pemrograman yang memungkinkan Anda meningkatkan ketahanan pengembangan aplikasi yang mendukung konkurensi. Pustaka Agen adalah pustaka templat C++ yang mempromosikan model pemrograman berbasis aktor dan pesan dalam proses yang diteruskan untuk aliran data dan tugas alur yang kasar. Pustaka Agen dibangun berdasarkan komponen penjadwalan dan manajemen sumber daya dari Runtime Konkurensi.

Model Pemrograman

Pustaka Agen menyediakan alternatif untuk status bersama dengan memungkinkan Anda menyambungkan komponen terisolasi melalui model komunikasi asinkron yang didasarkan pada aliran data alih-alih alur kontrol. Aliran data mengacu pada model pemrograman tempat komputasi dibuat ketika semua data yang diperlukan tersedia; alur kontrol mengacu pada model pemrograman di mana komputasi dibuat dalam urutan yang telah ditentukan.

Model pemrograman aliran data terkait dengan konsep penerusan pesan, di mana komponen independen program berkomunikasi satu sama lain dengan mengirim pesan.

Pustaka Agen terdiri dari tiga komponen: agen asinkron, blok pesan asinkron, dan fungsi pengiriman pesan. Agen mempertahankan status, dan menggunakan blok pesan dan fungsi pengiriman pesan untuk berkomunikasi satu dengan yang lain dan dengan komponen eksternal. Fungsi pengiriman pesan memungkinkan agen mengirim dan menerima pesan ke dan dari komponen eksternal. Blok pesan asinkron menyimpan pesan dan memungkinkan agen berkomunikasi dengan cara yang disinkronkan.

Ilustrasi berikut menunjukkan bagaimana dua agen menggunakan blok pesan dan fungsi pengiriman pesan untuk berkomunikasi. Dalam ilustrasi ini, agent1 mengirim pesan ke agent2 dengan menggunakan fungsi konkurensi::send dan konkurensi::unbounded_buffer objek. agent2menggunakan fungsi konkurensi::receive untuk membaca pesan. agent2 menggunakan metode yang sama untuk mengirim pesan ke agent1. Panah putus-putus mewakili aliran data antar agen. Panah solid menyambungkan agen ke blok pesan tempat mereka menulis atau membaca.

The components of the Agents Library.

Contoh kode yang mengimplementasikan ilustrasi ini ditampilkan nanti dalam topik ini.

Model pemrograman agen memiliki beberapa keunggulan dibandingkan mekanisme konkurensi dan sinkronisasi lainnya, misalnya, peristiwa. Salah satu keuntungannya adalah dengan menggunakan pesan yang diteruskan untuk mengirimkan perubahan status antar objek, Anda dapat mengisolasi akses ke sumber daya bersama, dan dengan demikian meningkatkan skalabilitas. Keuntungan untuk meneruskan pesan adalah bahwa ia mengikat sinkronisasi ke data alih-alih mengikatnya ke objek sinkronisasi eksternal. Ini menyederhanakan transmisi data di antara komponen dan dapat menghilangkan kesalahan pemrograman dalam aplikasi Anda.

Kapan Menggunakan Pustaka Agen

Gunakan pustaka Agen saat Anda memiliki beberapa operasi yang harus berkomunikasi satu sama lain secara asinkron. Blok pesan dan fungsi pengiriman pesan memungkinkan Anda menulis aplikasi paralel tanpa memerlukan mekanisme sinkronisasi seperti kunci. Ini memungkinkan Anda fokus pada logika aplikasi.

Model pemrograman agen sering digunakan untuk membuat alur data atau jaringan. Alur data adalah serangkaian komponen, yang masing-masing melakukan tugas tertentu yang berkontribusi pada tujuan yang lebih besar. Setiap komponen dalam alur aliran data melakukan pekerjaan saat menerima pesan dari komponen lain. Hasil pekerjaan tersebut diteruskan ke komponen lain dalam alur atau jaringan. Komponen dapat menggunakan fungsionalitas konkurensi yang lebih halus dari pustaka lain, misalnya, Pustaka Pola Paralel (PPL).

Contoh

Contoh berikut mengimplementasikan ilustrasi yang ditunjukkan sebelumnya dalam topik ini.

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

Contoh ini menghasilkan output berikut:

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

Topik berikut menjelaskan fungsionalitas yang digunakan dalam contoh ini.

Agen Asinkron
Menjelaskan peran agen asinkron dalam memecahkan tugas komputasi yang lebih besar.

Blok Pesan Asinkron
Menjelaskan berbagai jenis blok pesan yang disediakan oleh Pustaka Agen.

Fungsi Passing Pesan
Menjelaskan berbagai rutinitas passing pesan yang disediakan oleh Pustaka Agen.

Cara: Menerapkan Berbagai Pola Produsen-Konsumen
Menjelaskan cara menerapkan pola produsen-konsumen dalam aplikasi Anda.

Cara: Menyediakan Fungsi Kerja ke Kelas panggilan dan transformator
Mengilustrasikan beberapa cara untuk menyediakan fungsi kerja ke kelas konkurensi::panggilan dan konkurensi::transformer .

Cara: Menggunakan transformator dalam Alur Data
Memperlihatkan cara menggunakan kelas konkurensi::transformer dalam alur data.

Cara: Pilih Di Antara Tugas yang Selesai
Memperlihatkan cara menggunakan konkurensi::choice dan konkurensi::join classes untuk memilih tugas pertama untuk menyelesaikan algoritma pencarian.

Cara: Mengirim Pesan pada Interval Reguler
Menunjukkan cara menggunakan kelas konkurensi::timer untuk mengirim pesan secara berkala.

Cara: Menggunakan Filter Blok Pesan
Menunjukkan cara menggunakan filter untuk mengaktifkan blok pesan asinkron untuk menerima atau menolak pesan.

Parallel Patterns Library (PPL)
Menjelaskan cara menggunakan berbagai pola paralel, seperti algoritma paralel, dalam aplikasi Anda.

Runtime Konkurensi
Menjelaskan Runtime Konkurensi, yang menyederhanakan pemrograman paralel, dan berisi tautan ke topik terkait.