forked from solidoss/solidframe
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathipcmessage.hpp
159 lines (127 loc) · 4.13 KB
/
ipcmessage.hpp
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
152
153
154
155
156
157
158
159
// solid/frame/ipc/ipcservice.hpp
//
// Copyright (c) 2007, 2008, 2013 Valentin Palade (vipalade @ gmail . com)
//
// This file is part of SolidFrame framework.
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.
//
#ifndef SOLID_FRAME_IPC_IPCMESSAGE_HPP
#define SOLID_FRAME_IPC_IPCMESSAGE_HPP
#include "solid/system/function.hpp"
#include "solid/system/common.hpp"
#include "solid/frame/ipc/ipccontext.hpp"
#include <memory>
#include <type_traits>
namespace solid{
namespace frame{
namespace ipc{
class Service;
class Connection;
enum struct MessageFlags: ulong{
FirstFlagIndex = 0, //for rezerved flags
WaitResponse = (1<<(FirstFlagIndex + 0)),
Synchronous = (1<<(FirstFlagIndex + 1)),
Idempotent = (1<<(FirstFlagIndex + 2)),
OneShotSend = (1<<(FirstFlagIndex + 3)),
StartedSend = (1<<(FirstFlagIndex + 4)),
DoneSend = (1<<(FirstFlagIndex + 5)),
Canceled = (1<<(FirstFlagIndex + 6)),
};
using MessageFlagsValueT = std::underlying_type<MessageFlags>::type;
inline MessageFlagsValueT operator|(const MessageFlagsValueT _v, const MessageFlags _f){
return _v | static_cast<MessageFlagsValueT>(_f);
}
inline MessageFlagsValueT operator&(const MessageFlagsValueT _v, const MessageFlags _f){
return _v & static_cast<MessageFlagsValueT>(_f);
}
inline MessageFlagsValueT& operator|=(MessageFlagsValueT & _rv, const MessageFlags _f){
_rv |= static_cast<MessageFlagsValueT>(_f);
return _rv;
}
inline MessageFlagsValueT operator|(const MessageFlags _f1, const MessageFlags _f2){
return static_cast<MessageFlagsValueT>(_f1) | static_cast<MessageFlagsValueT>(_f2);
}
struct Message: std::enable_shared_from_this<Message>{
static bool is_synchronous(const ulong _flags){
return (_flags & MessageFlags::Synchronous) != 0;
}
static bool is_asynchronous(const ulong _flags){
return (_flags & MessageFlags::Synchronous) == 0;
}
static bool is_waiting_response(const ulong _flags){
return (_flags & MessageFlags::WaitResponse) != 0;
}
static bool is_idempotent(const ulong _flags){
return (_flags & MessageFlags::Idempotent) != 0;
}
static bool is_started_send(const ulong _flags){
return (_flags & MessageFlags::StartedSend) != 0;
}
static bool is_done_send(const ulong _flags){
return (_flags & MessageFlags::DoneSend) != 0;
}
static bool is_canceled(const ulong _flags){
return (_flags & MessageFlags::Canceled) != 0;
}
static bool is_one_shot(const ulong _flags){
return (_flags & MessageFlags::OneShotSend) != 0;
}
Message(uint8_t _state = 0):stt(_state){}
Message(Message const &_rmsg): requid(_rmsg.requid), stt(_rmsg.stt){}
virtual ~Message();
bool isOnSender()const{
return stt == 0;
}
bool isOnPeer()const{
return stt == 1;
}
bool isBackOnSender()const{
return stt == 2;
}
uint8_t state()const{
return stt;
}
RequestId const& requestId()const{
return requid;
}
template <class S>
void serialize(S &_rs, frame::ipc::ConnectionContext &_rctx){
if(S::IsSerializer){
//because a message can be sent to multiple destinations (usign DynamicPointer)
//on serialization we cannot use/modify the values stored by ipc::Message
//so, we'll use ones store in the context. Because the context is volatile
//we'll store as values.
_rs.pushCrossValue(_rctx.request_id.index, "requid_idx");
_rs.pushCrossValue(_rctx.request_id.unique, "requid_idx");
_rs.pushValue(_rctx.message_state, "state");
}else{
_rs.pushCross(requid.index, "requid_idx");
_rs.pushCross(requid.unique, "requid_uid");
_rs.push(stt, "state");
}
}
template <class S, class T>
static void serialize(S &_rs, T &_rt, const char *_name){
//here we do only pushes so we can have access to context
//using the above "serialize" function
_rs.push(_rt, _name);
_rs.push(static_cast<Message&>(_rt), "message_base");
}
private:
friend class Service;
friend class TestEntryway;
friend class Connection;
void adjustState(){
if(stt == 3) stt = 0;
}
private:
RequestId requid;
uint8_t stt;
};
using MessagePointerT = std::shared_ptr<Message>;
}//namespace ipc
}//namespace frame
}//namespace solid
#endif