Как бы вы реализовали Erlang-подобную отправку и получение в C ++? - PullRequest
10 голосов
/ 02 сентября 2008

На самом деле этот вопрос состоит из двух частей:

Что касается соответствия шаблонов, я изучал различные проекты, такие как App и Prop . Они выглядят довольно хорошо, но не могут заставить их работать над последней версией (4.x) g ++. Язык Felix также, похоже, довольно хорошо поддерживает сопоставление с образцом, но на самом деле это не C ++.

Что касается Актерской модели , существуют существующие реализации, такие как ACT ++ и Theron , но я не смог найти ничего, кроме статей о первом , а последний - только однопоточный [см. ответы].

Лично я реализовал акторов, используя многопоточность и потокобезопасную очередь сообщений. Сообщения являются хеш-подобными структурами и используют их вместе с рядом макросов препроцессора для реализации простого сопоставления с образцом.

Сейчас я могу использовать следующий код для отправки сообщения:

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

И следующее для простого сопоставления с шаблоном (qDebug и qPrintable зависят от Qt):

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

Однако, это выглядит немного хакерским и не очень надежным.

Как бы вы это сделали? Я пропустил какую-либо существующую работу?

Ответы [ 7 ]

11 голосов
/ 09 октября 2008

Что касается модели Актер, есть существующие реализации, такие как ACT ++ и Терон, но я не смог найти что-нибудь, кроме бумаг по первому, и последний только однопоточный.

Как автору Theron, мне было любопытно, почему вы считаете, что он однопоточный?

Лично я реализовал актеров используя многопоточность и потокобезопасный очередь сообщений

Вот как реализован Theron ..: -)

Ash

4 голосов
/ 27 мая 2009

В настоящее время я реализую библиотеку актеров для C ++ под названием "acedia" (в Google пока ничего об этом нет), которая использует "сопоставление типов". Библиотека - это проект для моей магистерской работы, и вы можете отправлять любые данные актеру вместе с ним.

Небольшой фрагмент:

recipient.send(23, 12.23f);

А на стороне получателя вы можете проанализировать полученное сообщение следующим образом:

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

... или вы можете определить набор правил, который вызывает для вас функцию или метод:

void doSomething(int, float);

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

Также возможно совпадение как по типу, так и по значению:

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

Константа «WILDCARD» означает, что любое значение будет принято. Передать без аргументов равно установить все аргументы "WILDCARD"; Это означает, что вы хотите соответствовать только типам.

Это, конечно, маленький фрагмент. Также вы можете использовать «case-классы», как в Scala. Они сопоставимы с «атомистикой» в эрланге. Вот более подробный пример:

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

Чтобы отреагировать на определенные классы дел, вы можете написать актера следующим образом:

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);
    }

};

Чтобы создать нового актера и запустить его, все, что вам нужно написать, это:

Acedia::spawn<SomeActor>();

Хотя библиотека еще не достигла бета-стадиона, показанные фрагменты работают, и у меня на нем работает первое приложение. Одной из основных целей библиотеки является поддержка распределенного программирования (также через сеть).

Ваш вопрос давно, но если он вам интересен, дайте мне знать! :)

4 голосов
/ 03 сентября 2008

Одной из важных особенностей erlang является то, как эти функции используются для создания надежных систем.

Модель отправки / получения не разделяет и явно копирует. Сами процессы - это легкие нити.

Если вы хотите иметь надежные свойства модели erlang, вам лучше использовать реальные процессы и IPC, а не потоки.

Если вам нужна надежная передача сообщений, возможно, вы захотите сериализовать и десериализовать содержимое. Особенно с типом безопасности.

Сопоставление с образцом в C ++ не всегда красиво, но для этого будет хороший образец - в итоге вы создадите объект диспетчера, который использует некоторую форму полиморфизма, чтобы получить то, что вы хотите.

Хотя, если вы не будете осторожны, вы получите xml поверх каналов:)

Действительно, если вы хотите модель erlang, вы действительно хотите использовать erlang. Если есть медленные биты, я уверен, что вы можете расширить свою программу, используя чужую функцию Интернет.

Проблема, связанная с повторной реализацией деталей, заключается в том, что у вас не будет хорошей связной библиотеки и решения. Решения, которые у вас уже есть, больше не похожи на C ++.

2 голосов
/ 10 ноября 2010

Вы можете имитировать поведение, используя механизм сигнала / слота Qt, тем более что сигнал / слот Qt поддерживает многопоточность.

0 голосов
/ 17 апреля 2014

Сегодня, если вам нужны надежные актеры в стиле эрланга в C ++ и сопоставление с образцом, Может быть, Руст это ответ.

Конечно, это не было публично, когда ОП спросил 5 лет назад, и по состоянию на апрель 2014 года он все еще не v1.0 - но он прогрессировал очень хорошо и определенно стабилизируется, достаточно языкового ядра Я думаю, что он стабилен.

И, конечно, это не C ++, но он имеет тот же подход к управлению памятью, что и C ++, за исключением того, что он поддерживает легкие задачи без общей памяти по умолчанию (затем предоставляет функции управляемой библиотеки для совместного использования - «Arc»); Он может напрямую вызывать (и напрямую выставлять) функции 'extern C'. Вы не можете делиться шаблонными заголовками библиотек с C ++ - но вы можете написать универсальные шаблоны, которые имитируют классы коллекций C ++ (и наоборот) для передачи ссылок на структуры данных через.

0 голосов
/ 09 июня 2009

Сегодня я размещаю библиотеку в sourceforge: https://sourceforge.net/projects/acedia/

Как я уже говорил, это ранний релиз. Но не стесняйтесь критиковать это!

0 голосов
/ 30 мая 2009

Мне определенно было бы интересно взглянуть на вашу библиотеку "acedia", и я бы хотел помочь, чем смогу. Erlang имеет несколько замечательных конструкций, и C ++ может определенно выиграть от такой библиотеки.

...