2005/5/9

     
 

ObjectLockPool.cpp

artefaktur
// -*- mode:C++; tab-width:2; c-basic-offset:2; indent-tabs-mode:nil -*-
//
// Copyright (C) 2000-2005 by Roger Rene Kommer / artefaktur, Kassel, Germany.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public License (LGPL).
//
//
// 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
// License ACDK-FreeLicense document enclosed in the distribution
// for more for more details.
// This file is part of the Artefaktur Component Development Kit:
//                         ACDK
//
// Please refer to
// - http://www.acdk.de
// - http://www.artefaktur.com
// - http://acdk.sourceforge.net
// for more information.
//
// $Header: /cvsroot/acdk/acdk/acdk_core/src/acdk/lang/sys/ObjectLockPool.cpp,v 1.11 2005/04/26 22:05:05 kommer Exp $



#include <acdk.h>

#include "sys.h"

#include "ObjectLockPool.h"

#include "core_vector.h"

#include "core_fastmutex.h"
#include "core_mutex.h"
#include "core_condition.h"
#include "../Thread.h"
#include "../System.h"

#ifdef ACDK_MT

//#define LOCAL_DEBUG
#ifdef LOCAL_DEBUG
#define DOUT(strexpr) \
do { \
  StringBuffer sb; \
  sb << strexpr; \
  System::out->println(sb.toString()); \
} while (false)
#else
/FONT>
#define DOUT(strexpr)
#endif
/FONT>


namespace acdk {
namespace lang {

//using namespace sys;
class ObjectLockPool
{
  sys::core_vector<ObjectLock*> _vec;
  int _firstFreePos;
  bool _destroyed;
public:
  ObjectLockPool()
  : _vec(0)
  , _firstFreePos(0)
  , _destroyed(false)
  {

  }
  ~ObjectLockPool()
  {
    for (int i = 0; i < _vec.size(); ++i)
    {
      ObjectLock* olock = _vec[i];
      if (olock != 0 && olock->_obj == 0)
        delete olock;
    }
    _destroyed = true;
  }
  ObjectLock* aquire(const acdk::lang::Object* obj)
  {
    if (_firstFreePos >= _vec.size())
    {
      int idx = _vec.size();
      _vec.push_back(new ObjectLock(idx));
      ObjectLock* ret = _vec[idx];
      ret->_obj = obj;
      ret->ensureLock();
      _firstFreePos = _vec.size();
      return ret;
    }
    ObjectLock* ret = _vec[_firstFreePos];
    ret->_obj = obj;
    ret->ensureLock();

    int i;
    for (i = _firstFreePos + 1; i < _vec.size() && _vec[i]->_obj != 0; ++i)
    {
    }
    _firstFreePos = i;
    return ret;
  }
  void release(ObjectLock* ol)
  {
    ol->_obj = 0;
    // destructor already called for this static object
    if (_destroyed == true)
    {
      delete ol;
      return;
    }
    if (_firstFreePos > ol->_index)
      _firstFreePos = ol->_index;
  }
};


ObjectLockPool& _getObjectLockPool()
{
  static ObjectLockPool sobjectLockPool;
  return sobjectLockPool;
}


//static
void
ObjectLock::releaseLock(acdk::lang::ObjectLock* lock)
{
  //delete lock;
  lock->reset();
  _getObjectLockPool().release(lock);
}

//static
ObjectLock*
ObjectLock::aquireLock(const acdk::lang::Object* obj)
{
  //return new ObjectLock();
  return _getObjectLockPool().aquire(obj);
}

ObjectLock::ObjectLock()
: _index(-1)
, _mutex(0)
, _monitor(0)
, _obj(0)
{
}

ObjectLock::ObjectLock(int idx)
: _index(idx)
, _mutex(0)
, _monitor(0)
, _obj(0)
{
}

ObjectLock::~ObjectLock()
{
 if (_monitor != 0) {
    delete _monitor;
    _monitor = 0;
  }
 if (_mutex != 0) {
   delete _mutex;
  _mutex = 0;
 }
}

void
ObjectLock::lock()
{
  ensureLock();
  _mutex->lock();
}

void
ObjectLock::unlock()
{
  ensureLock();
  _mutex->unlock();
}

acdk::lang::sys::static_mutex _aquire_lock;

void
ObjectLock::ensureLock()
{
  if (_mutex == 0) {
    TLockGuard< acdk::lang::sys::static_mutex>  lockthis(_aquire_lock);
    if (_mutex == 0)
      _mutex = new ObjectMutex();
  }
}

void
ObjectLock::ensureCondition()
{
  ensureLock();
  if (_monitor == 0)
  {
    TLockGuard< acdk::lang::sys::static_mutex>  lockthis(_aquire_lock);
    if (_monitor == 0)
    {
      _monitor = new ObjectMonitor(*_mutex);
      DOUT("ObjectLock: allocated condition: " << (int)(void*)_monitor);
    }
    else
    {
      DOUT("ObjectLock: had condition2: " << (int)(void*)_monitor);
    }
  }
  else
  {
    DOUT("ObjectLock: had condition: " << (int)(void*)_monitor);
  }

}

void
ObjectLock::reset()
{
  TLockGuard< acdk::lang::sys::static_mutex>  lockthis(_aquire_lock);
  if (_monitor != 0)
  {
    ObjectMonitor* smon = _monitor;
    DOUT("ObjectLock: reset condition: " << (int)(void*)_monitor);
    _monitor = 0;
    delete smon;
  }
  /* crashes
  if (_mutex != 0)
    _mutex->reset();
  */
}

void
ObjectLock::wait(int timeoutms, int timeoutus)
{
  ensureCondition();
  ScopedWaitingMonitor sm(_monitor);

  if (timeoutms == 0 && timeoutus == 0)
    _monitor->wait();
  else
    _monitor->wait(timeoutms/*, timeoutus*/);
  Thread::checkForPendingException();
}

void
ObjectLock::notify()
{
  ensureCondition();
  TUnLockGuard <ObjectMutex> unlock(*_mutex);
  _monitor->notify();
}

void
ObjectLock::notifyAll()
{
  ensureCondition();
  _monitor->notifyAll();
}


} // lang
} // acdk
#endif //ACDK_MT