]> rtime.felk.cvut.cz Git - frescor/forb.git/commitdiff
Started implementation of object reference (de)serialization
authorMichal Sojka <sojkam1@fel.cvut.cz>
Thu, 2 Oct 2008 15:38:03 +0000 (17:38 +0200)
committerMichal Sojka <sojkam1@fel.cvut.cz>
Thu, 2 Oct 2008 15:38:03 +0000 (17:38 +0200)
This is not finished yet!

Makefile.omk
forb-idl/forb-idl-c-headers.c
forb-idl/forb-idl-c-skels.c
object.c
object.h
tests/objref/Makefile [new file with mode: 0644]
tests/objref/Makefile.omk [new file with mode: 0644]
tests/objref/objref.c [new file with mode: 0644]
tests/objref/objref.idl [new file with mode: 0644]

index 4935b1544767311ae78fe00a4c212ed67d0b5e75..d9d743b56671fa5cb65c4f1d4fcdefc19cb5cf8d 100644 (file)
@@ -26,6 +26,7 @@ renamed_include_HEADERS += \
        $(call to_forb_subdir, forb.h) \
        $(call to_forb_subdir, iop.h) \
        $(call to_forb_subdir, object.h) \
+       $(call to_forb_subdir, refcnt.h) \
        $(call to_forb_subdir, request.h) \
        $(call to_forb_subdir, syncobj.h) \
        $(call to_forb_subdir, uuid.h)
index 7d770e82b86ba5cff5e1ef5252885295b1986b51..4fc794351d59a86fe96fc413a0eff572a96b437c 100644 (file)
@@ -445,6 +445,8 @@ ch_output_interface(IDL_tree tree, OIDL_Run_Info *rinfo, OIDL_C_Info *ci)
 
 /*         fprintf(ci->fh, "#define %s__freekids CORBA_Object__freekids\n", fullname); */
        fprintf(ci->fh, "typedef forb_object %s;\n", fullname);
+       fprintf(ci->fh, "#define %s_serialize(codec, obj) forb_object_serialize((codec), (obj))\n", fullname);
+       fprintf(ci->fh, "#define %s_deserialize(codec, obj) forb_object_deserialize((codec), (obj))\n", fullname);
 /*             fprintf(ci->fh, "extern CORBA_unsigned_long %s__classid;\n", fullname); */
 
        ch_output_impl_struct(tree, rinfo, ci);
index 7cf0b72e96826cf890f7462f0a3c30ad8224c62b..a700d170b8b5fb4cbc8a170b0b383c77ed89b2d3 100644 (file)
@@ -287,7 +287,13 @@ static void ck_output_op_skel(IDL_tree op, char *intf_id, OIDL_Run_Info *rinfo,
                        char *name = IDL_IDENT(IDL_PARAM_DCL(parm).simple_declarator).str;
                        fprintf(ci->fh, /* "  r = " */ "    ");
                        forb_cbe_write_typespec(ci->fh, IDL_PARAM_DCL(parm).param_type_spec);
-                       fprintf(ci->fh, "_deserialize(cin, &%s);\n", name);
+                       //forb_idl_print_node(parm, 6);
+                       //FIXME: We must determine, whether to parameter is of interface type.
+                       if (IDL_NODE_TYPE(IDL_PARAM_DCL(parm).param_type_spec) == IDLN_INTERFACE) {
+                         fprintf(ci->fh, "_deserialize(_obj->orb, cin, &%s);\n", name);
+                       } else {
+                         fprintf(ci->fh, "_deserialize(cin, &%s);\n", name);
+                       }
 /*                     fprintf(ci->fh, "    if (!r) { ev->major = FORB_EX_IMP_LIMIT; goto exception; }\n"); */
                }
        }
index 19dd016a4733d6f43c387ebe7d4b8cbffb2e5b63..03fc4fa40d611569a15e7c12064c80a410ecca75 100644 (file)
--- a/object.c
+++ b/object.c
@@ -1,6 +1,9 @@
 #include <forb/forb-internal.h>
 #include <forb/object.h>
 #include <stdio.h>
+#include <forb/cdr_codec.h>
+#include <forb/cdr.h>
+#include "misc.h"
 
 GAVL_CUST_NODE_INT_IMP(forb_objects_nolock /* cust_prefix */,
                       forb_t /* cust_root_t */,
@@ -35,11 +38,14 @@ forb_object_new(forb_orb orb,
        forb_object obj = forb_malloc(sizeof(*obj));
        if (obj) {
                memset(obj, 0, sizeof(*obj));
+               forb_ref_init(&obj->ref);
                obj->orb = orb;
                if (server_id) {
+                       /* remote object */
                        obj->server = *server_id;
                        obj->objkey = key;
                } else {
+                       /* local object */
                        if (orb) {
                                forb_t *forb = forb_object_to_forb(obj);
                                obj->server = forb->server_id;
@@ -52,7 +58,40 @@ forb_object_new(forb_orb orb,
        }
        return obj;
 }
+
+/** 
+ * This function does the real release of memory when reference count
+ * is zero.
+ *
+ * @note We add this function the _real suffix because the
+ * forb_object_release() is meant for applications use and we want the
+ * name similar to CORBA_Object_release().
+ */
+static void
+forb_object_release_real(forb_ref_t *ref)
+{
+       forb_object obj = container_of(ref, struct forb_object, ref);
        
+       if (obj->orb) {
+               forb_t *forb = forb_object_to_forb(obj);
+               if (forb_server_id_cmp(&obj->server, &forb->server_id) == 0) {
+                       /* Local object - unregister it from FORB. */
+                       forb_objects_delete(forb, obj);
+               }
+       }
+       forb_free(obj);
+}
+
+static inline void forb_object_get(forb_object obj)
+{
+       forb_ref_get(&obj->ref);
+}
+
+static inline void forb_object_put(forb_object obj)
+{
+       forb_ref_put(&obj->ref, forb_object_release_real);
+}
+
 /** 
  * Releases all memory associated with a object reference and
  * deregister the object from FORB.
@@ -61,11 +100,7 @@ forb_object_new(forb_orb orb,
  */
 void forb_object_release(forb_object obj)
 {
-       if (obj->orb) {
-               forb_t *forb = forb_object_to_forb(obj);
-               forb_objects_delete(forb, obj);
-       }
-       forb_free(obj);
+       forb_object_put(obj);
 }
 
 forb_object_key forb_object_to_key(forb_object obj)
@@ -149,20 +184,55 @@ forb_string_to_object(const forb_orb orb, const char *string)
  * 
  * @param obj Object reference to duplicate.
  * 
- * @return The new copy of @a obj or NULL in case of error.
+ * @return The new copy of @a obj or NULL in case of error. The
+ * duplicated object should be released later by forb_object_release().
  */
 forb_object
 forb_object_duplicate(const forb_object obj)
 {
-       forb_object new;
        if (!obj) {
                return NULL;
        }
-       if (forb_object_is_remote(obj)) {
-               new = forb_object_new(obj->orb, &obj->server, obj->objkey);
-       } else {
-               new = forb_malloc(sizeof(*new));
-               memcpy(new, obj, sizeof(*new));
-       }
-       return new;
+       forb_object_get(obj);
+       return obj;
+}
+
+/** 
+ * Serialize the object reference.
+ * 
+ * @param codec 
+ * @param obj 
+ * 
+ * @return CORBA_TRUE on success, CORBA_FALSE on error.
+ */
+CORBA_boolean
+forb_object_serialize(CDR_Codec *codec, forb_object *obj)
+{
+       if (!forb_server_id_serialize(codec, &(*obj)->server))
+               return CORBA_FALSE;
+       if (!forb_object_key_serialize(codec, &(*obj)->objkey))
+               return CORBA_FALSE;
+       return CORBA_TRUE;
+}
+
+/** 
+ * Creates the object reference by deserialization from ::CDR_Codec.
+ * 
+ * @param orb The FORB where the new reference will be used.
+ * @param codec 
+ * @param obj 
+ * 
+ * @return CORBA_TRUE on success, CORBA_FALSE on error.
+ */
+CORBA_boolean
+forb_object_deserialize(forb_orb orb, CDR_Codec *codec, forb_object *obj)
+{
+       forb_server_id server_id;
+       forb_object_key objkey;
+       if (!forb_server_id_deserialize(codec, &server_id))
+               return CORBA_FALSE;
+       if (!forb_object_key_deserialize(codec, &objkey))
+               return CORBA_FALSE;
+       *obj = forb_object_new(orb, &server_id, objkey);
+       return CORBA_TRUE;
 }
index bab1f99cc18d9f8840f6268c124b598d96c75134..a6185ac2a7ecd9345613b16f862f6811c7ea3aad 100644 (file)
--- a/object.h
+++ b/object.h
@@ -4,8 +4,26 @@
 #include <ul_gavlcust.h>
 #include <forb/forb-internal.h>
 #include <stdbool.h>
-
-/** Object reference structure */
+#include <forb/refcnt.h>
+#include <forb/basic_types.h>
+
+/**
+ * Object reference structure.
+ *
+ * The only ways for applications to create an object reference are:
+ * - call IDL generated forb_<interface>_new() function,
+ * - call forb_string_to_object().
+ *
+ * When the created object is not needed, the application should call
+ * forb_object_release().
+ *
+ * If the object reference is passed as a parameter of interface
+ * method, the same rules as in CORBA C mapping objref_ptr applies,
+ * which is:
+ * 
+ * - if the method needs to store the object reference, it must call
+ *   forb_object_duplicate() and store the duplicate.
+ */
 struct forb_object {
        /** @name Fields valid only for implementation */
        /*@{*/
@@ -31,6 +49,7 @@ struct forb_object {
        forb_object_key objkey;
 
        forb_orb orb;           /**< FORB reference */
+       forb_ref_t ref;         /**< Reference count */
 };
 
 struct forb_interface {
@@ -104,4 +123,9 @@ forb_object_is_remote(forb_object obj)
        return obj && (obj->implementation == NULL);
 }
 
+CORBA_boolean
+forb_object_serialize(CDR_Codec *codec, forb_object *obj);
+CORBA_boolean
+forb_object_deserialize(forb_orb orb, CDR_Codec *codec, forb_object *obj);
+
 #endif
diff --git a/tests/objref/Makefile b/tests/objref/Makefile
new file mode 100644 (file)
index 0000000..b22a357
--- /dev/null
@@ -0,0 +1,14 @@
+# Generic directory or leaf node makefile for OCERA make framework
+
+ifndef MAKERULES_DIR
+MAKERULES_DIR := $(shell ( old_pwd="" ;  while [ ! -e Makefile.rules ] ; do if [ "$$old_pwd" = `pwd`  ] ; then exit 1 ; else old_pwd=`pwd` ; cd -L .. 2>/dev/null ; fi ; done ; pwd ) )
+endif
+
+ifeq ($(MAKERULES_DIR),)
+all : default
+.DEFAULT::
+       @echo -e "\nThe Makefile.rules has not been found in this or partent directory\n"
+else
+include $(MAKERULES_DIR)/Makefile.rules
+endif
+
diff --git a/tests/objref/Makefile.omk b/tests/objref/Makefile.omk
new file mode 100644 (file)
index 0000000..16e2761
--- /dev/null
@@ -0,0 +1,7 @@
+test_PROGRAMS = objref
+
+lib_LOADLIBES = forb ulut fosa rt
+
+hello_inproc_SOURCES = objref.c
+objref_CLIENT_IDL = objref.idl
+objref_SERVER_IDL = objref.idl
diff --git a/tests/objref/objref.c b/tests/objref/objref.c
new file mode 100644 (file)
index 0000000..ede34ae
--- /dev/null
@@ -0,0 +1,77 @@
+/**
+ * @file   objref.c
+ * @author Michal Sojka <sojkam1@fel.cvut.cz>
+ * @date   Thu Oct  2 15:32:17 2008
+ * 
+ * @brief  Test for passing object references as parameters.
+ *
+ * In test a client calls server's method call_me_back(), which take
+ * client object reference as parameter. The server then invokes the
+ * callback() method on the received object reference.
+ * 
+ */
+
+#include "objref.h"
+#include <forb/forb.h>
+#include <error.h>
+#include <fosa.h>
+#include <forb/executor.h>
+
+void *server_thread(void *arg)
+{
+       hello hobj = arg;
+
+       forb_execute_object(hobj);
+       return NULL;
+}
+
+char *start_server()
+{
+       forb_orb orb;
+       hello hobj;
+
+       fosa_thread_id_t tid;
+
+       orb = forb_init();
+       hobj = hello_impl_initialize(orb);
+       fosa_thread_create(&tid, NULL, server_thread, hobj);
+
+       return forb_object_to_string(hobj);
+}
+
+
+
+void client(void *arg)
+{
+       forb_orb orb;
+       hello hobj;
+       struct forb_env env;
+       char *objref = arg;
+       
+       orb = forb_init();
+
+       sleep(1);               /* Hack to wait for dicovery of the two peers */
+
+       hobj = forb_string_to_object(orb, objref);
+       if (!hobj) {
+               error(1, 0, "Cannot create object reference from the string (%s)\n", objref);
+       }
+
+       hello_message(hobj, "Hello world!", &env);
+       if (forb_exception_occured(&env)) {
+               error(1, 0, "FORB exception %d", env.major);
+       }
+
+}
+
+int main(int argc, char *argv[])
+{
+
+       char *objref_str;
+       
+       objref_str = start_server();
+
+       client(objref_str);
+               
+       return 0;       
+}
diff --git a/tests/objref/objref.idl b/tests/objref/objref.idl
new file mode 100644 (file)
index 0000000..0b2329c
--- /dev/null
@@ -0,0 +1,9 @@
+module test {
+       interface client {
+               void callback();
+       };
+
+       interface server {
+               void call_me_back(in client obj);
+       };
+};