2008-09-02 33 views
10

En realidad, esta cuestión parece tener dos partes:¿Cómo implementaría enviar y recibir como Erlang en C++?

  • cómo implementar la coincidencia de patrones?
  • Cómo implementar send and receive (es decir, el modelo Actor)?

Para la parte de coincidencia de patrón, he estado investigando varios proyectos como App y Prop. Estos se ven muy bien, pero no pudieron hacer que funcionaran en una versión reciente (4.x) de g ++. El lenguaje Felix también parece ser compatible con la coincidencia de patrones bastante bien, pero realmente no es C++.

En cuanto a la Actor model, existen implementaciones existentes como ACT ++ y Theron, pero no pudieron encontrar nada, pero los papeles en el anterior , y el último es un único subproceso única [ver respuestas].

Personalmente, he implementado actores que usan subprocesos y una cola de mensajes segura para subprocesos. Los mensajes son estructuras similares a hash y se utilizan junto con varias macros de preprocesador para la coincidencia de patrones simple implementada.

En este momento, se puede utilizar el siguiente código para enviar un mensaje:

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

Y lo siguiente que hacer patrón simple juego (qDebug y qPrintable son Qt-específico):

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 

Sin embargo, esto parece un poco hackish para mí, y no es muy robusto.

¿Cómo lo harías? ¿Extrañé algún trabajo existente?

Respuesta

4

Una de las cosas importantes acerca de erlang es cómo se usan las características para hacer sistemas robustos.

El modelo de enviar/recibir es no compartir y copiar de forma explícita. Los procesos en sí son hilos livianos.

Si desea las propiedades robustas del modelo erlang, sería mejor usar procesos reales e IPC en lugar de hilos.

Si desea pasar mensajes sólidos, puede terminar deseando serializar y deserializar los contenidos. Especialmente con seguridad tipo.

La coincidencia de patrones en C++ no siempre es bonita, pero habrá un buen patrón para esto: terminará creando un objeto despachador que usa alguna forma de polimorfismo para obtener lo que desea.

Aunque si no se tiene cuidado se termina con XML a través de tuberías :)

Realmente, si desea que el modelo de Erlang que realmente desea utilizar Erlang. Si hay bits lentos, estoy seguro de que puede aumentar su programa utilizando una función externa de Internet.

El problema de volver a implementar las piezas es que no obtendrá una buena biblioteca y solución cohesivas. Las soluciones que ya tiene ya no se parecen mucho a C++.

11

En cuanto al modelo Actor, hay implementaciones existentes como ACT ++ y Theron, pero no pude encontrar nada más que papeles en el primero, y el último sólo es de un solo subproceso.

Como el autor de Theron, tenía curiosidad por qué crees que es de un solo hilo?

actores Personalmente, he implementado utilizando roscado y una cola de mensajes flujos seguros

Eso es cómo se implementa Theron .. :-)

Ash

+0

Para ser sincero, no tengo ni idea de por qué pensé que Theron tenía un único hilo. Volver a leer el sitio web no me da esa impresión en absoluto. ¡Mis disculpas por la confusión, y creo que sería justo si le diera otra oportunidad a Theron! –

+0

He tenido una experiencia feliz usando la concurrencia de Theron for Actors en los archivos mex de Matlab. – Chinasaur

4

I Actualmente estoy implementando una biblioteca de actores para C++ llamada "acedia" (no hay nada sobre esto en google) que use "tipo de coincidencia". La biblioteca es un proyecto para mi tesis de maestría y puede enviar cualquier tipo de datos a un actor con ella.

Un pequeño fragmento:

recipient.send(23, 12.23f); 

Y en el lado receptor se puede analizar bien el mensaje recibido de esta manera:

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

... o se puede definir un conjunto de reglas que invoca una función o método para usted:

void doSomething(int, float); 

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

también es posible hacer coincidir tanto en tipo y en el valor de:

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

La constante "WILDCARD" significa, que cualquier valor será aceptado. Pasar sin argumentos es igual establecer todos los argumentos a "WILDCARD"; lo que significa que solo quieres hacer coincidir los tipos.

Esto es ciertamente un pequeño fragmento. También puede usar "clases de casos" como en Scala. Son comparables a "atómicos" en erlang. Aquí está un ejemplo más detallado:

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

Para reaccionar a las clases de casos definidos se puede escribir un actor como esto:

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 crear un nuevo actor y ponerlo en marcha, todo lo que tiene que escribir es decir:

Acedia::spawn<SomeActor>(); 

Aunque la biblioteca ni siquiera alcanza el estadio beta los fragmentos mostrados trabajar y tengo una primera aplicación que se ejecuta en él. Uno de los principales objetivos de la biblioteca es apoyar la programación distribuida (también a través de una red).

Su pregunta es hace un tiempo, pero si le interesa: ¡hágamelo saber! :)

+0

Estoy definitivamente interesado; se ve muy bien. ¿Hay un sitio web donde puedo descargar la biblioteca/ver los documentos? ¿Serás abierto al buscarlo? –

0

Definitivamente estaría interesado en mirar su biblioteca "acedia" y me encantaría ayudar de cualquier manera que pudiera. Erlang tiene algunos constructos maravillosos y C++ definitivamente podría beneficiarse de dicha biblioteca.

0

Hoy hostet la biblioteca en SourceForge: https://sourceforge.net/projects/acedia/

Como dije antes de que sea una pronta liberación. ¡Pero siéntete libre de criticarlo!

+0

Lo he descargado, y lo probaré tan pronto como tenga la oportunidad. –

+1

Actualización: acedia está desactualizada, checkout libcppa en su lugar: [https://sourceforge.net/projects/acedia/](https://github.com/neverlord/libcppa) – neverlord

2

Puede imitar el comportamiento utilizando el mecanismo de señal/ranura de Qt, especialmente dado que la señal/ranura de Qt admite multihilo.

0

Hoy en día, si quieres actores robustos con estilo erlang en C++, y coincidencia de patrones, quizás Rust sea la respuesta.

Por supuesto, esto no estaba disponible públicamente cuando el OP preguntó ~ 5 años atrás, y hasta abril de 2014 todavía no es v1.0 todavía - pero ha estado progresando muy bien y definitivamente se está estabilizando, suficiente lenguaje el núcleo es estable, creo.

Y vale, no es C++, pero tiene el mismo enfoque para la administración de memoria que C++, excepto que admite tareas livianas sin memoria compartida por defecto (luego proporciona características de biblioteca controladas para compartir - "Arc"); Puede llamar directamente (y exponer directamente) funciones de 'C externo'. No puede compartir encabezados de biblioteca con plantillas con C++, pero puede escribir genéricos que imiten las clases de colección C++ (y viceversa) para pasar referencias a estructuras de datos.

Cuestiones relacionadas