Aracılığıyla paylaş


Zaman Uyumsuz İleti Blokları

Aracılar Kitaplığı, iletileri uygulama bileşenleri arasında iş parçacığı güvenli bir şekilde yaymanızı sağlayan birkaç ileti bloğu türü sağlar. Bu ileti bloğu türleri genellikle eşzamanlılık::send, eşzamanlılık::asend, eşzamanlılık::alma ve eşzamanlılık::try_receive gibi çeşitli ileti geçirme yordamlarıyla birlikte kullanılır. Aracılar Kitaplığı tarafından tanımlanan ileti geçirme yordamları hakkında daha fazla bilgi için bkz . İleti Geçirme İşlevleri.

Bölümler

Bu konu, aşağıdaki bölümleri içerir:

Kaynaklar ve Hedefler

Kaynaklar ve hedefler, ileti geçirmede iki önemli katılımcıdır. Kaynak, ileti gönderen bir iletişim uç noktasına başvurur. Hedef, iletileri alan bir iletişim uç noktasına başvurur. Bir kaynağı, okuduğunuz bir uç nokta ve hedefi de yazdığınız bir uç nokta olarak düşünebilirsiniz. Uygulamalar, mesajlaşma ağları oluşturmak için kaynakları ve hedefleri birbirine bağlar.

Aracılar Kitaplığı, kaynakları ve hedefleri göstermek için iki soyut sınıf kullanır: eşzamanlılık::ISource ve eşzamanlılık::ITarget. Kaynak olarak davranan ileti bloğu türleri ; ISourcehedef olarak davranan ileti bloğu türleri adresinden ITargettüretilir. Kaynak ve hedef olarak davranan ileti bloğu türleri hem hem ITargetde ISource 'den türetilir.

[Üst]

İleti Yayma

İleti yayma , bir bileşenden diğerine ileti gönderme işlemidir. İleti bloğuna ileti sunulduğunda, bu iletiyi kabul edebilir, reddedebilir veya erteleyebilir. Her ileti bloğu türü iletileri farklı şekillerde depolar ve iletir. Örneğin, unbounded_buffer sınıfı sınırsız sayıda ileti depolar, overwrite_buffer sınıf bir kerede tek bir ileti depolar ve transformer sınıfı her iletinin değiştirilmiş bir sürümünü depolar. Bu ileti bloğu türleri, bu belgenin ilerleyen bölümlerinde daha ayrıntılı olarak açıklanmıştır.

İleti bloğu bir iletiyi kabul ettiğinde isteğe bağlı olarak iş gerçekleştirebilir ve ileti bloğu bir kaynaksa, sonuçta elde edilen iletiyi ağın başka bir üyesine geçirebilir. İleti bloğu, almak istemediği iletileri reddetmek için bir filtre işlevi kullanabilir. Filtreler, bu konunun devamında İleti Filtreleme bölümünde daha ayrıntılı olarak açıklanmıştır. Bir iletiyi erteleyen bir ileti bloğu, bu iletiyi ayırabilir ve daha sonra kullanabilir. İleti ayırma, bu konunun devamında İleti Ayırma bölümünde daha ayrıntılı olarak açıklanmıştır.

Aracılar Kitaplığı, ileti bloklarının iletileri zaman uyumsuz veya zaman uyumlu bir şekilde geçirmesini sağlar. örneğin işlevini kullanarak send bir ileti bloğuna zaman uyumlu bir şekilde ileti geçirdiğinizde, hedef blok iletiyi kabul edene veya reddedene kadar çalışma zamanı geçerli bağlamı engeller. bir ileti bloğuna bir iletiyi zaman uyumsuz olarak geçirdiğinizde, örneğin işlevini kullanarak asend çalışma zamanı iletiyi hedefe sunar ve hedef iletiyi kabul ederse, çalışma zamanı iletiyi alıcıya yayarak zaman uyumsuz bir görev zamanlar. Çalışma zamanı, iletileri işbirliğine dayalı bir şekilde yaymak için basit görevler kullanır. Basit görevler hakkında daha fazla bilgi için bkz . Görev Zamanlayıcı.

Uygulamalar, mesajlaşma ağları oluşturmak için kaynakları ve hedefleri birbirine bağlar. Genellikle, ağı bağlar ve ağa veri geçirmek için veya asend çağrısında send bulunursunuz. Kaynak ileti bloğunu hedefe bağlamak için eşzamanlılık::ISource::link_target yöntemini çağırın. Kaynak bloğun hedefle bağlantısını kesmek için eşzamanlılık::ISource::unlink_target yöntemini çağırın. Kaynak bloğun tüm hedeflerinin bağlantısını kesmek için eşzamanlılık::ISource::unlink_targets yöntemini çağırın. Önceden tanımlanmış ileti bloğu türlerinden biri kapsam dışına çıktığında veya yok edildiğinde, otomatik olarak tüm hedef bloklarla bağlantısını keser. Bazı ileti bloğu türleri, yazabilecekleri hedef sayısı üst sınırını kısıtlar. Aşağıdaki bölümde, önceden tanımlanmış ileti bloğu türleri için geçerli olan kısıtlamalar açıklanmaktadır.

[Üst]

İleti Bloğu Türlerine Genel Bakış

Aşağıdaki tabloda önemli ileti bloğu türlerinin rolü kısaca açıklanmaktadır.

Unbounded_buffer
bir ileti kuyruğu depolar.

overwrite_buffer
Birden çok kez yazılabilen ve okunabilen bir ileti depolar.

Single_assignment
Bir kereye yazılabilen ve birden çok kez okunabilen bir ileti depolar.

Çağrı
bir ileti aldığında çalışma gerçekleştirir.

Trafo
Veri aldığında ve bu çalışmanın sonucunu başka bir hedef bloğuna gönderdiğinde çalışma gerçekleştirir. transformer sınıfı farklı giriş ve çıkış türleri üzerinde işlem yapabilir.

Seçim
Bir kaynak kümesinden kullanılabilir ilk iletiyi seçer.

join ve multitype join
Bir kaynak kümesinden tüm iletilerin alınmasını bekleyin ve ardından iletileri başka bir ileti bloğu için bir iletide birleştirin.

Zamanlayıcı
Düzenli aralıklarla hedef bloğa ileti gönderir.

Bu ileti bloğu türleri, farklı durumlarda yararlı olmalarını sağlayan farklı özelliklere sahiptir. Bazı özellikler şunlardır:

  • Yayma türü: İleti bloğunun veri kaynağı, veri alıcısı veya her ikisi gibi davranıp davranmadığı.

  • İleti sıralama: İleti bloğunun iletilerin gönderildiği veya alındığı özgün sırayı koruyup korumadığı. Önceden tanımlanmış her ileti bloğu türü, iletileri gönderdiği veya aldığı özgün sırayı korur.

  • Kaynak sayısı: İleti bloğunun okuyabileceği kaynak sayısı üst sınırı.

  • Hedef sayısı: İleti bloğunun yazabileceği hedef sayısı üst sınırı.

Aşağıdaki tabloda bu özelliklerin çeşitli ileti bloğu türleriyle ilişkisi gösterilmektedir.

İleti bloğu türü Yayma türü (Kaynak, Hedef veya Her İkisi) İleti sıralama (Sıralı veya Sıralanmamış) Kaynak sayısı Hedef sayısı
unbounded_buffer Her İkisi Sipariş edilen Sınırsız Sınırsız
overwrite_buffer Her İkisi Sipariş edilen Sınırsız Sınırsız
single_assignment Her İkisi Sipariş edilen Sınırsız Sınırsız
call Hedef Sipariş edilen Sınırsız Geçerli değil
transformer Her İkisi Sipariş edilen Sınırsız Kategori 1
choice Her İkisi Sipariş edilen 10 Kategori 1
join Her İkisi Sipariş edilen Sınırsız Kategori 1
multitype_join Her İkisi Sipariş edilen 10 Kategori 1
timer Source Geçerli değil Geçerli değil Kategori 1

Aşağıdaki bölümlerde ileti bloğu türleri daha ayrıntılı olarak açıklanmaktadır.

[Üst]

unbounded_buffer Sınıfı

concurrency::unbounded_buffer sınıfı genel amaçlı zaman uyumsuz bir mesajlaşma yapısını temsil eder. Bu sınıf, iletilerin birden çok kaynak tarafından yazılabilen veya birden çok hedef tarafından okunabilen bir ilk giren ilk çıkar (FIFO) sırasını tutar. Hedef bir nesneden unbounded_buffer ileti aldığında, bu ileti ileti kuyruğundan kaldırılır. Bu nedenle, bir unbounded_buffer nesnenin birden çok hedefi olsa da, her iletiyi yalnızca bir hedef alır. unbounded_buffer sınıfı, başka bir bileşene birden çok ileti geçirmek istediğinizde ve bu bileşenin her iletiyi alması gerektiğinde kullanışlıdır.

Örnek

Aşağıdaki örnekte, sınıfıyla çalışmanın temel yapısı gösterilmektedir unbounded_buffer . Bu örnek bir unbounded_buffer nesneye üç değer gönderir ve sonra bu değerleri aynı nesneden geri okur.

// unbounded_buffer-structure.cpp
// compile with: /EHsc
#include <agents.h>
#include <iostream>

using namespace concurrency;
using namespace std;

int wmain()
{
   // Create an unbounded_buffer object that works with
   // int data.
   unbounded_buffer<int> items;

   // Send a few items to the unbounded_buffer object.
   send(items, 33);
   send(items, 44);
   send(items, 55);

   // Read the items from the unbounded_buffer object and print
   // them to the console.
   wcout << receive(items) << endl;
   wcout << receive(items) << endl;
   wcout << receive(items) << endl;
}

Bu örnek aşağıdaki çıkışı oluşturur:

334455

Sınıfının nasıl kullanılacağını unbounded_buffer gösteren eksiksiz bir örnek için bkz . Nasıl yapılır: Çeşitli Üretici-Tüketici Desenlerini Uygulama.

[Üst]

overwrite_buffer Sınıfı

concurrency::overwrite_buffer sınıfı, bir nesnenin yalnızca bir overwrite_buffer ileti depolaması dışında sınıfına unbounded_buffer benzer. Ayrıca, hedef bir nesneden overwrite_buffer bir ileti aldığında, bu ileti arabellekten kaldırılmaz. Bu nedenle, birden çok hedef iletinin bir kopyasını alır.

Sınıfı overwrite_buffer , birden çok iletiyi başka bir bileşene geçirmek istediğinizde yararlıdır, ancak bu bileşen yalnızca en son değere ihtiyaç duyar. Bu sınıf, bir iletiyi birden çok bileşene yayınlamak istediğinizde de kullanışlıdır.

Örnek

Aşağıdaki örnekte, sınıfıyla çalışmanın temel yapısı gösterilmektedir overwrite_buffer . Bu örnek bir overwrite _buffer nesneye üç değer gönderir ve ardından aynı nesneden geçerli değeri üç kez okur. Bu örnek, sınıfın örneğine unbounded_buffer benzer. Ancak, overwrite_buffer sınıfı yalnızca bir ileti depolar. Ayrıca, çalışma zamanı okunduktan sonra bir overwrite_buffer nesneden iletiyi kaldırmaz.

// overwrite_buffer-structure.cpp
// compile with: /EHsc
#include <agents.h>
#include <iostream>

using namespace concurrency;
using namespace std;

int wmain()
{
   // Create an overwrite_buffer object that works with
   // int data.
   overwrite_buffer<int> item;

   // Send a few items to the overwrite_buffer object.
   send(item, 33);
   send(item, 44);
   send(item, 55);

   // Read the current item from the overwrite_buffer object and print
   // it to the console three times.
   wcout << receive(item) << endl;
   wcout << receive(item) << endl;
   wcout << receive(item) << endl;
}

Bu örnek aşağıdaki çıkışı oluşturur:

555555

Sınıfının nasıl kullanılacağını overwrite_buffer gösteren eksiksiz bir örnek için bkz . Nasıl yapılır: Çeşitli Üretici-Tüketici Desenlerini Uygulama.

[Üst]

single_assignment Sınıfı

concurrency::single_assignment sınıfı sınıfa overwrite_buffer benzer, ancak bir nesne yalnızca bir single_assignment kez yazılabilir. overwrite_buffer sınıfı gibi, hedef de bir single_assignment nesnesinden ileti aldığında, o ileti nesneden kaldırılmaz. Bu nedenle, birden çok hedef iletinin bir kopyasını alır. Sınıfı single_assignment , bir iletiyi birden çok bileşene yayınlamak istediğinizde kullanışlıdır.

Örnek

Aşağıdaki örnekte, sınıfıyla çalışmanın temel yapısı gösterilmektedir single_assignment . Bu örnek bir single_assignment nesneye üç değer gönderir ve ardından aynı nesneden geçerli değeri üç kez okur. Bu örnek, sınıfın örneğine overwrite_buffer benzer. Hem hem de overwrite_buffersingle_assignment sınıfları tek bir ileti depolasa da, single_assignment sınıf yalnızca bir kez yazılabilir.

// single_assignment-structure.cpp
// compile with: /EHsc
#include <agents.h>
#include <iostream>

using namespace concurrency;
using namespace std;

int wmain()
{
   // Create an single_assignment object that works with
   // int data.
   single_assignment<int> item;

   // Send a few items to the single_assignment object.
   send(item, 33);
   send(item, 44);
   send(item, 55);

   // Read the current item from the single_assignment object and print
   // it to the console three times.
   wcout << receive(item) << endl;
   wcout << receive(item) << endl;
   wcout << receive(item) << endl;
}

Bu örnek aşağıdaki çıkışı oluşturur:

333333

sınıfının nasıl kullanılacağını single_assignment gösteren eksiksiz bir örnek için bkz . İzlenecek Yol: Vadeli İşlemleri Uygulama.

[Üst]

çağrı Sınıfı

concurrency::call sınıfı, veri aldığında bir iş işlevi gerçekleştiren bir ileti alıcısı gibi davranır. Bu iş işlevi bir lambda ifadesi, işlev nesnesi veya işlev işaretçisi olabilir. Nesne call , sıradan bir işlev çağrısından farklı davranır çünkü ona ileti gönderen diğer bileşenlere paralel hareket eder. Bir call nesne bir ileti aldığında iş gerçekleştiriyorsa, bu iletiyi kuyruğa ekler. Her call nesne, kuyruğa alınan iletileri alındıkları sırayla işler.

Örnek

Aşağıdaki örnekte, sınıfıyla çalışmanın temel yapısı gösterilmektedir call . Bu örnek, aldığı her değeri konsola yazdıran bir call nesne oluşturur. Örnek daha sonra nesneye call üç değer gönderir. call Nesnesi iletileri ayrı bir iş parçacığında işlediğinden, bu örnekte nesnenin işlev döndürülmeden önce wmain tüm iletileri işlediğinden call emin olmak için bir sayaç değişkeni ve olay nesnesi de kullanılır.

// call-structure.cpp
// compile with: /EHsc
#include <agents.h>
#include <iostream>

using namespace concurrency;
using namespace std;

int wmain()
{
   // An event that is set when the call object receives all values.
   event received_all;

   // Counts the 
   long receive_count = 0L;
   long max_receive_count = 3L;

   // Create an call object that works with int data.
   call<int> target([&received_all,&receive_count,max_receive_count](int n) {
      // Print the value that the call object receives to the console.
      wcout << n << endl;
      
      // Set the event when all messages have been processed.
      if (++receive_count == max_receive_count)
         received_all.set();
   });

   // Send a few items to the call object.
   send(target, 33);
   send(target, 44);
   send(target, 55);

   // Wait for the call object to process all items.
   received_all.wait();
}

Bu örnek aşağıdaki çıkışı oluşturur:

334455

Sınıfın nasıl kullanılacağını call gösteren eksiksiz bir örnek için bkz . Nasıl yapılır: Çağrıya ve transformatör Sınıflarına İş İşlevleri Sağlama.

[Üst]

dönüştürücü Sınıfı

concurrency::transformer sınıfı hem ileti alıcısı hem de ileti gönderen olarak çalışır. sınıfa transformer benzer call çünkü veri aldığında kullanıcı tanımlı bir iş işlevi gerçekleştirir. Ancak sınıfı, transformer iş işlevinin sonucunu alıcı nesnelere de gönderir. Nesne call gibi, nesne transformer de ona ileti gönderen diğer bileşenlere paralel olarak hareket eder. Bir transformer nesne bir ileti aldığında iş gerçekleştiriyorsa, bu iletiyi kuyruğa ekler. Her transformer nesne, kuyruğa alınan iletilerini alındıkları sırayla işler.

sınıfı iletisini transformer tek bir hedefe gönderir. Oluşturucudaki parametresini _PTarget olarak NULLayarlarsanız, daha sonra concurrency::link_target yöntemini çağırarak hedefi belirtebilirsiniz.

Aracılar Kitaplığı tarafından sağlanan diğer tüm zaman uyumsuz ileti bloğu türlerinden farklı olarak, transformer sınıf farklı giriş ve çıkış türleri üzerinde işlem yapabilir. Bu türdeki verileri başka bir türe dönüştürme özelliği, sınıfı birçok eşzamanlı ağda önemli bir bileşen haline getirir transformer . Buna ek olarak, bir transformer nesnenin iş işlevine daha ayrıntılı paralel işlevsellik ekleyebilirsiniz.

Örnek

Aşağıdaki örnekte, sınıfıyla çalışmanın temel yapısı gösterilmektedir transformer . Bu örnek, çıkış olarak bir transformer değer üretmek için her giriş int değerini 0,33'e katlayan bir double nesne oluşturur. Örnek daha sonra dönüştürülen değerleri aynı transformer nesneden alır ve konsola yazdırır.

// transformer-structure.cpp
// compile with: /EHsc
#include <agents.h>
#include <iostream>

using namespace concurrency;
using namespace std;

int wmain()
{
   // Create an transformer object that receives int data and 
   // sends double data.
   transformer<int, double> third([](int n) {
      // Return one-third of the input value.
      return n * 0.33;
   });

   // Send a few items to the transformer object.
   send(third, 33);
   send(third, 44);
   send(third, 55);

   // Read the processed items from the transformer object and print
   // them to the console.
   wcout << receive(third) << endl;
   wcout << receive(third) << endl;
   wcout << receive(third) << endl;
}

Bu örnek aşağıdaki çıkışı oluşturur:

10.8914.5218.15

Sınıfının nasıl kullanılacağını transformer gösteren eksiksiz bir örnek için bkz . Nasıl yapılır: Veri İşlem Hattında transformatör kullanma.

[Üst]

seçenek Sınıfı

concurrency::choice sınıfı, bir kaynak kümesinden kullanılabilir ilk iletiyi seçer. choice sınıfı, veri akışı mekanizması yerine bir denetim akışı mekanizmasını temsil eder (Zaman Uyumsuz Aracılar Kitaplığı konusu, veri akışı ile denetim akışı arasındaki farkları açıklar).

Bir seçim nesnesinden okumak, parametresi olarak ayarlandığında Windows API işlevini WaitForMultipleObjects çağırmaya bWaitAllFALSEbenzer. Ancak, choice sınıfı verileri bir dış eşitleme nesnesi yerine olayın kendisine bağlar.

Genellikle, uygulamanızda control-flow'ı yönlendirmek için concurrency::receive işleviyle birlikte sınıfını kullanırsınızchoice. Farklı türlerde choice ileti arabellekleri arasından seçim yapmak zorunda olduğunuzda sınıfını kullanın. Aynı türe single_assignment sahip ileti arabellekleri arasından seçim yapmak zorunda olduğunuzda sınıfını kullanın.

Hangi iletinin seçildiğini belirleyebildiğinden, kaynakları bir choice nesneye bağlama sırası önemlidir. Örneğin, zaten bir ileti içeren birden çok ileti arabelleğini bir choice nesneye bağladığınız durumu göz önünde bulundurun. Nesnesi, choice bağlı olduğu ilk kaynaktan iletiyi seçer. Tüm kaynakları bağladıktan sonra nesne, choice her kaynağın ileti alma sırasını korur.

Örnek

Aşağıdaki örnekte, sınıfıyla çalışmanın temel yapısı gösterilmektedir choice . Bu örnekte eşzamanlılık::make_choice işlevi, üç ileti bloğu arasından seçim yapılan bir choice nesne oluşturmak için kullanılır. Örnek daha sonra çeşitli Fibonacci numaralarını hesaplar ve her sonucu farklı bir ileti bloğunda depolar. Örnek daha sonra konsola ilk tamamlanan işlemi temel alan bir ileti yazdırır.

// choice-structure.cpp
// compile with: /EHsc
#include <agents.h>
#include <ppl.h>
#include <iostream>

using namespace concurrency;
using namespace std;

// Computes the nth Fibonacci number.
// This function illustrates a lengthy operation and is therefore
// not optimized for performance.
int fibonacci(int n)
{
   if (n < 2)
      return n;
   return fibonacci(n-1) + fibonacci(n-2);
}

int wmain()
{
   // Although the following thee message blocks are written to one time only, 
   // this example illustrates the fact that the choice class works with 
   // different message block types.

   // Holds the 35th Fibonacci number.
   single_assignment<int> fib35;
   // Holds the 37th Fibonacci number.
   overwrite_buffer<int> fib37;
   // Holds half of the 42nd Fibonacci number.
   unbounded_buffer<double> half_of_fib42;   

   // Create a choice object that selects the first single_assignment 
   // object that receives a value.
   auto select_one = make_choice(&fib35, &fib37, &half_of_fib42);

   // Execute a few lengthy operations in parallel. Each operation sends its 
   // result to one of the single_assignment objects.
   parallel_invoke(
      [&fib35] { send(fib35, fibonacci(35)); },
      [&fib37] { send(fib37, fibonacci(37)); },
      [&half_of_fib42] { send(half_of_fib42, fibonacci(42) * 0.5); }
   );

   // Print a message that is based on the operation that finished first.
   switch (receive(select_one))
   {
   case 0:
      wcout << L"fib35 received its value first. Result = " 
            << receive(fib35) << endl;
      break;
   case 1:
      wcout << L"fib37 received its value first. Result = " 
            << receive(fib37) << endl;
      break;
   case 2:
      wcout << L"half_of_fib42 received its value first. Result = " 
            << receive(half_of_fib42) << endl;
      break;
   default:
      wcout << L"Unexpected." << endl;
      break;
   }
}

Bu örnek aşağıdaki örnek çıkışı oluşturur:

fib35 received its value first. Result = 9227465

35. Fibonacci sayısını hesaplayan görevin önce bitmesi garanti edilmediğinden, bu örneğin çıktısı farklılık gösterebilir.

Bu örnek, Fibonacci sayılarını paralel olarak hesaplamak için concurrency::p arallel_invoke algoritmasını kullanır. hakkında parallel_invokedaha fazla bilgi için bkz. Paralel Algoritmalar.

Sınıfın nasıl kullanılacağını choice gösteren eksiksiz bir örnek için bkz . Nasıl yapılır: Tamamlanan Görevler Arasından Seçim Yapma.

[Üst]

join ve multitype_join Sınıfları

Eşzamanlılık::join ve concurrency::multitype_join sınıfları, bir kaynak kümesinin her üyesinin ileti almasını beklemenize olanak sağlar. sınıfı, join ortak ileti türüne sahip kaynak nesneler üzerinde hareket eder. sınıfı, multitype_join farklı ileti türlerine sahip olabilecek kaynak nesneler üzerinde hareket eder.

Bir join veya multitype_join nesnesinden okumak, parametresi olarak ayarlandığında Windows API işlevini WaitForMultipleObjects çağırmaya bWaitAllTRUEbenzer. Ancak, tıpkı bir choice nesne gibi ve multitype_join nesneler de join verileri dış eşitleme nesnesi yerine olayın kendisine bağlayan bir olay mekanizması kullanır.

Nesneden join okuma bir std::vector nesnesi oluşturur. Nesneden multitype_join okuma bir std::tuple nesnesi oluşturur. Öğeler bu nesnelerde karşılık gelen kaynak arabelleklerinin veya multitype_join nesnesine join bağlandıkları sırada görünür. Kaynak arabellekleri bir join veya multitype_join nesnesine bağladığınız sıra, sonuçta elde vector edilen veya tuple nesnedeki öğelerin sırasıyla ilişkilendirildiğinden, var olan bir kaynak arabelleğin birleştirmeyle bağlantısını kaldırmamanızı öneririz. Bunun yapılması, belirtilmeyen davranışlara neden olabilir.

Doyumsuz Olmayan Birleştirmelere Karşı Doyumsuz

join ve multitype_join sınıfları doyumsuz ve doyumsuz olmayan birleşimler kavramını destekler. Doyumsuz birleştirme, tüm iletiler kullanılabilir olana kadar iletiler kullanılabilir hale geldikçe her kaynaktan bir ileti kabul eder. Doyumsuz olmayan birleştirme, iletileri iki aşamada alır. İlk olarak, doyumsuz olmayan bir birleştirme, her kaynaktan bir ileti sunulana kadar bekler. İkincisi, tüm kaynak iletiler kullanılabilir olduktan sonra doyumsuz olmayan bir birleştirme bu iletilerin her birini ayırmaya çalışır. Her iletiyi ayırabiliyorsa, tüm iletileri tüketir ve hedefine yar. Aksi takdirde, ileti rezervasyonları yayımlar veya iptal eder ve her kaynağın bir ileti almasını tekrar bekler.

Doyumsuz birleşimler, iletileri hemen kabul ettikleri için doyumsuz olmayan birleştirmelerden daha iyi performans gösterir. Ancak, nadir durumlarda, doyumsuz birleşimler kilitlenmelere yol açabilir. Bir veya daha fazla paylaşılan kaynak nesne içeren birden çok birleştirmeniz olduğunda doyumsuz olmayan bir birleşim kullanın.

Örnek

Aşağıdaki örnekte, sınıfıyla çalışmanın temel yapısı gösterilmektedir join . Bu örnek, üç single_assignment nesneden alan bir join nesne oluşturmak için eşzamanlılık::make_join işlevini kullanır. Bu örnek çeşitli Fibonacci sayılarını hesaplar, her sonucu farklı single_assignment bir nesnede depolar ve ardından nesnenin barındırmış olduğu her sonucu konsola join yazdırır. Bu örnek, sınıfın örneğine choice benzer, ancak sınıfın join tüm kaynak ileti bloklarının bir ileti almasını beklemesi dışında.

// join-structure.cpp
// compile with: /EHsc
#include <agents.h>
#include <ppl.h>
#include <iostream>

using namespace concurrency;
using namespace std;

// Computes the nth Fibonacci number.
// This function illustrates a lengthy operation and is therefore
// not optimized for performance.
int fibonacci(int n)
{
   if (n < 2)
      return n;
   return fibonacci(n-1) + fibonacci(n-2);
}

int wmain()
{
   // Holds the 35th Fibonacci number.
   single_assignment<int> fib35;
   // Holds the 37th Fibonacci number.
   single_assignment<int> fib37;
   // Holds half of the 42nd Fibonacci number.
   single_assignment<double> half_of_fib42;   

   // Create a join object that selects the values from each of the
   // single_assignment objects.
   auto join_all = make_join(&fib35, &fib37, &half_of_fib42);

   // Execute a few lengthy operations in parallel. Each operation sends its 
   // result to one of the single_assignment objects.
   parallel_invoke(
      [&fib35] { send(fib35, fibonacci(35)); },
      [&fib37] { send(fib37, fibonacci(37)); },
      [&half_of_fib42] { send(half_of_fib42, fibonacci(42) * 0.5); }
   );

   auto result = receive(join_all);
   wcout << L"fib35 = " << get<0>(result) << endl;
   wcout << L"fib37 = " << get<1>(result) << endl;
   wcout << L"half_of_fib42 = " << get<2>(result) << endl;
}

Bu örnek aşağıdaki çıkışı oluşturur:

fib35 = 9227465fib37 = 24157817half_of_fib42 = 1.33957e+008

Bu örnek, Fibonacci sayılarını paralel olarak hesaplamak için concurrency::p arallel_invoke algoritmasını kullanır. hakkında parallel_invokedaha fazla bilgi için bkz. Paralel Algoritmalar.

Sınıfın nasıl kullanılacağını join gösteren eksiksiz örnekler için bkz . Nasıl yapılır: Tamamlanan Görevler Arasında Seçim Yapma ve İzlenecek Yol: Kilitlenmeyi Önlemek için Birleştirmeyi Kullanma.

[Üst]

süreölçer Sınıfı

concurrency::timer sınıfı bir ileti kaynağı işlevi görür. Bir timer nesne, belirtilen süre dolduktan sonra hedefe bir ileti gönderir. Sınıf timer , ileti göndermeyi geciktirmeniz gerektiğinde veya düzenli aralıklarla ileti göndermek istediğinizde kullanışlıdır.

sınıfı iletisini timer tek bir hedefe gönderir. Oluşturucudaki parametresini _PTarget olarak NULLayarlarsanız, daha sonra eşzamanlılık::ISource::link_target yöntemini çağırarak hedefi belirtebilirsiniz.

Bir timer nesne yineleniyor veya yinelenemiyor olabilir. Yinelenen bir zamanlayıcı oluşturmak için oluşturucuyu _Repeating çağırdığınızda parametresini geçirintrue. Aksi takdirde, yinelenmeyen _Repeating bir süreölçer oluşturmak için parametresini geçirinfalse. Zamanlayıcı yineleniyorsa, her aralık sonrasında hedefine aynı iletiyi gönderir.

Aracılar Kitaplığı, başlatılmamış durumda nesneler oluşturur timer . Zamanlayıcı nesnesini başlatmak için concurrency::timer::start yöntemini çağırın. Bir timer nesneyi durdurmak için nesneyi yok edin veya concurrency::timer::stop yöntemini çağırın. Yinelenen zamanlayıcıyı duraklatmak için concurrency::timer::p ause yöntemini çağırın.

Örnek

Aşağıdaki örnekte, sınıfıyla çalışmanın temel yapısı gösterilmektedir timer . Örnek, uzun bir işlemin ilerleme durumunu raporlamak için ve call nesnelerini kullanırtimer.

// timer-structure.cpp
// compile with: /EHsc
#include <agents.h>
#include <iostream>

using namespace concurrency;
using namespace std;

// Computes the nth Fibonacci number.
// This function illustrates a lengthy operation and is therefore
// not optimized for performance.
int fibonacci(int n)
{
   if (n < 2)
      return n;
   return fibonacci(n-1) + fibonacci(n-2);
}

int wmain()
{
   // Create a call object that prints characters that it receives 
   // to the console.
   call<wchar_t> print_character([](wchar_t c) {
      wcout << c;
   });

   // Create a timer object that sends the period (.) character to 
   // the call object every 100 milliseconds.
   timer<wchar_t> progress_timer(100u, L'.', &print_character, true);

   // Start the timer.
   wcout << L"Computing fib(42)";
   progress_timer.start();

   // Compute the 42nd Fibonacci number.
   int fib42 = fibonacci(42);

   // Stop the timer and print the result.
   progress_timer.stop();
   wcout << endl << L"result is " << fib42 << endl;
}

Bu örnek aşağıdaki örnek çıkışı oluşturur:

Computing fib(42)..................................................result is 267914296

Sınıfın nasıl kullanılacağını timer gösteren eksiksiz bir örnek için bkz . Nasıl yapılır: Düzenli Aralıklarla İleti Gönderme.

[Üst]

İleti Filtreleme

İleti bloğu nesnesi oluşturduğunuzda, ileti bloğunun bir iletiyi kabul edip etmediğini belirleyen bir filtre işlevi sağlayabilirsiniz. Filtre işlevi, ileti bloğunun yalnızca belirli değerleri almasını garanti etmenin kullanışlı bir yoludur.

Aşağıdaki örnekte, yalnızca çift sayıları kabul etmek için filtre işlevi kullanan bir nesnenin nasıl oluşturulacağı unbounded_buffer gösterilmektedir. Nesnesi unbounded_buffer tek sayıları reddeder ve bu nedenle tek sayıları hedef bloklarına yaymıyor.

// filter-function.cpp
// compile with: /EHsc
#include <agents.h>
#include <iostream>

using namespace concurrency;
using namespace std;

int wmain()
{
   // Create an unbounded_buffer object that uses a filter
   // function to accept only even numbers.
   unbounded_buffer<int> accept_evens(
      [](int n) {
         return (n%2) == 0;
      });

   // Send a few values to the unbounded_buffer object.
   unsigned int accept_count = 0;
   for (int i = 0; i < 10; ++i)
   {
      // The asend function returns true only if the target
      // accepts the message. This enables us to determine
      // how many elements are stored in the unbounded_buffer
      // object.
      if (asend(accept_evens, i))
      {
         ++accept_count;
      }
   }

   // Print to the console each value that is stored in the 
   // unbounded_buffer object. The unbounded_buffer object should
   // contain only even numbers.
   while (accept_count > 0)
   {
      wcout << receive(accept_evens) << L' ';
      --accept_count;
   }
}

Bu örnek aşağıdaki çıkışı oluşturur:

0 2 4 6 8

Filtre işlevi bir lambda işlevi, işlev işaretçisi veya işlev nesnesi olabilir. Her filtre işlevi aşağıdaki formlardan birini alır.

bool (T)
bool (T const &)

Gereksiz veri kopyalamayı ortadan kaldırmak için, değere göre yayılan bir toplama türünüz olduğunda ikinci formu kullanın.

İleti filtreleme, bileşenlerin veri aldığında hesaplamalar gerçekleştirdiği veri akışı programlama modelini destekler. İletiden geçen ağdaki veri akışını denetlemek için filtre işlevlerini kullanan örnekler için bkz . Nasıl yapılır: İleti Bloğu Filtresi Kullanma, İzlenecek Yol: Veri Akışı Aracısı Oluşturma ve İzlenecek Yol: Görüntü İşleme Ağı Oluşturma.

[Üst]

İleti Rezervasyonu

İleti ayırma , ileti bloğunun bir iletiyi daha sonra kullanmak üzere ayırmasını sağlar. Genellikle ileti ayırma doğrudan kullanılmaz. Ancak, ileti ayırmayı anlamak, önceden tanımlanmış ileti bloğu türlerinden bazılarının davranışını daha iyi anlamanıza yardımcı olabilir.

Doyumsuz olmayan ve açgözlü birleşimleri göz önünde bulundurun. Bunların her ikisi de iletileri daha sonra kullanmak üzere ayırmak için ileti ayırmayı kullanır. Daha önce açıklanan bir doyumsuz olmayan birleştirme, iletileri iki aşamada alır. İlk aşamada doyumsuz join olmayan bir nesne, kaynaklarının her birinin ileti almasını bekler. Doyumsuz olmayan bir birleştirme daha sonra bu iletilerin her birini ayırmaya çalışır. Her iletiyi ayırabiliyorsa, tüm iletileri tüketir ve hedefine yar. Aksi takdirde, ileti rezervasyonları yayımlar veya iptal eder ve her kaynağın bir ileti almasını tekrar bekler.

Bir dizi kaynaktan gelen giriş iletilerini de okuyan doyumsuz birleştirme, her kaynaktan bir ileti almayı beklerken ek iletileri okumak için ileti ayırmayı kullanır. Örneğin, ve Bileti bloklarından A ileti alan doyumsuz bir birleştirme düşünün. Doyumsuz birleşim B'den iki ileti alır, ancak henüz 'den Abir ileti almadıysa, doyumsuz birleştirme, 'den Bikinci ileti için benzersiz ileti tanımlayıcısını kaydeder. Doyumsuz birleştirmeden A bir ileti aldıktan ve bu iletileri yaydıktan sonra, ikinci iletinin hala kullanılabilir olup olmadığını görmek için kaydedilen ileti B tanımlayıcısını kullanır.

Kendi özel ileti bloğu türlerinizi uygularken ileti ayırmayı kullanabilirsiniz. Özel ileti bloğu türü oluşturma hakkında bir örnek için bkz . İzlenecek Yol: Özel İleti Bloğu Oluşturma.

[Üst]

Ayrıca bkz.

Zaman Uyumsuz Aracılar Kitaplığı