⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 safecoll.cxx

📁 sloedgy open sip stack source code
💻 CXX
📖 第 1 页 / 共 2 页
字号:
/*
 * safecoll.cxx
 *
 * Thread safe collection classes.
 *
 * Portable Windows Library
 *
 * Copyright (c) 2002 Equivalence Pty. Ltd.
 *
 * The contents of this file are subject to the Mozilla Public License
 * Version 1.0 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
 * the License for the specific language governing rights and limitations
 * under the License.
 *
 * The Original Code is Portable Windows Library.
 *
 * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
 *
 * Contributor(s): ______________________________________.
 *
 * $Log: safecoll.cxx,v $
 * Revision 1.1  2006/06/29 04:18:19  joegenbaclor
 * *** empty log message ***
 *
 * Revision 1.14  2004/10/14 23:01:31  csoutheren
 * Fiuxed problem with usage of Sleep
 *
 * Revision 1.13  2004/10/14 12:31:47  rjongbloed
 * Added synchronous mode for safe collection RemoveAll() to wait until all objects
 *   have actually been deleted before returning.
 *
 * Revision 1.12  2004/10/04 12:54:33  rjongbloed
 * Added functions for locking an unlocking to "auto-unlock" classes.
 *
 * Revision 1.11  2004/08/14 07:42:31  rjongbloed
 * Added trace log at level 6 for helping find PSafeObject reference/dereference errors.
 *
 * Revision 1.10  2004/08/12 12:37:41  rjongbloed
 * Fixed bug recently introduced so removes deleted object from deletion list.
 * Also changed removal list to be correct type.
 *
 * Revision 1.9  2004/08/05 12:15:56  rjongbloed
 * Added classes for auto unlocking read only and read write mutex on
 *   PSafeObject - similar to PWaitAndSIgnal.
 * Utilised mutable keyword for mutex and improved the constness of functions.
 * Added DisallowDeleteObjects to safe collections so can have a PSafeObject in
 *   multiple collections.
 * Added a tempalte function to do casting of PSafePtr to a PSafePtr of a derived
 *   class.
 * Assured that a PSafeObject present on a collection always increments its
 *   reference count so while in collection it is not deleted.
 *
 * Revision 1.8  2004/04/03 08:22:22  csoutheren
 * Remove pseudo-RTTI and replaced with real RTTI
 *
 * Revision 1.7  2002/12/10 07:37:34  robertj
 * optimised SetLockMode() so if doesn't change mode it doesn't do anything.
 *
 * Revision 1.6  2002/10/29 00:06:24  robertj
 * Changed template classes so things like PSafeList actually creates the
 *   base collection class as well.
 * Allowed for the PSafeList::Append() to return a locked pointer to the
 *   object just appended.
 *
 * Revision 1.5  2002/10/04 08:22:50  robertj
 * Changed read/write mutex so can be called by same thread without deadlock
 *   removing the need to a lock count in safe pointer.
 * Added asserts if try and dereference a NULL safe pointer.
 * Added more documentation on behaviour.
 *
 * Revision 1.4  2002/08/29 06:53:28  robertj
 * Added optimisiation, separate mutex for toBeRemoved list.
 * Added assert for reference count going below zero.
 * Fixed incorrect usage of lockCount if target of an assignment from another
 *   safe pointer. Would not unlock the safe object which could cause deadlock.
 *
 * Revision 1.3  2002/05/06 00:44:45  robertj
 * Made the lock/unlock read only const so can be used in const functions.
 *
 * Revision 1.2  2002/05/01 04:48:05  robertj
 * GNU compatibility.
 *
 * Revision 1.1  2002/05/01 04:16:44  robertj
 * Added thread safe collection classes.
 *
 */

#ifdef __GNUC__
#pragma implementation "safecoll.h"
#endif

#include <ptlib.h>
#include <ptlib/safecoll.h>


#define new PNEW


/////////////////////////////////////////////////////////////////////////////

PSafeObject::PSafeObject()
{
  safeReferenceCount = 0;
  safelyBeingRemoved = FALSE;
}


BOOL PSafeObject::SafeReference()
{
  PWaitAndSignal mutex(safetyMutex);

  if (safelyBeingRemoved)
    return FALSE;

  safeReferenceCount++;
  PTRACE(6, "SafeColl\tIncrement reference count to " << safeReferenceCount << " for " << GetClass() << ' ' << (void *)this);
  return TRUE;
}


void PSafeObject::SafeDereference()
{
  safetyMutex.Wait();
  if (PAssert(safeReferenceCount > 0, PLogicError)) {
    safeReferenceCount--;
    PTRACE(6, "SafeColl\tDecrement reference count to " << safeReferenceCount << " for " << GetClass() << ' ' << (void *)this);
  }
  safetyMutex.Signal();
}


BOOL PSafeObject::LockReadOnly() const
{
  safetyMutex.Wait();

  if (safelyBeingRemoved) {
    safetyMutex.Signal();
    return FALSE;
  }

  safetyMutex.Signal();
  safeInUseFlag.StartRead();
  return TRUE;
}


void PSafeObject::UnlockReadOnly() const
{
  safeInUseFlag.EndRead();
}


BOOL PSafeObject::LockReadWrite()
{
  safetyMutex.Wait();

  if (safelyBeingRemoved) {
    safetyMutex.Signal();
    return FALSE;
  }

  safetyMutex.Signal();
  safeInUseFlag.StartWrite();
  return TRUE;
}


void PSafeObject::UnlockReadWrite()
{
  safeInUseFlag.EndWrite();
}


void PSafeObject::SafeRemove()
{
  safetyMutex.Wait();
  safelyBeingRemoved = TRUE;
  safetyMutex.Signal();
}


BOOL PSafeObject::SafelyCanBeDeleted() const
{
  PWaitAndSignal mutex(safetyMutex);
  return safelyBeingRemoved && safeReferenceCount == 0;
}


/////////////////////////////////////////////////////////////////////////////

PSafeLockReadOnly::PSafeLockReadOnly(const PSafeObject & object)
  : safeObject((PSafeObject &)object)
{
  locked = safeObject.LockReadOnly();
}


PSafeLockReadOnly::~PSafeLockReadOnly()
{
  if (locked)
    safeObject.UnlockReadOnly();
}


BOOL PSafeLockReadOnly::Lock()
{
  locked = safeObject.LockReadOnly();
  return locked;
}


void PSafeLockReadOnly::Unlock()
{
  if (locked) {
    safeObject.UnlockReadOnly();
    locked = FALSE;
  }
}



/////////////////////////////////////////////////////////////////////////////

PSafeLockReadWrite::PSafeLockReadWrite(const PSafeObject & object)
  : safeObject((PSafeObject &)object)
{
  locked = safeObject.LockReadWrite();
}


PSafeLockReadWrite::~PSafeLockReadWrite()
{
  if (locked)
    safeObject.UnlockReadWrite();
}


BOOL PSafeLockReadWrite::Lock()
{
  locked = safeObject.LockReadWrite();
  return locked;
}


void PSafeLockReadWrite::Unlock()
{
  if (locked) {
    safeObject.UnlockReadWrite();
    locked = FALSE;
  }
}


/////////////////////////////////////////////////////////////////////////////

PSafeCollection::PSafeCollection(PCollection * coll)
{
  collection = coll;
  collection->DisallowDeleteObjects();
  toBeRemoved.DisallowDeleteObjects();
  deleteObjects = TRUE;
}


PSafeCollection::~PSafeCollection()
{
  deleteObjectsTimer.Stop();

  toBeRemoved.AllowDeleteObjects();
  toBeRemoved.RemoveAll();

  collection->AllowDeleteObjects();
  delete collection;
}


BOOL PSafeCollection::SafeRemove(PSafeObject * obj)
{
  if (obj == NULL)
    return FALSE;

  PWaitAndSignal mutex(collectionMutex);
  if (!collection->Remove(obj))
    return FALSE;

  SafeRemoveObject(obj);
  return TRUE;
}


BOOL PSafeCollection::SafeRemoveAt(PINDEX idx)
{
  PWaitAndSignal mutex(collectionMutex);
  PSafeObject * obj = PDownCast(PSafeObject, collection->RemoveAt(idx));
  if (obj == NULL)
    return FALSE;

  SafeRemoveObject(obj);
  return TRUE;
}


void PSafeCollection::RemoveAll(BOOL synchronous)
{
  collectionMutex.Wait();

  while (collection->GetSize() > 0)
    SafeRemoveObject(PDownCast(PSafeObject, collection->RemoveAt(0)));

  collectionMutex.Signal();

  if (synchronous) {
    // Have unfortunate busy loop here, but it should be very
    // rare that it will be here for long
    while (!DeleteObjectsToBeRemoved())
      PThread::Sleep(100);
  }
}


void PSafeCollection::SafeRemoveObject(PSafeObject * obj)
{
  if (obj == NULL)
    return;

  obj->SafeDereference();

  if (!deleteObjects)
    return;

  obj->SafeRemove();

  removalMutex.Wait();
  toBeRemoved.Append(obj);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -