Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Activity
Dominik Charousset
@Neverlord
You can watch the metrics to see how many actors are currently running.
Even without setting up Prometheus, just configuring CAF to export metrics and then using curl manually works for an ad-hoc analysis.
Dmitriy Inyutin
@Kadzugi_gitlab
@Neverlord Hello Dominik, at the moment we are moving from the old version CAF 0.17.4 to the latest one and rewriting the tests (CAF_TEST), I would like to know what needs to be done now instead of the following:
using init_atom = atom_constant<atom("init")>;
using calc_atom = atom_constant<atom("calc")>;
using wait_atom = atom_constant<atom("wait")>;
Dominik Charousset
@Neverlord

@Kadzugi_gitlab the new pattern matching with 0.18 uses type IDs. Atoms still kinda exist, but they are simple, empty structs now. Basically:

CAF_BEGIN_TYPE_ID_BLOCK(my_types, caf::first_custom_type_id)
  CAF_ADD_ATOM(my_types, my_ns, init_atom)
  CAF_ADD_ATOM(my_types, my_ns, calc_atom)
  CAF_ADD_ATOM(my_types, my_ns wait_atom)
CAF_END_TYPE_ID_BLOCK(my_types)

This gives you the atom types my_ns::init_atom, etc. To obtain a value, just type my_ns::init_atom_v. You can also leave out the namespace if you wish. The new types must be registered at runtime, or you will most likely run into segfaults. Have a look at https://github.com/actor-framework/actor-framework/blob/master/examples/custom_type/custom_types_1.cpp. If you're not using the CAF_MAIN macro, you'll need to call something like:

    caf::init_global_meta_objects<caf::id_block::my_types>();
    caf::core::init_global_meta_objects();

Loading the middleman requires calling caf::io::init_global_meta_objects.

Hope that gets you started. The transition to 0.18 is a big one, but it's been worth it. 🙂

patszt
@patszt

Hi, i am wondering if i understand the new type inspection correctly.
Currently it is called like so:
f(caf::meta::type_name("type"), x);
Is there a difference between
f.object(x).pretty_name("type"); f.apply(x);

and

f.object(x).pretty_name("type").fields(f.field("x", x));

If i understood it correctly the second version will also be human readable if needed.

Dominik Charousset
@Neverlord
I'm not sure when this code would work. What type is x?
patszt
@patszt

It's a custom struct with it's own inspect overload. We could assume it contains std::string inside

The first example is the current use case in CAF 17.6

Dominik Charousset
@Neverlord
If you want to "unbox" that type during serialization (have your struct appear like an ordinary string), just do f.apply(x.str), otherwise f.object(x).fields(f.field("str", x.str));.
The new inspection exposes much more information about the structure of your type. This allows things like automatic conversion to and from JSON.
patszt
@patszt
And is there any overhead for using the fields version? I suppose there must be?
Dominik Charousset
@Neverlord
CAF does not support versioning. You can introduce new fields, but only as long as they are optional.
And "introduce" in the sense that: you'll be able to read old versions from things like JSON files. When connecting CAF nodes, the type information on all nodes must be identical (same as pre 0.18).
Dominik Charousset
@Neverlord
Ah, you haven't been talking about versioning of fields, did you? :D
The overhead boils down to the serializer you're using. In general, things like the binary serializer ignore the field information and you "pay" for two functions calls that the compiler most likely inlines and optimizes away. For a generic serializer, these function calls will be virtual, but then you most likely have something like a JSON serializer that actually needs the field information and does something with it.
1 reply
In case you didn't already find them, these are some "motivational examples" what's possible with the new type inspection: https://www.cafcademy.com/gems/json-serialization and https://www.cafcademy.com/gems/hashing.
Dmitriy Inyutin
@Kadzugi_gitlab

@Neverlord Hello Dominik, we continue to rewrite tests for version 0.18.6. Another question appeared, when connecting file caf/test/unit_test_impl.hpp, connection code:

#define CAF_SUITE main_test
#include <caf/test/unit_test_impl.hpp>

CAF_TEST(main) {
  CAF_CHECK_EQUAL(1, 1);
}

the following errors occur:

1) package\9e2288acb3ac24a42092c8fd8c34ee883b3fb639\include\caf/test/unit_test_impl.hpp(660,8): error C2039: 'core': is not a member of 'caf'
2) package\9e2288acb3ac24a42092c8fd8c34ee883b3fb639\include\caf/test/unit_test_impl.hpp(30): message : see declaration of 'caf' 
3) package\9e2288acb3ac24a42092c8fd8c34ee883b3fb639\include\caf/test/unit_test_impl.hpp(660,8): error C3083: 'core': the symbol to the left of a '::' must be a type 
4) package\9e2288acb3ac24a42092c8fd8c34ee883b3fb639\include\caf/test/unit_test_impl.hpp(660,14): error C2039: 'init_global_meta_objects': is not a member of 'caf'

Can you please tell me what the problem is?

Dominik Charousset
@Neverlord
Seems like you're missing #include "caf/init_global_meta_objects.hpp"
Dmitriy Inyutin
@Kadzugi_gitlab
@Neverlord thanks, let's try it now
Dominik Charousset
@Neverlord
Do you have any custom types in your system?
I'd generally suggest not relying on the default main anymore.
This is how we set up our binaries as of 0.18. The gist is, setting #define CAF_TEST_NO_MAIN before including the impl header and then initialize the type-id table according to your needs.
Dmitriy Inyutin
@Kadzugi_gitlab
Yes, they are used, now let's see an example, thanks
newjames1988
@newjames1988
Hi, I am new to CAF. i want to use it for my simulator project. I want to control the execution order of the node. is it possible to control execution order of node ?
Dominik Charousset
@Neverlord
What do you mean by execution order? Messages on an actor or what actors run in which order?
newjames1988
@newjames1988
actor run order
Dominik Charousset
@Neverlord
May I ask why? :)
newjames1988
@newjames1988
image.png
Dominik Charousset
@Neverlord
So, you want an update from all sensors before calculating the next output?
newjames1988
@newjames1988
Yes
one reason is as follows. My architecture is that one Node will be one Actor. Each node simulation of that part of a robot. Like dynamic behaviour will generate the data, which will fed into another sensor modelling and henceforth. Some sensor output frequency is not the same as others for that time step not to run that Node but use its previous data . We cannot run any control algorithm before getting the data from the sensor.
Dominik Charousset
@Neverlord
If each block is one actor, then I would recommend simply waiting in the ControlAlgo actor until it has all inputs available. Either by simply waiting for three messages or by looking at the sender for each message (this way, a sensor that triggers twice for whatever reason could 'override' its previous input and wouldn't be mistaken for the input for another sensor).
There is a deterministic scheduler in CAF, but you'd throw away all concurrency in your system and it's very easy to shoot yourself in the foot with that (it's mostly meant for unit testing).
Since the sensors trigger at different rates, the most simple solution would be having something like map<strong_actor_ptr, value_type> and run the algorithm whenever you have three entries after receiving something (and override the entry for the sender otherwise).
newjames1988
@newjames1988
simply waiting for three messages or by looking at the sender for each message (this way, a sensor that triggers twice for whatever reason could 'override' its previous input and wouldn't be mistaken for the input for another sensor). I will try to use this .
thanks for reply
Dylan Baros
@dylan-baros
Good morning. Is there anyone here who could assist with a windows install? I run cmake .. in the build folder and the project files are all built in the root directory. I then go to the root directory and run cmake --build . and everything seems to build but If I try to run any of the examples .exe files they can't find any of the dlls.
Dominik Charousset
@Neverlord
I suppose you figured it out yourself? actor-framework/actor-framework#1354 :)
If you don't want to deal with shared libraries in the first place and prefer statically linked binaries, you can set --disable-shared-libs (configure script) or BUILD_SHARED_LIBS=OFF (CMake).
Dylan Baros
@dylan-baros
@Neverlord yes thanks. I have never played with windows libraries before but figured out.
Marco Leclerc
@ke9
Hi all, need some help/clarification regarding message_priority before I fill an issue in github. Let's say I send a bunch of high priority messages to an actor, and then a normal priority message... is it by design that a normal priority message will be processed before all high priority messages already in the actor's mailbox? From the documentation: "Urgent messages are put into a different queue of the receiver’s mailbox", I would expect that all queued high priority messages be processed before any new messages are sent to an actor. It used to work in the past (don't remember how long ago), some of our unit tests are failing now with CAF 0.18.5 . thanks for any help/hints !
Dominik Charousset
@Neverlord
@ke9 Actors draw from both queues. They first check the high-priority queue and consume messages up to a maximum. Then they look into the default queue, again consuming up to a maximum of messages. Rince and repeat. Actors will consume more messages from their high-priority queue overall, but the reasoning here is to avoid scenarios where an actor would make no progress at all on its regular messages for a long time if there's a burst of high-priority messages coming in.
Marco Leclerc
@ke9

@Neverlord Hi thanks for the clarification, makes sense to give actor the chance to process all messages, we do the same at a higher level. We will adapt our design accordingly. Would be interesting to document this behavior a little bit in the user manual. On my test (windows box, x64 release) , I send a bunch of high priority messages, then a bunch of normal priority messages and the actor eventually processes 9 high priority messages for 3 normal priority messages (3 to 1 ratio), until the test finishes.
caf::message_priority::high : 1444419
caf::message_priority::normal : 3
caf::message_priority::high : 9
caf::message_priority::normal : 3
caf::message_priority::high : 9
caf::message_priority::normal : 3
caf::message_priority::high : 9
caf::message_priority::normal : 3

Have a nice day!

Dominik Charousset
@Neverlord
Yeah, the docs should definitely mention that! Have nice day as well. 🙂
Dylan Baros
@dylan-baros

I am having an issue where my project builds on linux but does not build on Windows with cmake. Here is the error:

[main] Building folder: POC
[build] Starting build
[proc] Executing command: C:\src\vcpkg\downloads\tools\cmake-3.24.0-windows\cmake-3.24.0-windows-i386\bin\cmake.EXE --build c:/Users/dbaros/Documents/POC_example/POC/build --config Debug --target ALL_BUILD -j 6 --
[build] MSBuild version 17.3.1+2badb37d1 for .NET Framework
[build] duck_classes.vcxproj -> C:\Users\dbaros\Documents\POC_example\POC\build\source\DuckClasses\Debug\duck_classes.lib
[build] libcaf_core.vcxproj -> C:\Users\dbaros\Documents\POC_example\POC\build_deps\caf-build\libcaf_core\Debug\caf_core.lib
[build] main.cpp
[build] C:\Users\dbaros\Documents\POC_example\POC\build_deps\caf-src\libcaf_core\caf/mixin/sender.hpp(73,19): error C2338: static_assert failed: 'at least one type has no ID, did you forgot to announce it via CAF_ADD_TYPE_ID?' [C:\Users\dbaros\Documents\POC_example\POC\build\source\DuckParty\DuckParty.exe.vcxproj]
[build] C:\Users\dbaros\Documents\POC_example\POC\source\DuckParty/DuckActor.h(32): message : see reference to function template instantiation 'void caf::mixin::sender<B,D>::send<caf::message_priority::normal,DisplayActor,const display_behavior&,std::chrono::time_point<std::chrono::system_clock,std::chrono::duration<std::chrono::system_clock::rep,std::chrono::system_clock::period>>&,std::string&>(const Dest &,const display_behavior &,std::chrono::time_point<std::chrono::system_clock,std::chrono::duration<std::chrono::system_clock::rep,std::chrono::system_clock::period>> &,std::string &)' being compiled [C:\Users\dbaros\Documents\POC_example\POC\build\source\DuckParty\DuckParty.exe.vcxproj]
[build] with
[build] [
[build] B=caf::scheduled_actor,
[build] D=caf::typed_event_based_actor<caf::result<void> (do_duck_behavior)>,
[build] Dest=DisplayActor
[build] ]
[build] C:\Users\dbaros\Documents\POC_example\POC\source\DuckParty/DuckActor.h(32): message : see reference to function template instantiation 'void caf::mixin::sender<B,D>::send<caf::message_priority::normal,DisplayActor,const display_behavior&,std::chrono::time_point<std::chrono::system_clock,std::chrono::duration<std::chrono::system_clock::rep,std::chrono::system_clock::period>>&,std::string&>(const Dest &,const display_behavior &,std::chrono::time_point<std::chrono::system_clock,std::chrono::duration<std::chrono::system_clock::rep,std::chrono::system_clock::period>> &,std::string &)' being compiled [C:\Users\dbaros\Documents\POC_example\POC\build\source\DuckParty\DuckParty.exe.vcxproj]
[build] with
[build] [
[build] B=caf::scheduled_actor,
[build] D=caf::typed_event_based_actor<caf::result<void> (do_duck_behavior)>,
[build] Dest=DisplayActor
[build] ]
[proc] The command: C:\src\vcpkg\downloads\tools\cmake-3.24.0-windows\cmake-3.24.0-windows-i386\bin\cmake.EXE --build c:/Users/dbaros/Documents/POC_example/POC/build --config Debug --target ALL_BUILD -j 6 -- exited with code: 1 and signal: null
[build] Build finished with exit code 1

Any help would be appreciated
I give the types IDs and it works on linux.
Dominik Charousset
@Neverlord

There's not enough context to tell what's going wrong on MSVC. The static assert usually triggers when forgetting some includes, but that wouldn't explain why it worked for you on Linux.

Btw, if you're evaluating CAF on Windows: there's a performance issue that's been fixed recently actor-framework/actor-framework#1343.

Dylan Baros
@dylan-baros
@Neverlord thanks. So this is likely an include issue? Is there a difference between how the includes are handled on linux and windows?
Dominik Charousset
@Neverlord
It usually is a matter of not having the type ID block visible, but hard to tell without code.
Dylan Baros
@dylan-baros
I inherited this code so pardon my ignorance, but here is what they did, They used CAF_ADD_ATOM:
CAF_BEGIN_TYPE_ID_BLOCK(duck_msg_types, caf::first_custom_type_id)
CAF_ADD_ATOM(duck_msg_types, do_duck_behavior)
CAF_ADD_ATOM(duck_msg_types, display_behavior)
CAF_END_TYPE_ID_BLOCK(duck_msg_types)
Dylan Baros
@dylan-baros
@Neverlord I did not realize that you actually have seen this code before. I work at National Instruments where you have provided some support for a CAF based project. I posted my repo and question on stackoverflow and if you get a chance to look at it I would appreciate it. https://stackoverflow.com/questions/73901792/cant-compile-code-using-the-c-actor-framework-on-windows-using-cmake-works-o
patszt
@patszt

What is the proper syntax to pass std::vector<std::string> CLI arguments in 0.18.6?

--some-list-option=[\"a\"]

seems to work, but when i try to add the second entry
--some-list-option=[\"a\", \"b\"]
it fails with pec::invalid_argument.

This syntax is used in test/config_option_set.cpp