Blocos assíncronas de mensagem
A biblioteca de agentes fornece vários tipos de mensagem- bloco que permitem que você se propagar mensagens entre componentes do aplicativo de uma maneira segura.Esses tipos de mensagem- bloco são freqüentemente usados com várias rotinas mensagem- passando, como concurrency::send, concurrency::asend, concurrency::receive, e concurrency::try_receive.Para obter mais informações sobre a mensagem que passa rotinas que são definidas pela biblioteca de agentes, consulte Mensagem que passa funções.
Seções
Este tópico contém as seções a seguir:
Fontes e destinos
Propagação de mensagem
Visão geral de tipos do bloco de mensagem
classe de unbounded_buffer
classe de overwrite_buffer
classe de single_assignment
classe de chamada
classe transformador
classe bem escolhida
adição e classes de multitype_join
classe de timer
Filtragem de mensagem
Reserva de mensagem
Fontes e destinos
As fontes e destinos são dois participantes importantes sobre passar de mensagem.Uma fonte refere-se a um ponto final de comunicação que envia mensagens.Um destino se refere a um ponto final de comunicação que receber mensagens.Você pode pensar em uma origem como um ponto de extremidade que você ler e um destino como um ponto de extremidade a que você escreva.Os aplicativos em fontes e destinos juntos para formar redes de mensagem.
A biblioteca de agentes usa duas classes abstratas para representar fontes e destinos: concurrency::ISource e concurrency::ITarget.Tipos de bloco de mensagem que atuam como as fontes derivam de ISource; os tipos de bloco de mensagem que atuam como destinos derivam de ITarget.Os tipos de bloco de mensagem que atuam como fontes e destinos derivam de ISource e de ITarget.
Superior[]
Propagação de mensagem
A bolha mensagem de é o ato de enviar uma mensagem de um componente para outro.Quando um bloco de mensagem é oferecido uma mensagem, pode aceitar, diminuir, ou adiar a mensagem.Armazenamentos em blocos de cada mensagem e passe mensagens de maneiras diferentes.Por exemplo, a classe de unbounded_buffer armazena um número ilimitado de mensagens, a classe de overwrite_buffer armazena uma única mensagem de uma vez, e a classe transformador armazena uma versão modificada de cada mensagem.Esses tipos de bloco de mensagem são descritos em detalhes posteriormente neste documento.
Quando um bloco de mensagem aceita uma mensagem, opcionalmente pode realizar o trabalho e, se o bloco de mensagem é uma fonte, passa a mensagem resultante para outro membro da rede.Um bloco de mensagem pode usar uma função de filtro para reduzir as mensagens não desejar receber.Filtros são descritos em detalhes posteriormente neste tópico, na seção Filtragem de mensagem.Um bloco de mensagem que adia uma mensagem pode permitir a mensagem e consumir-la posteriormente.Font fallback de mensagem é descrita em mais detalhes posteriormente neste tópico, na seção Reserva de mensagem.
A biblioteca de agentes permite blocos de mensagem passa a de forma assíncrona de forma síncrona ou mensagens.Quando você passa uma mensagem a um bloco de mensagem, de forma síncrona por exemplo, usando a função de send , o runtime bloqueia o contexto atual até que o bloco de destino aceita ou rejeite a mensagem.Quando você passa uma mensagem a um bloco de mensagem de forma assíncrona, por exemplo, usando a função de asend , o tempo de execução oferece a mensagem para o destino, e se o destino aceita a mensagem, o tempo de execução agenda uma tarefa assíncrona que propague a mensagem para o receptor.O tempo de execução usa tarefas leve propagar mensagens de uma maneira cooperativa.Para obter mais informações sobre as tarefas leve, consulte Agendador de tarefa (tempo de execução de simultaneidade).
Os aplicativos em fontes e destinos juntos para formar redes de mensagem.Normalmente, você vincula a rede e a chamada send ou asend para passar dados para a rede.Para conectar um bloco de mensagem de origem para um destino, chame o método de concurrency::ISource::link_target .Para desativar um bloco de origem de um destino, chame o método de concurrency::ISource::unlink_target .Para desativar um bloco de origem de todos os seus alvos, chame o método de concurrency::ISource::unlink_targets .Quando um bloco de mensagem predefinida de tipos as folhas defina o escopo ou é destruído, ele automaticamente desliga-se de todos os blocos de destino.Alguns tipos de bloco de mensagem restringe o número máximo de destinos a que podem escrever.A seção a seguir descreve as limitações que se aplicam aos tipos predefinidos do bloco de mensagem.
Superior[]
Visão geral de tipos do bloco de mensagem
A tabela a seguir descreve resumidamente a função de tipos importantes de mensagem- bloco.
unbounded_buffer
Armazena uma fila de mensagens.overwrite_buffer
Armazena uma mensagem a que pode ser escrita e leitura de várias vezes.single_assignment
Armazena uma mensagem que pode ser escrita em uma vez e leitura de várias vezes.chamada
O trabalho é executado quando ele recebe uma mensagem.transformador
O trabalho é executado quando receber dados e envia o resultado desse trabalho para outro bloco de destino.A classe de transformer pode atuar em diferentes tipos de entrada e saída.escolha
Seleciona a primeira mensagem disponível de um conjunto de fontes.adição e o multitype join
Espere todas as mensagens sejam recebidas de um conjunto de fontes e combinar nas mensagens em uma mensagem para outro bloco de mensagem.timer
Enviar uma mensagem a um bloco de destino em um intervalo normal.
Esses tipos de mensagem- bloco têm características diferentes que são úteis para as situações diferentes.Esses são algumas das características:
Tipo de propagação: Se o bloco de mensagem atua como uma fonte de dados, um receptor de dados, ou ambos.
Ordenação de mensagem: Se o bloco de mensagem mantém o original ordem em que as mensagens são enviadas e recebidas.Cada mensagem predefinida em blocos mantém a ordem em que envia original ou recebe mensagens.
Contagem de origem: O número máximo de fontes de que o bloco de mensagem pode ler.
Contagem de destino: O número máximo de destinos a qual o bloco de mensagem pode escrever.
A tabela a seguir mostra como essas características se referem aos vários mensagem- bloco necessários.
Em blocos mensagem |
Tipo de bolha origem (, ou ambos destino) |
Ordenação de mensagens (ordenada ou desordenada) |
Contagem de origem |
Contagem de destino |
---|---|---|---|---|
unbounded_buffer |
Ambos |
Ordenada |
Irrestrito |
Irrestrito |
overwrite_buffer |
Ambos |
Ordenada |
Irrestrito |
Irrestrito |
single_assignment |
Ambos |
Ordenada |
Irrestrito |
Irrestrito |
call |
Destino |
Ordenada |
Irrestrito |
Não aplicável |
transformer |
Ambos |
Ordenada |
Irrestrito |
1 |
choice |
Ambos |
Ordenada |
10 |
1 |
join |
Ambos |
Ordenada |
Irrestrito |
1 |
multitype_join |
Ambos |
Ordenada |
10 |
1 |
timer |
Origem |
Não aplicável |
Não aplicável |
1 |
As seções a seguir descrevem os tipos de mensagem- bloco com mais detalhes.
Superior[]
classe de unbounded_buffer
A classe representa uma estrutura de concurrency::unbounded_buffer assíncrona de uso geral de mensagem.Esta classe armazena primeiro em, primeiro a sair de (FIFO) fila de mensagens que podem ser gravadas por várias fontes ou para ler os vários destinos.Quando um destino recebe uma mensagem de um objeto de unbounded_buffer , essa mensagem é removida de fila de mensagens.Como consequência, embora um objeto de unbounded_buffer pode ter vários destinos, somente um destino receberá cada mensagem.A classe de unbounded_buffer é útil quando você deseja passar várias mensagens para outro componente, e esse componente deve receber cada mensagem.
Exemplo
O exemplo a seguir mostra a estrutura básica de como trabalhar com a classe de unbounded_buffer .Este exemplo envia três valores a um objeto de unbounded_buffer e lê a trás dos valores do mesmo objeto.
// 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;
}
Esse exemplo produz a seguinte saída.
Para um exemplo completo que mostra como usar a classe de unbounded_buffer , considere Como: Padrões de Produtor- Consumidor de implementar vários.
Superior[]
classe de overwrite_buffer
A classe de concurrency::overwrite_buffer é semelhante à classe de unbounded_buffer , exceto que a armazenamentos de um objeto de overwrite_buffer apenas uma mensagem.Além disso, quando um destino recebe uma mensagem de um objeto de overwrite_buffer , a mensagem não é removido do buffer.Como consequência, vários destinos recebem uma cópia de mensagem.
A classe de overwrite_buffer é mais mensagens para outro componente, mas do componente precisa úteis quando você deseja passar somente o valor mais recente.Essa classe também é útil quando você deseja passar uma mensagem para vários componentes.
Exemplo
O exemplo a seguir mostra a estrutura básica de como trabalhar com a classe de overwrite_buffer .Este exemplo envia três valores a um objeto de overwrite _buffer e depois lê o valor atual do mesmo objeto três vezes.Este exemplo é semelhante ao exemplo para a classe de unbounded_buffer .No entanto, a classe de overwrite_buffer armazena apenas uma mensagem.Além disso, o tempo de execução não remove a mensagem de um objeto de overwrite_buffer depois que é lido.
// 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;
}
Esse exemplo produz a seguinte saída.
Para um exemplo completo que mostra como usar a classe de overwrite_buffer , considere Como: Padrões de Produtor- Consumidor de implementar vários.
Superior[]
classe de single_assignment
A classe de concurrency::single_assignment é semelhante à classe de overwrite_buffer , exceto que um objeto de single_assignment pode ser escrito a apenas uma vez.Como a classe de overwrite_buffer , quando um destino receber uma mensagem de um objeto de single_assignment , que a mensagem não será removida do objeto.Como consequência, vários destinos recebem uma cópia de mensagem.A classe de single_assignment é útil quando você deseja passar uma mensagem para vários componentes.
Exemplo
O exemplo a seguir mostra a estrutura básica de como trabalhar com a classe de single_assignment .Este exemplo envia três valores a um objeto de single_assignment e depois lê o valor atual do mesmo objeto três vezes.Este exemplo é semelhante ao exemplo para a classe de overwrite_buffer .Embora as classes de overwrite_buffer e de single_assignment armazena uma única mensagem, a classe de single_assignment pode ser escrita a apenas uma vez.
// 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;
}
Esse exemplo produz a seguinte saída.
Para um exemplo completo que mostra como usar a classe de single_assignment , considere Passo a passo: implementando futuros.
Superior[]
classe de chamada
A classe de concurrency::call atua como um receptor de mensagem que executa uma função de trabalho quando receber dados.Essa função do operador pode ser uma expressão lambda, um objeto de função, ou um ponteiro de função.Um objeto de call se comporta de forma diferente do que uma chamada de função comum porque atua paralelamente a outros componentes que você envia mensagens.Se um objeto de call está executando o trabalho quando receber uma mensagem, adiciona aquela mensagem para uma fila.Cada objeto de call processa mensagens enfileirados na ordem em que eles são recebidas.
Exemplo
O exemplo a seguir mostra a estrutura básica de como trabalhar com a classe de call .Este exemplo cria um objeto de call que imprime cada valor que recebe o console.O exemplo envia em três valores para o objeto de call .Porque o objeto de call processa mensagens em um segmento separado, este exemplo também usa uma variável de contagem e um objeto de evento para garantir que os processos que o objeto de call todas as mensagens antes da função de wmain retornam.
// 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();
}
Esse exemplo produz a seguinte saída.
Para um exemplo completo que mostra como usar a classe de call , considere Como: Fornecer funções de trabalho para as classes de chamada e transformador.
Superior[]
classe transformador
A classe de concurrency::transformer atua como um receptor de mensagem e como um remetente de mensagem.A classe de transformer é semelhante à classe de call porque executa uma função de trabalho definido pelo usuário quando receber dados.No entanto, a classe de transformer também envia o resultado da função de trabalho para objetos de receptor.Como um objeto de call , um objeto de transformer atua paralelamente a outros componentes que você envia mensagens.Se um objeto de transformer está executando o trabalho quando receber uma mensagem, adiciona aquela mensagem para uma fila.Cada objeto de transformer processa as mensagens enfileirados na ordem em que eles são recebidas.
A classe de transformer envia a mensagem a um destino.Se você definir o parâmetro de _PTarget no construtor, a NULLmais tarde você pode especificar o destino chamando o método de concurrency::link_target .
Diferentemente de todos os outros tipos assíncronas do bloco de mensagem que são fornecidos pela biblioteca de agentes, a classe de transformer pode atuar em diferentes tipos de entrada e saída.Essa capacidade para transformar os dados de um tipo para outro faz a classe de transformer um componente-chave em muitas redes simultâneas.Além disso, você pode adicionar funcionalidades paralela mais mais aguçado na função de trabalho de um objeto de transformer .
Exemplo
O exemplo a seguir mostra a estrutura básica de como trabalhar com a classe de transformer .Este exemplo cria um objeto de transformer múltiplos que cada valor de int de entrada por 0,33 para produzir um valor de double como saída.O exemplo então recebe os valores tornam-se do mesmo objeto de transformer e imprime-os no console.
// 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;
}
Esse exemplo produz a seguinte saída.
Para um exemplo completo que mostra como usar a classe de transformer , considere Como: Use o transformador em um canal de dados.
Superior[]
classe bem escolhida
A classe de concurrency::choice seleciona a primeira mensagem disponível de um conjunto de fontes.A classe de choice representa um mecanismo de fluxo de controle em vez de um mecanismo de fluxo de dados ( Biblioteca de agentes assíncrono o tópico descreve as diferenças entre o fluxo de dados e o fluxo de controle).
Ler de um objeto choice é semelhante a chamar a função da API do Windows WaitForMultipleObjects quando tiver o parâmetro de bWaitAll definido como FALSE.No entanto, os dados dos próprios associa ao evento da classe de choice em vez a um objeto externo de sincronização.
Normalmente, você usa a classe de choice juntamente com a função de concurrency::receive para levar o fluxo de controle em seu aplicativo.Use a classe de choice quando você precisa selecionar entre os buffers de mensagem que têm diferentes tipos.Use a classe de single_assignment quando você precisa selecionar entre os buffers de mensagem que têm o mesmo tipo.
A ordem em que você vincula fontes para um objeto de choice é importante porque pode determinar que mensagem é selecionada.Por exemplo, considere os casos onde você vincula os buffers de vários mensagem que já contém uma mensagem a um objeto de choice .O objeto de choice seleciona a mensagem da primeira fonte que está associado a.Depois que você vincula todas as fontes, o objeto de choice preserva a ordem em que cada origem recebe uma mensagem.
Exemplo
O exemplo a seguir mostra a estrutura básica de como trabalhar com a classe de choice .Este exemplo usa a função de concurrency::make_choice para criar um objeto de choice que selecionar entre três blocos de mensagem.O exemplo então calcula vários números de Fibonacci e armazena cada resultado em um bloco diferente de mensagem.O exemplo imprime no console uma mensagem baseada em operação que tiver concluído primeiro.
// 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;
}
}
Este exemplo produz a seguinte saída de exemplo:
Porque a tarefa que calcula o número de 35th Fibonacci não é garantida para concluir primeiro, a saída deste exemplo podem variar.
Este exemplo usa o algoritmo de concurrency::parallel_invoke para calcular paralelamente números de Fibonacci.Para obter mais informações sobre parallel_invoke, consulte Algoritmos paralelos.
Para um exemplo completo que mostra como usar a classe de choice , considere Como: selecionar entre tarefas concluídas.
Superior[]
adição e classes de multitype_join
As classes de concurrency::join e de concurrency::multitype_join permitem que você espera cada membro de um conjunto de fontes para receber uma mensagem.A classe de join atua em objetos de origem que tem um tipo de mensagem comuns.A classe de multitype_join atua em objetos de origem que podem ter tipos diferentes de mensagem.
Ler de um objeto de join ou de multitype_join é semelhante a chamar a função da API do Windows WaitForMultipleObjects quando tiver o parâmetro de bWaitAll definido como TRUE.No entanto, apenas como um objeto de choice , join e objetos de multitype_join usam um mecanismo de evento que associa os próprios dados para o evento em vez a um objeto externo de sincronização.
Ler de um objeto de join gera um objeto de std::vector .Ler de um objeto de multitype_join gera um objeto de std::tuple .Os elementos aparecem nesses objetos na mesma ordem que os buffers correspondentes de origem são associados ao objeto de join ou de multitype_join .Porque a ordem em que você tem buffers de origem a um objeto de join ou de multitype_join está associado com a ordem dos elementos em vector ou o objeto resultante de tuple , recomendamos que você não unlink um buffer existente fonte de uma associação.Isso pode levar ao comportamento não especificado.
Ávido contra não ávido join
As classes de join e de multitype_join suportam o conceito de ávido e não ávido join.Um ávido join aceita uma mensagem de cada uma das fontes como as mensagens se tornam disponíveis até que qualquer mensagem está disponível.Um não ávido join recebe mensagens de duas fases.Primeiro, um não ávido join a espera até que é oferecido uma mensagem de cada uma das fontes.Segundo, que as mensagens de origem estiverem disponíveis, um não ávido ingressar em tentativas para permitir cada uma dessas mensagens.Se pode definir cada mensagem, consome todas as mensagens e propagar-las para seu destino.Caso contrário, libera-se, ou cancelamentos, as reservas de mensagem e espera-se novamente cada origem para receber uma mensagem.
Ávido join executam melhor do que não ávido joins porque aceitam mensagens imediatamente.No entanto, em casos raros, ávido join pode resultar em deadlocks.Use um não ávido join quando você tiver vários joins que contém um ou mais objetos compartilhados de origem.
Exemplo
O exemplo a seguir mostra a estrutura básica de como trabalhar com a classe de join .Este exemplo usa a função de concurrency::make_join para criar um objeto de join que recebeu de três objetos de single_assignment .Este exemplo calcula vários números de Fibonacci, armazena cada resultado em um objeto diferente de single_assignment , e imprime no console cada resultado que o objeto de join comporta.Este exemplo é semelhante ao exemplo para a classe de choice , exceto que a espera da classe de join para que todos os blocos de mensagem de origem recebe uma mensagem.
// 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;
}
Esse exemplo produz a seguinte saída.
Este exemplo usa o algoritmo de concurrency::parallel_invoke para calcular paralelamente números de Fibonacci.Para obter mais informações sobre parallel_invoke, consulte Algoritmos paralelos.
Para os exemplos completos que mostram como usar a classe de join , consulte Como: selecionar entre tarefas concluídas e Passo a passo: Usar join para evitar a deadlock.
Superior[]
classe de timer
A classe de concurrency::timer atua como uma fonte de mensagem.Um objeto de timer envia uma mensagem a um destino após um período de tempo especificado passados.A classe de timer é útil quando você deve atrasar enviar uma mensagem ou você deseja enviar uma mensagem em um intervalo normal.
A classe de timer envia a mensagem a apenas um destino.Se você definir o parâmetro de _PTarget no construtor, a NULLmais tarde você pode especificar o destino chamando o método de concurrency::ISource::link_target .
Um objeto de timer pode repetir ou não repita.Para criar um timer repetitiva, true passar para o parâmetro de _Repeating quando você chama o construtor.Caso contrário, false passar para o parâmetro de _Repeating crie um temporizador não repetindo.Se o timer é repetitiva, envia a mesma mensagem para seu destino após cada intervalo.
A biblioteca de agentes cria objetos de timer no estado não inicializado.Para iniciar um objeto timer, chame o método de concurrency::timer::start .Para parar um objeto de timer , destrua o objeto ou chamar o método de concurrency::timer::stop .Para pausar um timer de repetição, chame o método de concurrency::timer::pause .
Exemplo
O exemplo a seguir mostra a estrutura básica de como trabalhar com a classe de timer .O exemplo usa timer e objetos de call para relatar o progresso de uma operação longa.
// 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;
}
Este exemplo produz a seguinte saída de exemplo:
Para um exemplo completo que mostra como usar a classe de timer , considere Como: enviar uma mensagem em um intervalo normal.
Superior[]
Filtragem de mensagem
Quando você cria um objeto do bloco de mensagem, você pode fornecer uma função de filtro que determina se o bloco de mensagem aceita ou rejeita uma mensagem.Uma função de filtro é uma maneira útil para garantir que um bloco de mensagens recebe somente certos valores.
O exemplo a seguir mostra como criar um objeto de unbounded_buffer que usa uma função de filtro para aceitar somente mesmo números.O objeto de unbounded_buffer descarta números ímpares, e como consequência não propaga números ímpares a seus blocos de destino.
// 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;
}
}
Esse exemplo produz a seguinte saída.
Uma função de filtro pode ser uma função lambda, um ponteiro de função, ou um objeto de função.Cada função de filtro utiliza uma das seguintes formas.
Para eliminar copiar desnecessário de dados, use o segundo formulário quando você tiver um agregado tipo que seja propagado por valor.
Filtragem de mensagem oferece suporte ao modelo de programação do fluxo de dados , em que os componentes executam cálculos quando recebem dados.Para exemplos que usam funções de filtragem para controlar o fluxo de dados em uma mensagem que passa a rede, consulte Como: Use um filtro de bloco de mensagem, Passo a passo: Criando um agente do fluxo de dados, e Passo a passo: Criando uma rede Processamento de imagens.
Superior[]
Reserva de mensagem
Font fallback de mensagem permite que um bloco de mensagens para permitir para uso posterior uma mensagem.Normalmente, a reserva de mensagem não é usada diretamente.No entanto, a mensagem de fallback noções básicas sobre melhor pode ajudar você a entender o comportamento dos tipos predefinidos do bloco de mensagem.
Considere não ávido e ávido join.Ambos usam a reserva de mensagens para permitir para uso posterior mensagens.Um descrito anteriormente, um não ávido join recebe mensagens de duas fases.Durante a primeira etapa, um objeto não ávido de join espera cada uma das fontes para receber uma mensagem.Um não ávido condições na tentativa de definir cada uma dessas mensagens.Se pode definir cada mensagem, consome todas as mensagens e propagar-las para seu destino.Caso contrário, libera-se, ou cancelamentos, as reservas de mensagem e espera-se novamente cada origem para receber uma mensagem.
Um ávido join, que também ler mensagens de entrada de um número de fontes, fallback mensagem de usa as mensagens adicionais de leitura quando esperar para receber uma mensagem de cada origem.Por exemplo, considere um ávido join que receber mensagens de blocos A e Bde mensagem.Se o ávidos unem duas recebem mensagens de B mas ainda não recebeu uma mensagem de A, o ávido join salva o identificador exclusivo de mensagem para a segunda mensagem de B.Depois que o ávidos unem recebem uma mensagem de A e propaga para fora essas mensagens, ele usa o identificador de mensagem exceto para ver se a segunda mensagem de B ainda está disponível.
Você pode usar font fallback de mensagem quando você implementar seus próprios tipos personalizados do bloco de mensagem.Para um exemplo sobre como criar uma mensagem personalizado em blocos, consulte Passo a passo: Criando um bloco personalizado de mensagem.
Superior[]