132
|
1 /*******************************************************************************
|
|
2
|
|
3 copyright: Copyright (c) 2007 Tango. All rights reserved
|
|
4
|
|
5 license: BSD style: $(LICENSE)
|
|
6
|
|
7 version: April 2007: Initial release
|
|
8
|
|
9 author: h3r3tic, Kris
|
|
10
|
|
11 *******************************************************************************/
|
|
12
|
|
13 module tango.net.cluster.NetworkCall;
|
|
14
|
|
15 private import tango.core.Traits;
|
|
16 private import tango.core.Thread;
|
|
17
|
|
18 private import tango.net.cluster.NetworkMessage;
|
|
19
|
|
20 protected import tango.io.protocol.model.IReader,
|
|
21 tango.io.protocol.model.IWriter;
|
|
22
|
|
23 protected import tango.net.cluster.model.IChannel;
|
|
24
|
|
25
|
|
26 /*******************************************************************************
|
|
27
|
|
28 task harness, for initiating the send
|
|
29
|
|
30 *******************************************************************************/
|
|
31
|
|
32 class NetworkCall : NetworkMessage
|
|
33 {
|
|
34 /***********************************************************************
|
|
35
|
|
36 ***********************************************************************/
|
|
37
|
|
38 void send (IChannel channel = null)
|
|
39 {
|
|
40 if (channel)
|
|
41 channel.execute (this);
|
|
42 else
|
|
43 {
|
|
44 auto x = cast(IChannel) Thread.getLocal(0);
|
|
45 if (x)
|
|
46 x.execute (this);
|
|
47 else
|
|
48 execute;
|
|
49 }
|
|
50 }
|
|
51 }
|
|
52
|
|
53
|
|
54 /*******************************************************************************
|
|
55
|
|
56 Template for RPC glue
|
|
57
|
|
58 *******************************************************************************/
|
|
59
|
|
60 class NetCall(alias realFunc) : NetworkCall
|
|
61 {
|
|
62 alias ParameterTupleOf!(realFunc) Params;
|
|
63 alias ReturnTypeOf!(realFunc) RetType;
|
|
64
|
|
65 static if (!is(RetType == void)) {
|
|
66 RetType result;
|
|
67 }
|
|
68 Params params;
|
|
69
|
|
70
|
|
71 override char[] toString() {
|
|
72 return signatureOfFunc!(realFunc);
|
|
73 }
|
|
74
|
|
75 RetType opCall(Params params, IChannel channel = null) {
|
|
76 foreach (i, _dummy; this.params) {
|
|
77 this.params[i] = params[i];
|
|
78 }
|
|
79 send (channel);
|
|
80
|
|
81 static if (!is(RetType == void)) {
|
|
82 return result;
|
|
83 }
|
|
84 }
|
|
85
|
|
86 override void execute() {
|
|
87 static if (!is(RetType == void)) {
|
|
88 result = realFunc(params);
|
|
89 } else {
|
|
90 realFunc(params);
|
|
91 }
|
|
92 }
|
|
93
|
|
94 override void read(IReader input) {
|
|
95 static if (!is(RetType == void)) {
|
|
96 input(result);
|
|
97 }
|
|
98 foreach (i, _dummy; params) input(params[i]);
|
|
99 }
|
|
100
|
|
101 override void write(IWriter output) {
|
|
102 static if (!is(RetType == void)) {
|
|
103 output(result);
|
|
104 }
|
|
105 foreach (i, _dummy; params) output(params[i]);
|
|
106 }
|
|
107 }
|
|
108
|
|
109
|
|
110 /*******************************************************************************
|
|
111
|
|
112 Magic to get a clean function signature
|
|
113
|
|
114 *******************************************************************************/
|
|
115
|
|
116 private {
|
|
117 struct Wrapper(alias fn) {}
|
|
118 const char[] WrapperPrefix = `__T7Wrapper`;
|
|
119
|
|
120
|
|
121 uint parseUint(char[] str) {
|
|
122 int res = 0;
|
|
123 foreach (c; str) {
|
|
124 res *= 10;
|
|
125 res += c - '0';
|
|
126 }
|
|
127 return res;
|
|
128 }
|
|
129
|
|
130
|
|
131 char[] sliceOffSegment(inout char[] str) {
|
|
132 assert (str.length > 0 && str[0] >= '0' && str[0] <= '9');
|
|
133
|
|
134 int lenEnd = 0;
|
|
135 for (; str[lenEnd] >= '0' && str[lenEnd] <= '9'; ++lenEnd) {}
|
|
136
|
|
137 char[] lenStr = str[0..lenEnd];
|
|
138 uint segLen = parseUint(lenStr);
|
|
139 str = str[lenEnd .. $];
|
|
140
|
|
141 char[] res = str[0..segLen];
|
|
142 str = str[segLen .. $];
|
|
143 return res;
|
|
144 }
|
|
145
|
|
146
|
|
147 char[] digOutWrapper(char[] wrapped) {
|
|
148 wrapped = wrapped[1..$]; // skip the 'S'
|
|
149 char[] seg;
|
|
150
|
|
151 do {
|
|
152 seg = sliceOffSegment(wrapped);
|
|
153 } while (seg.length < WrapperPrefix.length || seg[0..WrapperPrefix.length] != WrapperPrefix);
|
|
154
|
|
155 return seg[WrapperPrefix.length .. $];
|
|
156 }
|
|
157
|
|
158
|
|
159 char[] demangleDFunc(char[] mangled) {
|
|
160 char[] res = sliceOffSegment(mangled);
|
|
161
|
|
162 while (mangled.length > 0 && mangled[0] >= '0' && mangled[0] <= '9') {
|
|
163 res ~= '.' ~ sliceOffSegment(mangled);
|
|
164 }
|
|
165 return res;
|
|
166 }
|
|
167
|
|
168
|
|
169 char[] nameOf_impl(char[] wrapped) {
|
|
170 char[] wrapper = digOutWrapper(wrapped)[1..$]; // skip the 'S'
|
|
171 char[] mangled = sliceOffSegment(wrapper);
|
|
172
|
|
173 if (mangled.length > 2 && mangled[0..2] == `_D`) {
|
|
174 // D func
|
|
175 return demangleDFunc(mangled[2..$]);
|
|
176 } else {
|
|
177 return mangled; // C func
|
|
178 }
|
|
179 }
|
|
180
|
|
181
|
|
182 int match_param_(char[] str) {
|
|
183 if (str.length < `_param_0`.length) return 0;
|
|
184
|
|
185 int numDigits = 0;
|
|
186 while (str[$-1-numDigits] >= '0' && str[$-1-numDigits] <= '9') {
|
|
187 ++numDigits;
|
|
188 }
|
|
189
|
|
190 if (0 == numDigits) return 0;
|
|
191
|
|
192 if (str.length >= `_param_`.length + numDigits && str[$-`_param_`.length-numDigits .. $-numDigits] == `_param_`) {
|
|
193 return `_param_`.length + numDigits;
|
|
194 } else {
|
|
195 return 0;
|
|
196 }
|
|
197 }
|
|
198
|
|
199
|
|
200 // sometimes the param lists have ugly _param_[0-9]+ names in them...
|
|
201 char[] tidyTupleStringof(char[] str) {
|
|
202 char[] res;
|
|
203 for (int i = 0; i < str.length; ++i) {
|
|
204 char c = str[i];
|
|
205
|
|
206 if (c == ')' || c == ',') {
|
|
207 if (auto len = match_param_(str[0..i])) {
|
|
208 // len is the length of the _param_[0-9]+ thing
|
|
209 int start = i-1-len;
|
|
210 str = str[0..start] ~ str[i..$];
|
|
211 i -= len;
|
|
212 }
|
|
213 }
|
|
214 }
|
|
215
|
|
216 return str;
|
|
217 }
|
|
218
|
|
219
|
|
220 template nameOfFunc(alias fn) {
|
|
221 static assert (is(typeof(fn) == function));
|
|
222 const char[] nameOfFunc = nameOf_impl((Wrapper!(fn)).mangleof);
|
|
223 }
|
|
224
|
|
225
|
|
226 template signatureOfFunc(alias fn) {
|
|
227 static assert (is(typeof(fn) == function));
|
|
228 const char[] signatureOfFunc = ReturnTypeOf!(fn).stringof ~ ' ' ~ nameOfFunc!(fn) ~ tidyTupleStringof(ParameterTupleOf!(fn).stringof);
|
|
229 }
|
|
230 } |