1 /*
2  * The MIT License (MIT)
3  *
4  * Copyright (c) 2014 Richard Andrew Cattermole
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in all
14  * copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24 module dakka.base.impl.local;
25 import dakka.base.impl.defs;
26 import dakka.base.defs;
27 
28 pure string generateFuncLocalHandler(T : Actor, string m)() {
29 	import std.traits : ReturnType;
30 	enum T t = T.init;
31 
32 	string ret;
33 	ret ~= "            synchronized(localRef) {\n";
34 
35 	ret ~= "                if(supervisor !is null && !isAlive_) {\n";
36 	ret ~= "                    if ((supervisor.isLocalInstance && supervisor.isAlive_ && !supervisor.isDying_) || (!supervisor.isLocalInstance && getDirector().validAddressIdentifier((cast(ActorRef!(Actor))supervisor).remoteAddressIdentifier))) {\n";
37 	ret ~= "                        (cast()supervisor).onChildError(this, \"Node instance is on a remote server. But it has been disconnected.\");\n";
38 	ret ~= "                    } else {\n";
39 	ret ~= "                        die();\n";
40 	ret ~= "                    }\n";
41 	ret ~= "                }\n";
42 
43 	static if (hasReturnValue!(T, m)) {
44 		// this shouldn't be pushed into a new thread. Blocks because we have a return type.
45 		ret ~= "                try {\n";
46 		ret ~= "                    return localRef." ~ m ~ "(" ~ generateFuncCall!(T, m) ~ ");\n";
47 		ret ~= "                } catch(Exception e) {\n";
48 		ret ~= "                    if(supervisor !is null) {\n";
49 		ret ~= "                        if (supervisor.isLocalInstance || (!supervisor.isLocalInstance && getDirector().validAddressIdentifier((cast(ActorRef!(Actor))supervisor).remoteAddressIdentifier))) {\n";
50 		ret ~= "                            (cast()supervisor).onChildError(this, e.toString());\n";
51 		ret ~= "                        } else {\n";
52 		ret ~= "                            die();\n";
53 		ret ~= "                        }\n";
54 		ret ~= "                    }\n";
55 		ret ~= "                    return " ~ typeText!(ReturnType!(mixin("t." ~ m))) ~ ".init;\n";
56 		ret ~= "                }\n";
57 	} else {
58 		// with a void return type, we want to push this into another thread. Asynchronous because we don't have a return type. No point blocking is there?
59 		ret ~= "                runTask({\n";
60 		ret ~= "                    try {\n";
61 		ret ~= "                        localRef." ~ m ~ "(" ~ generateFuncCall!(T, m) ~ ");\n";
62 		ret ~= "                    } catch(Exception e) {\n";
63 		ret ~= "                        if(supervisor !is null) {\n";
64 		ret ~= "                            if (supervisor.isLocalInstance || (!supervisor.isLocalInstance && getDirector().validAddressIdentifier((cast(ActorRef!(Actor))supervisor).remoteAddressIdentifier))) {\n";
65 		ret ~= "                                (cast()supervisor).onChildError(this, e.toString());\n";
66 		ret ~= "                            } else {\n";
67 		ret ~= "                                die();\n";
68 		ret ~= "                            }\n";
69 		ret ~= "                        }\n";
70 		ret ~= "                    }\n";
71 		ret ~= "                });\n";
72 	}
73 	
74 	ret ~= "            }\n";
75 	return ret;
76 }