Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Aracılar Kütüphanesi, mesajları uygulama bileşenleri arasında iş parçacığı açısından güvenli bir şekilde yaymanıza olanak tanıyan birkaç mesaj bloğu türü sağlar. Bu ileti bloğu türleri, concurrency::send, concurrency::asend, concurrency::receive ve concurrency::try_receive gibi çeşitli ileti geçirme yordamlarıyla birlikte sıkça 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. Bir hedef, iletileri alan bir iletişim uç noktasıdır. 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 ISource adresinden türetilir; hedef olarak davranan ileti bloğu türleri ITarget adresinden türetilir. Kaynak ve hedef olarak davranan ileti bloğu türleri hem hem ISourcede ITarget '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 geciktiren bir ileti bloğu, bu iletiyi rezerve edebilir ve daha sonra tüketebilir. İleti ayırma, bu konunun devamında İleti Ayırma bölümünde daha ayrıntılı olarak açıklanmıştır.
Agent Kitaplığı, ileti bloklarının iletileri zaman uyumsuz veya zaman uyumlu bir şekilde iletmesini sağlar. Örneğin, send işlevini kullanarak bir ileti bloğuna zaman uyumlu bir şekilde bir ileti ilettiğinizde, çalışma zamanı süreci, hedef blok iletiyi kabul edene veya reddedene kadar mevcut bağlamı engeller. Bir ileti bloğuna bir mesajı eşzamansız olarak ilettiğinizde, örneğin asend işlevini kullanarak, çalışma zamanı mesajı hedefe sunar ve hedef mesajı kabul ederse, çalışma zamanı mesajı alıcıya ileten eşzamansız bir görevi 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 aktarmak için send veya asend çağrısını yaparsınız. 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.
tekli_atama
Bir kereye yazılabilen ve birden çok kez okunabilen bir ileti depolar.
çağırmak
bir ileti aldığında çalışma gerçekleştirir.
transformatör
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 ikisi | Sipariş Verildi | Sınırsız | Sınırsız |
overwrite_buffer |
Her ikisi | Sipariş Edildi | Sınırsız | Sınırsız |
single_assignment |
Her ikisi | Sipariş | Sınırsız | Sınırsız |
call |
Hedef | Sipariş edilen | Sınırsız | Geçerli değil |
transformer |
Her ikisi | Sipariş edilen | Sınırsız | 1 |
choice |
Her ikisi | Sipariş edilen | 10 | 1 |
join |
Her ikisi | Sipariş edilen | Sınırsız | 1 |
multitype_join |
Her ikisi | Sipariş edilen | 10 | 1 |
timer |
Kaynak | Geçerli değil | Geçerli değil | 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, unbounded_buffer sınıfıyla çalışmanın temel yapısı gösterilmektedir. 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ı nasıl kullanacağınızı 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 unbounded_buffer ileti depolaması dışında sınıfına overwrite_buffer benzer. Ayrıca, hedef overwrite_buffer nesnesinden bir mesaj aldığında, bu mesaj 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, overwrite_buffer sınıfıyla çalışmanın temel yapısı gösterilmektedir. 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
overwrite_buffer sınıfının nasıl kullanılacağını 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 örnek, single_assignment sınıfıyla çalışmanın temel yapısını göstermektedir. 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. Her iki overwrite_buffer ve single_assignment sınıfı tek bir mesaj depolamasına rağmen, single_assignment sınıfına 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
single_assignment sınıfının nasıl kullanılacağını gösteren eksiksiz bir örnek için bkz. Kılavuz: Futures Kavramları 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 örnek, call sınıfıyla çalışmanın temel yapısını göstermektedir. 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ği için, bu örnekte nesnenin işlev döndürülmeden önce tüm iletileri işlediğinden emin olmak amacıyla bir sayaç değişkeni ve bir 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ı gösteren eksiksiz bir örnek için bkz call. Nasıl yapılır: Çağrı ve Dönüştürücü Sınıflarına İşlev 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.
transformer sınıfı, veri aldığında kullanıcı tanımlı bir işlev gerçekleştirdiği için call sınıfına benzer. 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 örnek, transformer sınıfıyla çalışmanın temel yapısını göstermektedir. 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
Eksiksiz bir örnek için, transformer sınıfının nasıl kullanılacağını gösteren örneğe bakınız: 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, Windows API fonksiyonunu WaitForMultipleObjectsbWaitAll parametresi FALSE olarak ayarlandığında çağırmaya benzer. Ancak, choice sınıfı verileri bir dış eşitleme nesnesi yerine olayın kendisine bağlar.
Genellikle, uygulamanızda kontrol akışını yönlendirmek için choice sınıfını concurrency::receive işleviyle birlikte kullanırsınız. 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 örnek, choice sınıfıyla çalışmanın temel yapısını göstermektedir. Bu örnekte concurrency::make_choice işlevi, üç mesaj bloğu arasında seçim yapan bir choice nesnesi 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ı 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ı
concurrency::join ve concurrency::multitype_join sınıfları, bir kaynaklar kümesinin her üyesinin ileti almasını beklemenizi 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, bWaitAll parametresi TRUE olarak ayarlandığında Windows API işlevi WaitForMultipleObjects’yi çağırmaya benzer. Ancak, tıpkı bir choice nesne gibi ve join nesneler de multitype_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 join veya multitype_join nesnesine bağlanma sırasına göre görünür. Var olan bir kaynak arabelleği birleştirmeden çıkarmamanızı öneririz, çünkü kaynak arabelleklerini bir join veya multitype_join nesnesine bağladığınız sıralama, sonuçta ortaya çıkan vector veya tuple nesnesindeki öğelerin sıralamasıyla ilişkilidir. Bunun yapılması, belirtilmeyen davranışlara neden olabilir.
Açgözlü ve Açgözlü Olmayan Birleştirmeler
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.
Açgözlü olmayan birleştirme, iletileri iki aşamada alır. İlk olarak, açgözlü 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 hedefe iletir. Aksi takdirde, ileti rezervasyonları yayımlar veya iptal eder ve her kaynağın bir ileti almasını tekrar bekler.
Açgözlü birleştirmeler, iletileri hemen kabul ettikleri için açgözlü olmayan birleştirmelere göre daha iyi performans gösterir. Ancak, nadir durumlarda, açgözlü birleşimler kilitlenmelere yol açabilir. Bir veya daha fazla paylaşılan kaynak nesnesi içeren birden çok bağlantınız olduğunda, tutumlu olmayan bir bağlantı kullanın.
Örnek
Aşağıdaki örnek, join sınıfıyla çalışmanın temel yapısını göstermektedir. Bu örnek, üç single_assignment nesnesinden alan bir join nesne oluşturmak için concurrency::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, choice sınıfı örneğine benzer, ancak join sınıfı, tüm kaynak ileti bloklarının bir mesaj almasını bekler.
// 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ı 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]
zamanlayıcı 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 çağırırken _Repeating parametresi için true değerini geçirin. Aksi takdirde, yinelenmeyen bir zamanlayıcı oluşturmak için false parametresi için _Repeating değerini geçirin. Zamanlayıcı yineleniyorsa, her aralık sonrasında hedefine aynı iletiyi gönderir.
Aracılar Kitaplığı, timer nesnelerini başlatılmamış halde oluşturur. 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 bir zamanlayıcıyı duraklatmak için concurrency::timer::pause yöntemini çağırın.
Örnek
Aşağıdaki örnek, timer sınıfıyla çalışmanın temel yapısını göstermektedir. Örnek, uzun bir işlemin ilerleme durumunu raporlamak için timer ve call nesnelerini kullanır.
// 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
Eksiksiz bir örnek için, timer sınıfının nasıl kullanılacağını gösteren, 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. Mesaj ileten ağda veri akışını kontrol etmek 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 mesaj rezervasyonu 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. Her ikisi de iletileri daha sonra kullanmak üzere rezerve etmek için mesaj rezervasyonunu kullanır. Daha önce açıklandığı gibi, doyumsuz birleştirme iletileri iki aşamada alır. İlk aşamada açgözlü olmayan join nesne, kaynaklarının her birinden mesaj almayı bekler. Cimri olmayan bir birleştirme daha sonra bu iletilerin her birini ayırmaya çalışır. Her iletiyi ayırabiliyorsa, tüm iletileri tüketir ve hedefe iletir. Aksi takdirde, ileti rezervasyonları yayımlar veya iptal eder ve her kaynağın bir ileti almasını tekrar bekler.
Açgözlü birleştirme, bir dizi kaynaktan gelen giriş iletilerini de okur. Her kaynaktan bir ileti almayı beklerken ek iletileri okumak için mesaj rezervasyonunu kullanır. Örneğin, mesaj blokları A ve B tarafından mesajlar alan açgözlü birleştirmeyi düşünün. Açgözlü birleşim B'den iki ileti alır, ancak henüz A'den bir ileti almadıysa, açgözlü birleşim B'den ikinci ileti için benzersiz ileti tanımlayıcısını kaydeder. Açgözlü birleştirme A öğesinden bir mesaj alıp bu mesajları yaydıktan sonra, B öğesinden gelen ikinci mesajın hala kullanılabilir olup olmadığını görmek için kaydedilen mesaj 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]