Search code examples
c++linuxmultithreadingpreempt-rtc++-actor-framework

Port handcraft systems to libcaf


I currently have an application which uses handcrafted actors. My plan is to to port it to libcaf.

The current state is: I have one big global message queue where my systems (aka actors) subscribe to get their messages. They respond with messages to that global queue.

The whole system is a realtime application which runs on Linux rt-preempt kernel. The GUI thread is a system(actor) itself but it's not on RT priority.

Right now my systems don't need to know the receivers of their messages, because the receivers register for their wanted ones.

My porting idea is as following: I use one global actor as a replacement for my global message queue and it handles the registration for the messages. This way, i can get an easy log of the messages for debugging purpose and i dont need to let all actors know all possible targets.

I have an IO system (canbus) which handles the contact to the real world.

In my current system i spawn the GUI thread + system. It waits for RT to initialize. After the gui thread is spawned, i switch to RT Preempt priority and create the other systems, prefault the stack and so on. When all is setup, i notify the gui that RT is up. Now my system is initilized.

When some fatal things happens or the system Needs to shut down, i send a message and all systems shut down and all threads get joined.

My questions are: How can i seperate the GUI actor/thread from the RT thread in libcaf? Would you recommend to fork the GUI in a seperate process? Can i spawn actors on different RT priority threads?

EDIT: I find the spawn option detached. Are the spawned actors (childs of a detached actor) on the same thread?


Solution

  • The current state is: I have one big global message queue where my systems (aka actors) subscribe to get their messages. They respond with messages to that global queue.

    Right now my systems don't need to know the receivers of their messages, because the receivers register for their wanted ones.

    CAF has publish/subscribe groups that seem to be a good fit here. Consumers simply join a well-known group and producers send to it. This gives you exactly the decoupling of senders and receivers you are looking for.

    When some fatal things happens or the system Needs to shut down, i send a message and all systems shut down and all threads get joined.

    There are two ways to achieve this easily. One is to use the group, but that requires that all your actors are subscribed to it when fatal system state is detected. Alternatively, you could use a single "root" actor to spawn all other actors and always use the linked flag during spawn. In this way, killing the root actor will recursively kill its children.

    How can i seperate the GUI actor/thread from the RT thread in libcaf? Would you recommend to fork the GUI in a seperate process?

    In 0.14, you will have to move the GUI to its own process and then connect to it via remote_actor. As a side effect, this decouples the GUI from the application logic and crashes in the GUI don't affect other parts of your system. Of course you pay for localhost communication and serialization in this scenario.

    With the upcoming 0.15, you could also use different actor_system instances with separated schedulers. This could save you a bit of overhead, but I would still prefer to move the GUI to its own process.

    By the way, you don't need to actually use fork. You could simply run your application, publish one actor to a port and then connect your GUI via remote_actor.

    I find the spawn option detached. Are the spawned actors (childs of a detached actor) on the same thread?

    A detached actor will always run in its own thread.

    Can i spawn actors on different RT priority threads?

    Short answer: no. CAF uses the std::thread interface, which is portable but simply does not support RT priorities. Adding priority-flags when detaching actors is doable, but platform-specific features like that are not on our todo list.

    That being said, we would of course accept patches to CAF that add RT priority support.