$(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)
/* 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);
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"); */
}
}
#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 */,
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;
}
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.
*/
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)
*
* @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;
}
#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 */
/*@{*/
forb_object_key objkey;
forb_orb orb; /**< FORB reference */
+ forb_ref_t ref; /**< Reference count */
};
struct forb_interface {
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
--- /dev/null
+# 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
+
--- /dev/null
+test_PROGRAMS = objref
+
+lib_LOADLIBES = forb ulut fosa rt
+
+hello_inproc_SOURCES = objref.c
+objref_CLIENT_IDL = objref.idl
+objref_SERVER_IDL = objref.idl
--- /dev/null
+/**
+ * @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;
+}
--- /dev/null
+module test {
+ interface client {
+ void callback();
+ };
+
+ interface server {
+ void call_me_back(in client obj);
+ };
+};