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