RPC and Dynamic function call
Rory McGuire
rjmcguire at gmail.com
Sun Nov 22 23:45:32 PST 2009
"Denis Koroskin" <2korden at gmail.com> wrote:
> On Sat, 21 Nov 2009 12:42:35 +0300, Rory McGuire <rjmcguire at gmail.com>
> wrote:
>
>> "Denis Koroskin" <2korden at gmail.com> wrote:
>>
>>> "Denis Koroskin" <2korden at gmail.com> wrote:
>>> ...
>>
>> cut
>>
>>> ...
>>
>>
>> Why did you use asm etc...?
>>
>> I made a de/serializer that just uses templates and static ifs.
>>
>> it doesn't do serialization of delegates etc... but I don't know that
>> moving executable code across would be safe (I think java can do it,
>> but then it has a vm).
>>
>> mine does:
>> int, long, double, string, object, struct.
>>
>> I can post the code if you want. So far I have only used it to present
>> the methods of an object as a kind of server, with a client being able
>> to connect to it.
>>
>> Was inspired by hessiand on dsource.org.
>>
>> Can post code if you would like to see. I posted the automatic object
>> wrapping code a couple of days ago as a simple example of template
>> usage Thread: "Metaprogramming in D: Some real world examples".
>>
>> -Rory
>>
>
> You missed the point. I only used asm to invoke function on remote side.
> Serialization is done purely with templates.
>
:) I thought I had missed the point thats why I asked :D.
On the Server side I used a similar method that the guy who wrote hessiand used
for calling the objects methods, my code:
module servers.ObjectSocketServer;
//import serialize.ISerializer;
import transports.ITransport;
import transports.SocketTransport;
import tango.core.Exception;
version (Tango) {
alias char[] string;
import tango.net.Socket;
import tango.io.Stdout;
import tango.core.Traits;
// alias ParameterTupleOf ParameterTypeTuple;
}
class ObjectSocketServer(T,C) {
Socket request_conn;
T serializer;
ITransport transport;
C instance;
IMethod[string] methods;
this(Socket request_conn) {
instance = new C();
transport = new SocketTransport(request_conn);
serializer = new T(transport);
this.request_conn = request_conn;
}
~this() {
request_conn = null;
serializer = null;
transport = null;
foreach (key, method; methods) {
methods.remove(key);
}
instance = null;
}
void close() {
try {
if (request_conn !is null) {
request_conn.shutdown(SocketShutdown.BOTH);
request_conn.detach();
}
} catch (Exception e) {}
}
/+ void expose(char[] method)() {
pragma(msg, mixin(MethodType_mixin!(method)()));
} +/
void expose(alias M)() {
const string name = NameOfFunc!(M);
//pragma(msg, "expose: "~ name);
pragma(msg, "expose:\n"~ GenMethod!(C, name));
methods[name] = mixin(GenMethod!(C, name));
}
void run() {
scope(exit) close();
try {
Stdout("run").newline;
int i;
while (true) {
//Stdout("again").newline;
auto method = serializer.read!(string)();
//Stdout("method = "~ method).newline;
try {
if (!(method in methods))
throw new Exception("Not Found");
methods[method](serializer, instance);
} catch (Exception e) {
e.writeOut((char[] str) { Stdout(str).newline;});
Stdout("Caught exception must serialize: ")(e.line)(":")
(e.file)(" ")(e.toString).newline;
}
Stdout(i)("\r")();
i++;
}
Stdout().newline;
} catch (Exception e) {
Stdout("Caught exception: ")(e.toString).newline;
}
}
interface IMethod {
string getName();
void opCall(T, C);
}
}
// this would be inside the class but cant be
string GenMethod(alias C, string name)() {
string ret = "new class IMethod {\n";
ret ~= "\tstring getName() { return \""~ name ~"\"; }\n";
ret ~= "\tvoid opCall(T serializer, C instance) {\n";
ret ~= "\t\tserializer.write(instance."~name~"(serializer.read!
("~ParameterTupleOf!(mixin(MethodType_mixin!(name)()))[0].stringof~")()));\n";
foreach (i,p; ParameterTupleOf!(mixin(MethodType_mixin!(name)()))[1..$]) {
ret ~= "\t\tserializer.write(instance."~name~"(serializer.read!
("~p.stringof~")()));\n";
}
ret ~= "\t\tserializer.getTransport().flush();\n";
ret ~= "\t}\n";
ret ~= "}\n";
return ret;
}
public template NameOfFunc(alias f) {
version (LDC) {
const char[] NameOfFunc = (&f).stringof[1 .. $];
} else {
const char[] NameOfFunc = (&f).stringof[2 .. $];
}
}
string MethodType_mixin(string method)() {
return "typeof(&C.init."~ method ~")";
}
More information about the Digitalmars-d
mailing list