Variable passing rule


Structure/Object reference

In C++, the structure of CORBA is mapped to the structure "struct".

 // -*- IDL -*-
 struct Profile {
   short short_value;
   long  long_value;
 };

 // -*- C++ -*-
 struct Profile {
   CORBA::Short short_value;
   CORBA::Long  long_value;
 };

 class Profile_var {
   
 };

  • Fixed length structure
  • Variable length structure

If the structure contains variable length members (string, wstring, sequence, (struct with variable length members, union with variable length member), the structure is considered variable length data. In this case, C ++ code different from the fixed length structure is generated, and handling in return value and out parameter is different.

  • _var type The IDL compiler automatically generates C ++ structures and _ var type classes from the structure in IDL. The _var type class behaves like a smart pointer, and when you use the _var class as a variable length structure, the memory allocated to variable length members is automatically managed.
    • If assignment is made from a variable of type _var (var1, for example) to another variable of type _var (var2), the ownership of the pointer is moved to var 2, then var 1 is initialized or assigned It can not be used until it is broken.
    • When the structure goes out of scope, all memory associated with the variable length member is automatically released. However, if the _var type variable already transferred ownership comes out of the scope, the original data will not be released. (We already transferred ownership.)
    • If the initialized or assigned structure is reinitialized or assigned again, the memory associated with the original data is automatically released.
    • If an object reference is assigned to a variable length member, a copy of that object reference is created. If a pointer is assigned to a variable length member, no copy is created.

_ var type

Transformation constructor (T_ptr)

  • Implementation example
      _CORBA_ObjRef_Var(T_ptr p) : pd_objref(p) {}

The ownership of object reference of type _ptr moves to type _ var, so there is no increase or decrease of reference count.

 MyObject_ptr ptr = obj->get_myobject();
 // ptr must be released at the proper timing
 MyObject_var var(ptr);
 // Ownership moved to var, so you do not need to release ptr
 // The reference count is decremented when var is dismantled, such as going out of scope
 

Transformation constructor (const T_var&)

  • Implementation example
     Object_var(const T_var& p) : pd_ref(T::_duplicate(p.pd_ref)) {}

The ownership of the object reference of _var type of the assignment source is copied.

 MyObject_var var0 = obj->get_myobject();
 // var 0 has ownership
 MyObject_var var1(var0);
 // Reference count is incremented and var 1 also owns ownership

Transformation constructor (const T_member)

  • Implementation example

in argument and in () function

It simply returns _ptr type pointer of object reference. Movement of ownership does not occur.

  • Implementation example
     T_ptr  in() const { return pd_objref; }

It is usually used to pass an object reference to the in argument of a function. Functions given object references do not have ownership and should not be 'released' in the function. After returning from the function, the _var type variable still holds ownership, and the object is released when the _var type variable is disassembled.

When defining a function that takes an object reference as an in argument, it is defined as an argument of type _ptr. Furthermore, within a function, just call the operation of the object, do not do release etc. Also, if you want to save an object reference in a function somewhere (global variable, static variable, object member etc.), you need to duplicate the duplicate function to copy ownership.

  • Example of use
     void myfunc(MyObject_ptr obj)
     {
       obj->function();
       CORBA::release(obj); // ×Do not do this
       m_obj = obj; // ×I do not own ownership
       m_obj = MyObject::duplicate(obj); // ○Duplicate ownership
     }
     
     {// Another context
       MyObject_var obj(hoge->get_object());
       myfunc(obj.in()); // Transfer of ownership does not occur
     }
     // Since the scope has passed, the reference count is decremented

out argument and out () function

Returns the currently owned reference as release (decrement the reference count) and sets the reference pointer to nil and returns it. That is, if an object reference is held before the out () function call, the ownership is abandoned and the reference is discarded.

  • Implementation example
     T_ptr& out() {
        T_Helper::release(pd_objref);
        pd_objref = T_Helper::_nil();
        return pd_objref;
     }

It is usually used to pass an object reference to the out argument of a function. That is, after returning from the function, it is expected that a new object reference is held in this variable. At this time, ownership of the object reference is assumed to be held in this variable. On the function side passed the variable with out(), it is necessary to generate or duplicate an object reference in some way and pass ownership to the argument.

When defining a function that takes an object reference as an out argument, it is defined as an argument of _ptr type reference. Within a function, an argument is always a nil object reference, and it is normally expected to substitute some object for ownership.

  • Example of use
     void myfunc(MyObject_ptr& obj)
     {
       assert(CORBA::is_nil(obj)); // Always a nil object
       obj->function(); // Because it is nil, I can not call operations
     
       // m_obj is a _var type member variable
       obj = m_obj; // ×You do not duplicate ownership.
       // After return, it may be freely released outside the function.
     
       obj = MyObject::duplicate(obj); // ○I own copies of ownership.
       // After return, even if it is released outside the function, the object reference is not broken.
       return;
     }
     
     {// Another context
       MyObject_var obj;
       obj = get_object(); // △Since it is used as an out variable, it is better not to insert anything before passing it
       myfunc(obj.out());
       // Object should have been assigned and returned
       assert(!CORBA::is_nil(obj));
       obj->function();
     }
     // Since the scope has passed, the reference count is decremented.
     

    inout()

Returns a pointer reference to the reference.

  • Implementation
     T_ptr& inout()    { return pd_objref; }

It is usually used to pass an object reference to the inout argument of a function. That is, within the function, it is expected that some object reference is included in the argument, and the ownership of the object shifts to the function side. Also, the function is expected to give some object reference to this argument and return it, giving arguments, ie ownership of the calling variable. In the function, when setting an object reference newly as an argument, it is necessary to first generate release and then create or duplicate a new object reference and pass ownership to the argument.

Functions that take object references as inout arguments are not highly recommended from a design standpoint. If you need to define a function to take as an inout argument, define it as an argument to _ptr type reference.

  • Example of use
     void myfunc(MyObject_ptr& obj)
     {
       if (!CORBA::is_nil(obj))
       {
         obj->function(); // If obj is not nil, you can call the operation.
       }
     
       CORBA::release(obj); // The responsibility to release is in this function
       /*
         * Within this function, only if there is a new object reference in obj,
         * By assigning to the _var variable immediately after receiving the argument,
         * Decrement the reference count automatically at the end of the function
         * You may use a technique.     
         * MyObject_var deleter = obj;
        */
     
       // Make it MyObject_var m_obj
       obj = m_obj; // × I do not duplicate ownership
       // After return, it may be released outside the function.
       obj = MyObject::_duplicate(m_obj); // ○ obj was also given ownership of MyObject
       // After return, even if it is released outside the function, the object reference is not broken.
     }
     
     {// Another context
       MyObject_var obj;
       obj = get_object(); // obj has ownership
       myfunc(obj); // Released in function
       // The one pointed by obj may be interchanged.
     }
     // Since the scope has passed, the reference count is decremented.

_retn()

Abandon ownership of the object reference currently held and return a pointer.

 T_ptr _retn() {
    T_ptr tmp = pd_objref;
    pd_objref = T_Helper::_nil();
    return tmp;
 }

It is usually used when returning an object reference to the return value of a function. Since ownership passes to the caller of the function, the caller is responsible for discarding object references. Therefore, it needs to be released on the caller side or received with the _var type variable. Conversely, when returning an object reference by return value, since the reference always decrements the reference count by release on the caller side, it is necessary to duplicate the ownership by _duplicate () etc. within the function.

  • Example of use
     MyObject_ptr myfunc()
     {
       MyObject_var ret;
       ret = m_obj; // ×Ownership shifts to ret.
       // After return, it may be released outside the function.
     
       ret = MyObject::_duplicate(m_obj); // ○Reproduction of ownership
       // Even if release is called after returning, m_obj keeps ownership.
     
       return ret._retn();
     }
     
     { // Another context
       MyObject_var obj;
       obj = myfunc(); // Obtain ownership of the object
       obj->function();
     
       MyObject_ptr ptr;
       ptr = myfunc(); //Obtain ownership of the object
       ptr->function();
     
       CORBA::release(ptr); // Decrement reference count
      }
      // Since the scope has passed, the reference count is decremented

Rule summary

Function type release responsibility in function
in T_ptr Caller Operation call
out T_ptr & Caller side _duplicate assignment
inout T_ptr & in: function, out: caller side after release, _duplicate assignment
_retn T_ptr Caller side _duplicate and return

Reference count with substitution of _var type, _ptr type

Assigning _var type to _ptr type

Assignment to a pointer.

No replication, no release.

  • Example of use

 { 
  MyObject_var var;
  var = myfunc(); // Obtain ownership of the object
 
  MyObject_ptr ptr
  ptr = MyObject::_duplicate(var); //Obtain ownership of object (Increment reference count)
 
  // ptr = var;
  // This can cause reference count error. After calling, ptr and var are the same object   // but no reference count maintenance is done. var maintains possession of its target object   / / You do. Also, ptr was the only pointer to the object or proxy it was previously pointing to   //, a memory leak occurs.
 
  CORBA::release(ptr); // Decrement reference count
 }
 //As for var, the reference count is decremented because it passed the scope

_ptr type assignment to type _var

It is released () for the object held by _var, It is not duplicate () for _ptr type objects passed as arguments.

No duplication, release.

  • Implementation (omniORB)

  inline T_var& operator= (T_ptr p) {
    T_Helper::release(pd_objref);
    pd_objref = p;
    return *this;
  }

  • Example of use

 { 
  MyObject_ptr ptr;
  ptr = myfunc(); // Obtain ownership of the object
 
  MyObject_var obj;
  obj = MyObject::_duplicate(ptr); //Obtain ownership of object (Increment reference count)
 
  CORBA::release(ptr); // Decrement reference count
 }
 // With respect to obj, the reference count is decremented because it passed the scope

Assigning _var type to _var type

Release () is called on the object held by _var, Also, duplicate () is called on the object passed in the argument.

There is duplication, release.

  • Implementation (omniORB)

  inline T_var& operator= (const T_var& p) {
    if( &p != this ) {
      T_Helper::duplicate(p.pd_objref);
      T_Helper::release(pd_objref);
      pd_objref = p.pd_objref;
    }
    return *this;
  }

  • Example of use

 { 
  MyObject_var var1;
  var1 = myfunc(); // Obtain ownership of the object
 
  MyObject_var var2;
  var2 = var1; //Obtain ownership of object (reference count is automatically incremented)
 
  } // For var 1, var 2, the reference count is decremented since it has passed the scope

Reference count with _narrow ()

In the process of _narrow () processing, when the call to _narrow () succeeds, the reference count of the target object is incremented, but if it fails it is not incremented.

Decrement is not performed.

  • Implementation (RTCSK.cc)

 RTC::RTObject_ptr
 RTC::RTObject::_narrow(::CORBA::Object_ptr obj)
 {
   if( !obj || obj->_NP_is_nil() || obj->_NP_is_pseudo() ) return _nil();
   _ptr_type e = (_ptr_type) obj->_PR_getobj()->_realNarrow(_PD_repoId);
   return e ? e : _nil();
 }

  • Implementation (omniObjRef.cc)

 void*
 omniObjRef::_realNarrow(const char* repoId)
 {
  // Attempt to narrow the reference using static type info.
  void* target = _ptrToObjRef(repoId);
 
  if( target ) {
    if (!lid ||
    (lid && !lid->deactivated() && lid->servant() &&
     lid->servant()->_ptrToInterface(repoId))) {
 
      omni::duplicateObjRef(this);
    }
    else {
      omniObjRef* objref;
      omniIOR*    ior;
 
      {
    ior = pd_ior->duplicateNoLock();
      }
 
      {
    objref = omni::createObjRef(repoId,ior,1,0);
      }
    }
  }
  else {
    if( _real_is_a(repoId) ) {
      omniObjRef* objref;
      omniIOR* ior;
 
      {
    ior = pd_ior->duplicateNoLock();
      }
 
      {
    objref = omni::createObjRef(repoId,ior,1,_identity());
      }
 
      }
    }
  }
  return target;
 }

Rules

Client side

If the client receives an object reference from the call, the client must release it when that object reference is no longer needed.

Server side

The ownership of the reference passed to the caller is abandoned (that is, its reference count is decremented by one, so it is normal to call the appropriate _duplicate () function before returning the reference)

Download

latest Releases : 2.0.0-RELESE

2.0.0-RELESE Download page

Number of Projects

Choreonoid

Motion editor/Dynamics simulator

OpenHRP3

Dynamics simulator

OpenRTP

Integrated Development Platform

AIST RTC collection

RT-Components collection by AIST

TORK

Tokyo Opensource Robotics Association

DAQ-Middleware

Middleware for DAQ (Data Aquisition) by KEK