[omniORB-dev] Removing an entry from proxyObjectFactory

Christian Perez Christian.Perez@irisa.fr
Wed, 26 Feb 2003 17:00:33 +0100


This is a multi-part message in MIME format.
--------------30269C50EFB09E59EDDFEC71
Content-Type: text/plain; charset=iso-8859-1
Content-Transfer-Encoding: 8bit

Hi,

Duncan Grisby wrote:
> 
> On Thursday 20 February, Christian Perez wrote:
> 
> If you can convince yourself that that situation will never arise in
> your application, it would be safe to unload stubs, and unregister
> their proxyObjectFactories.

Good news !
 
> > In attachement, you'll find such an implementation of proxyFactory.cc
> > derived from omniORB3 (location src/lib/omniORB2/orbcore/proxyFactory.cc).
> > This implementation is based on the used of the map of the C++ STL.
> 
> There are two problems here. First, your suggestion is not thread
> safe. Second, it is not possible to use STL within omniORB, since it
> is not available everywhere.

The file was provided to illustrate the kind of modification I suggested.
As it was stated in the file, it was not a thread-safe implementation nor
a final implementation (it was derived from omniORB-3!)

Taking into your comments (no STL), here is a modified version of proxyFactory.cc
derived from omniORB-4. If you do not see any drawbacks, it would be very
nice if it could be inserted it into omniORB-4.

It has been successfully tested within a non trivial application.

Best regards,
Christian Pérez
--------------30269C50EFB09E59EDDFEC71
Content-Type: text/plain; charset=us-ascii;
 name="proxyFactory-fix.cc"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="proxyFactory-fix.cc"

// -*- Mode: C++; -*-
//                            Package   : omniORB
// proxyFactory.cc            Created on: 24/2/99
//                            Author    : Sai Lai Lo (sll)
//
//    Copyright (C) 1996, 1997 Olivetti & Oracle Research Laboratory
//
//    This file is part of the omniORB library
//
//    The omniORB library is free software; you can redistribute it and/or
//    modify it under the terms of the GNU Library General Public
//    License as published by the Free Software Foundation; either
//    version 2 of the License, or (at your option) any later version.
//
//    This library is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//    Library General Public License for more details.
//
//    You should have received a copy of the GNU Library General Public
//    License along with this library; if not, write to the Free
//    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
//    02111-1307, USA
//
//
// Description:
//    Implementation of proxyObjectFactory.
//

/*
  $Log: proxyFactory.cc,v $
  Revision 1.2.2.5  2001/09/19 17:26:53  dpg1
  Full clean-up after orb->destroy().

  Revision 1.2.2.4  2001/04/18 18:18:05  sll
  Big checkin with the brand new internal APIs.

  Revision 1.2.2.3  2000/11/09 12:27:59  dpg1
  Huge merge from omni3_develop, plus full long long from omni3_1_develop.

  Revision 1.2.2.2  2000/09/27 17:58:56  sll
  Changed include/omniORB3 to include/omniORB4

  Revision 1.2.2.1  2000/07/17 10:35:58  sll
  Merged from omni3_develop the diff between omni3_0_0_pre3 and omni3_0_0.

  Revision 1.3  2000/07/13 15:25:55  dpg1
  Merge from omni3_develop for 3.0 release.

  Revision 1.1.2.1  1999/09/22 14:27:05  djr
  Major rewrite of orbcore to support POA.

*/

#include <omniORB4/CORBA.h>
#include <omniORB4/proxyFactory.h>

OMNI_NAMESPACE_BEGIN(omni)

static proxyObjectFactory** ofl = 0;
static int                  ofl_size = 0;
static int                  ofl_len = 0;
static omni_mutex*          ofl_mutex = 0;

proxyObjectFactory::~proxyObjectFactory()
{
  OMNIORB_ASSERT(pd_repoId);

  // Remove itself from the global list

  ofl_mutex->lock();

  // Binary search to find the factory.

  int bottom = 0;
  int top = ofl_len;
  int pos = -1;
  while( bottom < top ) {

    int middle = (bottom + top) / 2;

    int cmp = strcmp(pd_repoId, ofl[middle]->pd_repoId);

    if( cmp < 0 )       top = middle;
    else if( cmp > 0 )  bottom = middle + 1;
    else                { pos = middle; break; }
  }

  // sanity check
  if (pos == -1) {
    if( omniORB::trace(1) ) {
      omniORB::logger l;
      l << "Could not find proxyObjectFactory " << this->pd_repoId
	<< " whitin its desctructor at "
	<< __FILE__ << ": line " << __LINE__ << "\n";
    }
  } else {
    // remove it by shifting all pointers
    // this is not the most efficient ;(
    ofl_len = ofl_len - 1;
    if (pos != ofl_len ) {
      // this is not the last : shift
      memcpy((void*)&ofl[pos], (void*)&ofl[pos+1], (ofl_len - pos) * sizeof(proxyObjectFactory*));
    }
  }

  ofl_mutex->unlock();
}

proxyObjectFactory::proxyObjectFactory(const char* repoId)
  : pd_repoId(repoId)
{
  // These factories are constructed statically in the stubs, thus
  // there should be no possiblilty of concurrency.

  // This is not longer true as we try to support dynamic code loading and unloading

  OMNIORB_ASSERT(repoId);

  if( !ofl ) {
    ofl_size = 5;
    ofl = new proxyObjectFactory* [ofl_size];
    ofl_len = 0;
    // We can not rely on the order of initialization of global object
    // This should be ok as there are some proxyObjectFactory created
    // during the loading of the omniORB library, which is assumed to be a sequential operaion
    ofl_mutex = new omni_mutex();
  }

  ofl_mutex->lock(); 

  if( ofl_len == ofl_size ) {
    int new_ofl_size = ofl_size * 2;
    proxyObjectFactory** new_ofl = new proxyObjectFactory* [new_ofl_size];
    for( int i = 0; i < ofl_size; i++ )  new_ofl[i] = ofl[i];
    delete[] ofl;
    ofl = new_ofl;
    ofl_size = new_ofl_size;
  }

  // Binary search to determine the insertion point.

  int bottom = 0;
  int top = ofl_len;

  while( bottom < top ) {

    int middle = (bottom + top) / 2;

    int cmp = strcmp(repoId, ofl[middle]->pd_repoId);

    if( cmp < 0 )       top = middle;
    else if( cmp > 0 )  bottom = middle + 1;
    else {
      ofl[middle] = this;
      if( omniORB::trace(15) )
	  omniORB::logf("Replaced proxyObjectFactory for %s.", repoId);
      ofl_mutex->unlock(); 
      return;
    }
  }

  OMNIORB_ASSERT(top == bottom);

  for( int i = ofl_len; i > bottom; i-- )
    ofl[i] = ofl[i - 1];

  ofl[bottom] = this;
  ofl_len++;

  ofl_mutex->unlock(); 
}


void
proxyObjectFactory::shutdown()
{
  ofl_mutex->lock(); 
  ofl_size = 0;
  ofl_len = 0;
  delete[] ofl;
  ofl_mutex->unlock();
  delete ofl_mutex;
}


proxyObjectFactory*
proxyObjectFactory::lookup(const char* repoId)
{
  // Factories should all be registered before the ORB is initialised,
  // so at this point the list is read-only. Concurrent accesses are
  // safe, except that the list is deleted when the ORB is shutdown.
  // There is a very small possibility that we will segfault below,
  // but that can only happen if the application is creating an object
  // reference at the same time as they are shutting down the ORB.

  OMNIORB_ASSERT(repoId);

  ofl_mutex->lock(); 

  // Binary search to find the factory.

  int bottom = 0;
  int top = ofl_len;

  proxyObjectFactory* res = 0;
  while( bottom < top ) {

    int middle = (bottom + top) / 2;

    int cmp = strcmp(repoId, ofl[middle]->pd_repoId);

    if( cmp < 0 )       top = middle;
    else if( cmp > 0 )  bottom = middle + 1;
    else                { res = ofl[middle]; break; }
  }

  ofl_mutex->unlock(); 

  return res;
}

OMNI_NAMESPACE_END(omni)

--------------30269C50EFB09E59EDDFEC71--