Как бы вы реализовали Erlang-подобную отправку и получение на C?

StackOverflow https://stackoverflow.com/questions/40423

  •  09-06-2019
  •  | 
  •  

Вопрос

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

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

Для Модель актера, существуют существующие реализации, такие как ACT и Терон, но кроме статей о первом я ничего не нашел, а последний является только однопоточным [Посмотри ответы].

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

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

(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

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

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

Это было полезно?

Решение

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

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

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

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

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

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

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

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

Другие советы

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

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

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

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

Пепел

В настоящее время я реализую библиотеку актеров для 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»;это означает, что вы хотите сопоставлять только типы.

Это, конечно, небольшой фрагмент.Также вы можете использовать «кейс-классы», как в 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>();

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

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

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

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

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

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

Сегодня, если вам нужны надежные актеры в стиле erlang в C и сопоставление с образцом, возможно, Rust — это ответ.

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top