2 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
5 Desc: Class for proxy objects.
9 #include <proto/exec.h>
10 #include <exec/memory.h>
11 #include <proto/oop.h>
12 #include <proto/utility.h>
14 #include <oop/proxy.h>
15 #include <oop/server.h>
25 #include <aros/debug.h>
27 #define OOPBase (GetOBase(((OOP_Class *)cl)->UserData))
29 /* This proxyclass is used to create a proxy object for
30 another object owned by another process. You can then call
31 methods on the object through the proxy, using IPC.
32 This makes methodcalls threadsafe.
34 Note the API of this class sucks (It's not OS-independent).
35 This implementation is mainly there to show that the idea works.
41 /* The object this is a proxy for */
42 OOP_Object
*RealObject
;
44 /* Server's Msgport to which we send requests */
45 struct MsgPort
*ServerPort
;
47 /* The server replies to this port */
48 struct MsgPort
*ReplyPort
;
50 /* Mem used for passing the message */
51 struct ProxyMsg
*Message
;
58 static OOP_Object
*_Root_New(OOP_Class
*cl
, OOP_Object
*o
, struct pRoot_New
*msg
)
60 /* Get the attributes */
61 OOP_Object
*realobject
;
62 struct MsgPort
*serverport
;
64 EnterFunc(bug("Proxy::New()\n"));
68 /* Object from other process which we create a proxy for */
69 realobject
= (OOP_Object
*)GetTagData(aProxy_RealObject
, NULL
, msg
->attrList
);
71 /* MsgPort to pass method invocation throgh.
72 Note that one could very well use a socket or a pipe to pass
76 serverport
= (struct MsgPort
*)GetTagData(aProxy_Port
, NULL
, msg
->attrList
);
78 /* Those two params MUST be supplied */
79 if ( !(realobject
&& serverport
) )
82 o
= (OOP_Object
*)OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)msg
);
85 struct ProxyData
*data
;
86 ULONG disp_mid
= OOP_GetMethodID(IID_Root
, moRoot_Dispose
);
88 data
= (struct ProxyData
*)OOP_INST_DATA(cl
, o
);
90 /* Clear the instance data */
91 memset(data
, 0, sizeof (struct ProxyData
));
93 /* This is ugly, as we will soon run out of sigbits */
94 data
->ReplyPort
= CreateMsgPort();
97 /* Allocate MEMF_PUBLIC message struct */
98 data
->Message
= AllocMem(sizeof (struct ProxyMsg
), MEMF_PUBLIC
);
101 struct ProxyMsg
*pm
= data
->Message
;
103 /* Save the instance data */
104 data
->RealObject
= realobject
;
105 data
->ServerPort
= serverport
;
107 /* Preinitialize some fields in the message struct */
108 pm
->pm_Message
.mn_Length
= sizeof (struct ProxyMsg
);
109 pm
->pm_Message
.mn_ReplyPort
= data
->ReplyPort
;
110 pm
->pm_Object
= realobject
;
112 ReturnPtr("Proxy::New", OOP_Object
*, o
);
115 DeleteMsgPort(data
->ReplyPort
);
119 OOP_CoerceMethod(cl
, o
, (OOP_Msg
)&disp_mid
);
122 ReturnPtr("Proxy::New", OOP_Object
*, NULL
);
128 static VOID
_Root_Dispose(OOP_Class
*cl
, OOP_Object
*o
, OOP_Msg msg
)
130 struct ProxyData
*data
= OOP_INST_DATA(cl
, o
);
132 /* Delete the replyport.. */
134 DeleteMsgPort(data
->ReplyPort
);
136 /* .. the message struct.. */
138 FreeMem(data
->Message
, sizeof (struct ProxyMsg
));
140 /* .. and the object itself. */
141 OOP_DoSuperMethod(cl
, o
, msg
);
143 ReturnVoid("Proxy::Dispose");
147 #define OOPBase ((struct Library *)(OOP_OCLASS(o)->UserData))
152 /* The proxy has a custom DoMethod() call that
153 handles passing the method on to the server's MsgPort.
156 static IPTR
_Proxy_DoMethod(OOP_Object
*o
, OOP_Msg msg
)
158 struct ProxyData
*data
= OOP_INST_DATA(OOP_OCLASS(o
), o
);
160 EnterFunc(bug("Proxy_DoMethod()\n"));
162 /* Pass a pointer to the message */
163 data
->Message
->pm_ObjMsg
= msg
;
166 PutMsg(data
->ServerPort
, (struct Message
*)data
->Message
);
168 /* Wait for server to reply. Note that this is prone to deadlocks,
169 and that this must be fixed. (For example the task calling
170 the remote obj through the proxy, is also server.
171 And the server receiving the call tries to call *us*.
173 WaitPort(data
->ReplyPort
);
175 /* Get the reply, so we can reuse the memory to send new requests.
177 GetMsg(data
->ReplyPort
);
179 ReturnInt("Proxy_DoMethod", IPTR
, data
->Message
->pm_RetVal
);
185 OOP_Class
*init_proxyclass(struct Library
*OOPBase
)
188 struct OOP_MethodDescr root_methods
[] =
190 {(IPTR (*)())_Root_New
, moRoot_New
},
191 {(IPTR (*)())_Root_Dispose
, moRoot_Dispose
},
196 struct OOP_InterfaceDescr ifdescr
[] =
198 { root_methods
, IID_Root
, 2},
202 struct TagItem tags
[] =
204 {aMeta_SuperID
, (IPTR
)CLID_Root
},
205 {aMeta_InterfaceDescr
, (IPTR
)ifdescr
},
206 {aMeta_ID
, (IPTR
)CLID_Proxy
},
207 {aMeta_InstSize
, (IPTR
)sizeof (struct ProxyData
) },
208 {aMeta_DoMethod
, (IPTR
)_Proxy_DoMethod
},
215 EnterFunc(bug("InitProxyClass()\n"));
217 cl
= (OOP_Class
*)OOP_NewObject(NULL
, CLID_MIMeta
, tags
);
220 cl
->UserData
= OOPBase
;
224 ReturnPtr ("InitProxyClass", OOP_Class
*, cl
);