Pergunta

Realmente, esta questão parece ter duas partes:

  • Como implementar o padrão de correspondência?
  • Como implementar enviar e receber (i.é.o modelo de agente)?

Para a correspondência de padrões parte, tenho procurado em vários projetos como Aplicação e Prop.Essas olhar muito bonito, mas não podia levá-los a trabalhar em uma versão recente (4.x) de g++.O Felix a linguagem também parece apoiar a correspondência de padrão muito bem, mas não é realmente C++.

Como para o Ator, modelo, existem implementações existentes como ATO++ e Theron, mas eu não poderia encontrar qualquer coisa, mas a de artigos sobre o antigo, e o último é single-threaded apenas [ver respostas].

Pessoalmente, eu tenho implementado atores do uso de threads e uma thread-safe fila de mensagens.As mensagens são de hash-estruturas, e usou-as em conjunto com um número de pré-processador de macros simples implementadas de correspondência de padrão.

Agora, eu posso usar o seguinte código para enviar uma mensagem:

(new Message(this))
    ->set("foo", "bar")
    ->set("baz", 123)
    ->send(recipient);

E o seguinte para fazer simples correspondência de padrões (qDebug e qPrintable são Qt-específica):

receive_and_match(m)
    match_key("foo")    { qDebug("foo: %s", qPrintable(m->value("foo").toString())); }
    or_match_key("baz") { qDebug("baz: %d", m->value("baz").toInt()); }
    or_match_ignore
end_receive

No entanto, isso parece um pouco hackish para mim, e não é muito robusta.

Como você faria isso?Fez eu perder qualquer trabalho existente?

Foi útil?

Solução

Uma das coisas importantes sobre erlang é a forma como os recursos são usados para fazer sistemas robustos.

Enviar/receber modelo não é compartilhamento de arquivos e copiar explicitamente.Os próprios processos são leves threads.

Se você não desejo o robusto propriedades do modelo de erlang, você seria melhor usar processos reais e IPC, ao invés de threads.

Se você deseja robusto para passagem de mensagens que você pode acabar querendo serializar e deserialise o conteúdo.Especialmente com o tipo de segurança.

Correspondência de padrão em C++ não é sempre bonita, mas não vai ser um bom padrão para isso - você vai acabar criando um objeto dispatcher que usa algum tipo de polimorfismo para obter o que deseja.

Apesar de que se você não tiver cuidado pode acabar com xml sobre os tubos :)

Realmente, se você deseja que o modelo de erlang você realmente quer usar erlang.Se há lento bits, tenho certeza de que você pode aumentar o seu programa usando um estrangeiro função da internet.

O problema sobre a re-execução partes, é você não ter uma boa coesa biblioteca e a solução.As soluções que você já não se pareciam muito com o C++ mais.

Outras dicas

Como para o modelo de agente, há implementações existentes como ATO++ e Theron, mas eu não conseguia encontrar qualquer coisa, mas a de artigos sobre o antigo, e o último é single-threaded só.

Como o autor de Theron, eu estava curioso para saber por que você acredita que é single-threaded?

Pessoalmente, eu tenho implementado atores uso de threads e uma thread-safe fila de mensagens

É assim que Theron é implementado..:-)

Ash

Estou actualmente a implementar um ator biblioteca para C++ chamado "acedia" (não há nada ainda sobre isso no google), que usa o "tipo de correspondência".A biblioteca é um projeto para a minha tese de mestrado e que você pode enviar qualquer tipo de dados para um ator com ele.

Um pequeno trecho:

recipient.send(23, 12.23f);

E no lado do destinatário, você pode analisar a mensagem recebida como este:

Message msg = receive();
if (msg.match<int, float>() { ... }

...ou você pode definir um conjunto de regras que invoca uma função ou método para você:

void doSomething(int, float);

InvokeRuleSet irs;
irs.add(on<int, float>() >> doSomething);
receiveAndInvoke(irs);

Também é possível combinar ambos sobre o tipo e o valor:

Message msg = receive();
if (msg.match<int, float>(42, WILDCARD) { ... }
else if (msg.match<int, float>() { ... }

A constante "CURINGA" significa que qualquer valor será acceptet.Passar sem argumentos é igual conjunto de todos os argumentos para "UNIVERSAL";o que significa que você só deseja corresponder os tipos.

Este é, certamente, um pequeno fragmento.Você também pode usar a caso "classes", como em Scala.Eles são comparáveis "atômicos" em erlang.Aqui está um exemplo mais detalhado:

ACEDIA_DECLARE_CASE_CLASS(ShutdownMessage)
ACEDIA_DECLARE_CASE_CLASS(Event1)
ACEDIA_DECLARE_CASE_CLASS(Event2)

Para reagir ao caso de classes que você pode escrever um ator parecido com este:

class SomeActor : public Actor
{

  void shutdown() { done = true; }
  void handleEvent1();
  void handleEvent1();

  public:

    SomeActor() : done(false) { }

    virtual void act()
    {
      InvokeRuleSet irs;
      irs
        .add(on<ShutdownMessage>() >> method(&SomeActor::shutdown))
        .add(on<Event1>() >> method(&SomeActor::handleEvent1))
        .add(on<Event2>() >> method(&SomeActor::handleEvent2))
      ;
      while (!done) receiveAndInvoke(irs);
    }

};

Para criar um novo ator e iniciá-lo, tudo que você tem para escrever é:

Acedia::spawn<SomeActor>();

Apesar de a biblioteca não chegou até mesmo a versão beta do estádio mostrados trechos de trabalho e eu tenho uma primeira aplicação em execução.Um dos principais objetivos da biblioteca é de suporte de programação distribuída (também através de uma rede).

Sua pergunta é há um tempo atrás, mas se você estiver interessado em:deixe-me saber!:)

Você pode imitar o comportamento usando Qt signal/slot mecanismo, especialmente desde Qt signal/slot suporta multitarefa.

Eu com certeza gostaria de estar interessado em olhar para o seu "acedia" biblioteca e gostaria de ajudar de alguma maneira que eu podia.Erlang tem algumas maravilhosas construções e C++ definitivamente poderia beneficiar de uma biblioteca.

Hoje eu hostet a biblioteca no sourceforge: https://sourceforge.net/projects/acedia/

Como eu disse antes, é uma versão inicial.Mas sinta-se livre para criticá-lo!

Hoje, se você quiser erlang estilo robusto atores em C++, e a correspondência de padrões, talvez a Ferrugem é a resposta.

É claro que isso não estava em torno publicamente quando o OP pediu ~5 anos atrás, e a partir de abril de 2014 ainda não é v1.0, mas foi progredindo muito bem e é, definitivamente, a estabilização, o suficiente da língua de núcleo é estável, eu acho.

E ok não é C++, mas tem a mesma abordagem para o gerenciamento de memória como C++, exceto que ele suporta leve tarefas sem memória compartilhada por padrão (em seguida, fornece controlada biblioteca de recursos para partilha - "Arco");Ele pode chamar diretamente (e expor diretamente) 'extern C" de funções.Você não pode compartilhar modelo de biblioteca de cabeçalhos com C++, mas você pode escrever genéricos que simular C++ classes de coleção (e vice versa) para passar referências a dados-estruturas de todo.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top