libactor is a simple C library that helps you build an application based on the Actor model. It is currently not supported on Windows. Any Linux/BSD should be fine, as long as it supports pthreads.
The library works great, but one caveat is that if one actor crashes – they all fall down. In a future release there will be sandboxing of each actor to provide better reliability.
Once you have installed libactor, you just have to link it to your application with the flag -lactor.
You must include <libactor/actor.h> in your project as well.
When sending a message, the type should be greater than 100, (anything below that may be used by the library).
Sends a message to an actor. type is a user defined value. data is a pointer to a block of data that will be sent to the actor.
Note: The data is copied before being sent to the actor. If you are passing a structure, make sure that it doesn’t contain any pointers to memory, as this can cause a crash. data should be a complete message, see Memory Management.
libactor uses pthreads for concurrency. If you allocate memory with malloc() and pass a pointer or try to access the memory in a different actor, your application may crash. Therefore, if you plan to send a message to another actor, make sure that the message is complete(no pointers, only raw data). See Example.
libactor provides some convenience functions for managing memory. Please use these in your actors. Reference counting is used to manage memory. When an actor exits, any unfreed memory will be automatically freed. (But you should still release anything you are not using).
This is okay:
struct user {
char *username;
char *password;
int status;
};
struct user usermsg;
// initialize usermsg here
actor_send_msg(5, 1, &usermsg, sizeof(struct user));
This is bad:
struct usr_login_info {
char *username;
char *password;
};
struct user {
struct usr_login_info *info;
int status;
};
struct user usermsg;
// initialize usermsg here
actor_send_msg(5, 1, &usermsg, sizeof(struct user));
In the bad example, the user struct will be copied, but the pointer to info may then be accessed by multiple actors.
Below is a simple example of how to use the actor library. One actor will be spawned which will then spawn another actor, send it a ping message, and loop.
main.c:
#include <stdio.h>
#include <libactor/actor.h>
ACTOR_FUNCTION(pong_func, args) {
actor_msg_t *msg;
while(1) {
msg = actor_receive();
if(msg->type == PING_MSG) {
printf("PING! ");
actor_reply_msg(msg, PONG_MSG, NULL, 0);
}
arelease(msg);
}
}
ACTOR_FUNCTION(ping_func, args) {
actor_msg_t *msg;
actor_id aid = spawn_actor(pong_func, NULL);
while(1) {
actor_send_msg(aid, PING_MSG, NULL, 0);
msg = actor_receive();
if(msg->type == PONG_MSG) printf("PONG!\n");
arelease(msg);
sleep(5);
}
}
ACTOR_FUNCTION(main_func, args) {
struct actor_main *main = (struct actor_main*)args;
int x;
/* Accessing the arguments passed to the application */
printf("Number of arguments: %d\n", main->argc);
for(x = 0; x < main->argc; x++) printf("Argument: %s\n", main->argv[x]);
/* PING/PONG example */
spawn_actor(ping_func, NULL);
}