[omniORB] Sequences/allocbuf/freebuf comment

Yan Pujante yan@corp.socialnet.com
Thu, 15 Feb 2001 09:22:37 -0800


Hello

I am not sure it is the right place for this kind of comment but here it is. I
am using a sequence of structures (in IDL: typedef sequence<C> CSeq;)

I really like in the CORBA spec how you get a C_var defined for you and you use
it this way:

C *myfunc()
{

  C_var c = new C();

  // do stuff (which can potentially throws an exception)

  return c._retn(); // remove the ownership
}


But there is no equivalent for an array of C used in a sequence. According to
the spec, you are supposed to create it using CSeq::allocbuf and free it using
CSeq::freebuf. So the code would be:

C *array = CSeq::allocbuf(n);

// initialize each element of the array...
// this can potentially throws an exception

// here I am giving the ownership of the array to the sequence
// so I don't have to free it myself
CSeq_var seq = new CSeq(n, n, array, true);

return seq._retn();

The problem in this code is that it can potentially leak memory if something
wrong happen between allocbuf and the transfer of ownership.

Hence the idea of creating a wrapper equivalent to the _var contruct:

template <class T, class U>
class TUBuf
{
  public:
    inline TUBuf(int nElems) : _buf(U::allocbuf(nElems)) {}
    inline TUBuf(T *buf) : _buf(buf) {}
    inline T& operator[] (int idx) { return _buf[idx]; }
    inline T *_retn() { T *tmp = _buf; _buf = NULL; return tmp; }
    inline ~TUBuf() { if(_buf) U::freebuf(_buf); }
  private:
    T *_buf;
};

Then the previous code can be rewritten:

TUBuf< C, CSeq > array(n);

// initialize each element of the array...
// this can potentially throws an exception

// here I am giving the ownership of the array to the sequence
CSeq_var seq = new CSeq(n, n, array._retn(), true);

return seq._retn();


Now it is safe. My only concern is that I have to write a function taking 2
template parameters because in the code generated there is no way of extracting
C from CSeq

A code like that would do the job:

class CSeq : ....
{
   typedef C _myType; // traditionnal construct found everywhere in STL
   ....
}

Then the template function could be rewritten:

template <class U>
class TUBuf
{
  public:
    typedef typename U::_myType T;
    inline TUBuf(int nElems) : _buf(U::allocbuf(nElems)) {}
    inline TUBuf(T *buf) : _buf(buf) {}
    inline T& operator[] (int idx) { return _buf[idx]; }
    inline T *_retn() { T *tmp = _buf; _buf = NULL; return tmp; }
    inline ~TUBuf() { if(_buf) U::freebuf(_buf); }
  private:
    T *_buf;
};

and finally the allocation code:
TUBuf< CSeq > array(n);

Yan

-- 

http://eowyn.fr.eu.org/~yan/ | yan@corp.socialnet.com