-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsilnia.c
151 lines (117 loc) · 3.35 KB
/
silnia.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#include "cacti.h"
#define MESSAGES 4
#define MSG_HELLO_BACK 1
#define MSG_ASSIGN_VALUE 2
#define MSG_KILL 3
typedef struct value_data {
int curr;
int n;
int result;
actor_id_t first_actor;
actor_id_t next_actor;
role_t* role;
} value_data_t;
void silnia_hello(void **stateptr __attribute__((unused)), size_t nbytes __attribute__((unused)), void* data) {
actor_id_t prev_actor = (actor_id_t)data;
if (prev_actor == actor_id_self()) {
// first actor from system
return;
}
actor_id_t* my_id = malloc(sizeof(actor_id_t));
if (my_id == NULL) {
syserr("malloc");
}
*my_id = actor_id_self();
message_t msg_hello_back = {
.message_type = MSG_HELLO_BACK,
.data = my_id
};
send_message(prev_actor, msg_hello_back);
}
void silnia_hello_back(void **stateptr __attribute__((unused)), size_t nbytes __attribute__((unused)), void* data) {
value_data_t* value_data = *stateptr;
actor_id_t next_actor = *(actor_id_t*)data;
free(data);
value_data_t* next_data = malloc(sizeof(value_data_t));
if (next_data == NULL) {
syserr("malloc");
}
*next_data = *value_data;
next_data->curr++;
value_data->next_actor = next_actor;
message_t msg_assign_value = {
.message_type = MSG_ASSIGN_VALUE,
.data = next_data
};
send_message(next_actor, msg_assign_value);
}
void silnia_assign_value(void **stateptr, size_t nbytes __attribute__((unused)), void* data) {
*stateptr = data;
value_data_t* value_data = *stateptr;
value_data->result *= value_data->curr;
if (value_data->curr == value_data->n) {
printf("%d\n", value_data->result);
message_t msg_kill = {
.message_type = MSG_KILL,
};
send_message(value_data->first_actor, msg_kill);
}
else {
message_t msg_spawn = {
.message_type = MSG_SPAWN,
.data = value_data->role
};
send_message(actor_id_self(), msg_spawn);
}
}
void silnia_kill(void **stateptr, size_t nbytes __attribute__((unused)), void* data __attribute__((unused))) {
value_data_t* value_data = *stateptr;
actor_id_t next_actor = value_data->next_actor;
bool last = value_data->curr == value_data->n;
free(value_data);
message_t msg_godie = {
.message_type = MSG_GODIE
};
send_message(actor_id_self(), msg_godie);
if (!last) {
message_t msg_kill = {
.message_type = MSG_KILL
};
send_message(next_actor, msg_kill);
}
}
int main() {
int n;
scanf("%d", &n);
actor_id_t first_actor;
// role
const size_t nprompts = MESSAGES;
void (**prompts)(void **, size_t, void *) = malloc(sizeof(void *) * nprompts);
prompts[0] = &silnia_hello;
prompts[MSG_HELLO_BACK] = &silnia_hello_back;
prompts[MSG_ASSIGN_VALUE] = &silnia_assign_value;
prompts[MSG_KILL] = &silnia_kill;
role_t role = {
.nprompts = nprompts,
.prompts = prompts
};
// create first actor
actor_system_create(&first_actor, &role);
value_data_t* first_data = malloc(sizeof(value_data_t));
if (first_data == NULL) {
syserr("malloc");
}
first_data->n = n;
first_data->curr = 1;
first_data->result = 1;
first_data->role = &role;
first_data->first_actor = first_actor;
message_t msg_assign_value = {
.message_type = MSG_ASSIGN_VALUE,
.data = first_data
};
send_message(first_actor, msg_assign_value);
actor_system_join(first_actor);
free(prompts);
return 0;
}