-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathChannel.hpp
More file actions
102 lines (81 loc) · 2.15 KB
/
Copy pathChannel.hpp
File metadata and controls
102 lines (81 loc) · 2.15 KB
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
#ifndef CHANNEL_HPP
#define CHANNEL_HPP
#include <stdexcept>
#include <errno.h>
#include <sys/neutrino.h>
#include "MessageType.hpp"
#include "Settings.hpp"
// #include <cstdint>
// Type T must have public field messageId
template<typename T, size_t T_size = sizeof(T)>
class Channel {
union {
int channel_id;
int connection_id;
} channel;
bool active_send;
bool active_receive;
bool owner;
void assert_permission_to_receive() {
if(!active_receive) {
throw std::runtime_error("Receiving is blocked.");
}
}
void assert_permission_to_send() {
if(!active_send) {
throw std::runtime_error("Sending is blocked.");
}
}
public:
Channel()
: active_send(false), active_receive(true), owner(true) {
if((channel.channel_id = ChannelCreate()) < 0) {
throw std::runtime_error("Can't create channel.");
}
active = true;
}
Channel(int ch_id, pid_t pid)
: channel_id(ch_id)
, active_send(true)
, active_receive(false)
, owner(false) {
int res = ConnectAttach(0, ch_id, pid, 0, 0);
if(res == -1) {
throw std::runtime_error("Can't connect to channel.");
}
channel.connection_id = res;
}
~Channel() {
if(owner) {
ChannelDestroy(channel.channel_id);
} else {
ConnectDetach(channel.connection_id);
}
}
int getChannelId() const { return channel_id; }
void receive(T& msg) const {
assert_permission_to_receive();
int msgId = MsgReceive(channel.channel_id, &msg, T_size. nullptr);
if(msgId < 0) {
throw std::runtime_error("Error while receiving message.");
}
if(msgId == 0) {
msg.messageId = 0;
return;
}
msg.messageId = msgId;
}
void send(const T& outMsg, T& inMsg) const {
assert_permission_to_send();
int result = MsgSend(channel.connection_id, (void*)outMsg, T_size,
(void*)inMsg, T_size);
if(result == MessageType::ERROR) {
inMsg.message[::MESSAGE_LENGTH-1] = 0; // na wszelki wyp.
throw std::runtime_error(inMsg.message);
}
}
void respond(const T& msg) const {
MsgReply(msg.messageId, msg.messageType, (void*)msg, T_size);
}
};
#endif // CHANNEL_HPP