489 lines
12 KiB
C++
489 lines
12 KiB
C++
// ==========================================================================
|
|
// Class Specification : COXFileWatchNotifier
|
|
// ==========================================================================
|
|
|
|
// Header file : OXFileWatchNotifier.h
|
|
|
|
// Version: 9.3
|
|
|
|
// This software along with its related components, documentation and files ("The Libraries")
|
|
// is © 1994-2007 The Code Project (1612916 Ontario Limited) and use of The Libraries is
|
|
// governed by a software license agreement ("Agreement"). Copies of the Agreement are
|
|
// available at The Code Project (www.codeproject.com), as part of the package you downloaded
|
|
// to obtain this file, or directly from our office. For a copy of the license governing
|
|
// this software, you may contact us at legalaffairs@codeproject.com, or by calling 416-849-8900.
|
|
|
|
// //////////////////////////////////////////////////////////////////////////
|
|
|
|
// Properties:
|
|
// NO Abstract class (does not have any objects)
|
|
// YES Derived from CObject
|
|
|
|
// NO Is a Cwnd.
|
|
// NO Two stage creation (constructor & Create())
|
|
// NO Has a message map
|
|
// NO Needs a resource
|
|
|
|
// NO Persistent objects (saveable on disk)
|
|
// NO Uses exceptions
|
|
|
|
// //////////////////////////////////////////////////////////////////////////
|
|
|
|
// Desciption :
|
|
// This class tread-safe collection assigning an unique ID to each object
|
|
|
|
// Prerequisites (necessary conditions):
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
#ifndef __OXIDMANAGER_H__
|
|
#define __OXIDMANAGER_H__
|
|
|
|
#if _MSC_VER >= 1000
|
|
#pragma once
|
|
#endif // _MSC_VER >= 1000
|
|
|
|
#include "OXDllExt.h"
|
|
|
|
#ifndef __AFXTEMPL_H__
|
|
#error Make sure <AfxTempl.h> is added to your StdAfx.h
|
|
#endif
|
|
#ifndef __AFXMT_H__
|
|
#error Make sure <afxmt.h> is added to your StdAfx.h
|
|
#endif
|
|
|
|
#define INITIAL_SIZE 10
|
|
#define GROW_BY 5
|
|
|
|
|
|
template<class ClassType>
|
|
class COXIDManager : public CObject
|
|
{
|
|
// Data members -------------------------------------------------------------
|
|
public:
|
|
|
|
protected:
|
|
CArray<ClassType*, ClassType*> m_arObjs; // Array of the elements
|
|
CUIntArray m_arFreeIDs; // not assigned ID
|
|
int m_nLastUsedSlot; // last used index in m_arObjs
|
|
CCriticalSection m_crsecGuard;
|
|
|
|
private:
|
|
|
|
// Member functions ---------------------------------------------------------
|
|
public:
|
|
COXIDManager(); // Standard for serialization
|
|
// --- In :
|
|
// --- Out :
|
|
// --- Returns :
|
|
// --- Effect : Constructs the object
|
|
|
|
COXIDManager(int nSize, int nGrowBy);
|
|
// --- In : nSize: initial number of expected Elements
|
|
// nGrowBy: value for correcting the size of the array whet it grows
|
|
// --- Out :
|
|
// --- Returns :
|
|
// --- Effect : Constructs the object
|
|
|
|
UINT AddItem(ClassType* pObj);
|
|
// --- In : pObj: the object to be added
|
|
// --- Out :
|
|
// --- Returns : the ID of the object
|
|
// --- Effect : adds pObj to the ID-Manager and returns a unique ID
|
|
|
|
ClassType* GetItemPtr(UINT nID) ;
|
|
// --- In : nID: the ID of the requested object
|
|
// --- Out :
|
|
// --- Returns : a pointer to the object or NULL if the ID is not valid
|
|
// --- Effect : returns a pointer to the object identified by nID
|
|
|
|
ClassType* RemoveItem(UINT nID);
|
|
// --- In : nID: the ID of the object to be removed
|
|
// --- Out :
|
|
// --- Returns : a pointer to the object or NULL if the ID is not valid
|
|
// --- Effect : returns a pointer to the object identified by nID and
|
|
// removes the object from the Manager.
|
|
// Note: Does not delete the Object !
|
|
|
|
void RemoveAll ();
|
|
// --- In :
|
|
// --- Out :
|
|
// --- Returns :
|
|
// --- Effect : removes all OBJ from the Manager.
|
|
// Note: Does not delete the Objects !
|
|
|
|
void DeleteAll ();
|
|
// --- In :
|
|
// --- Out :
|
|
// --- Returns :
|
|
// --- Effect : Removes all Objects and deletes them
|
|
|
|
int GetHeadPosition() ;
|
|
// --- In :
|
|
// --- Out :
|
|
// --- Returns : the ID of first slot that is not empty
|
|
// --- Effect : returns first slot (for iteration)
|
|
|
|
ClassType* GetNext(int& nPos) ;
|
|
// --- In : nPos: the ID of the current slot
|
|
// --- Out : nPos: the ID of the next non empty slot
|
|
// --- Returns : a pointer to the object at the current slot
|
|
// --- Effect : returns object at slot nPos and calculates next nPos
|
|
|
|
UINT ItemCount();
|
|
// --- In :
|
|
// --- Out :
|
|
// --- Returns : the number if items in the IDManager
|
|
// --- Effect : determines the number of items
|
|
|
|
virtual ~COXIDManager();
|
|
// --- In :
|
|
// --- Out :
|
|
// --- Returns :
|
|
// --- Effect : Object destructor
|
|
|
|
#ifdef _DEBUG
|
|
virtual void AssertValid() ;
|
|
// --- In :
|
|
// --- Out :
|
|
// --- Returns :
|
|
// --- Effect : AssertValid performs a validity check on this object
|
|
// by checking its internal state.
|
|
// In the Debug version of the library, AssertValid may assert and
|
|
// thus terminate the program.
|
|
|
|
virtual void Dump(CDumpContext& dc) ;
|
|
// --- In : dc : The diagnostic dump context for dumping, usually afxDump.
|
|
// --- Out :
|
|
// --- Returns :
|
|
// --- Effect : Dumps the contents of the object to a CDumpContext object.
|
|
// It provides diagnostic services for yourself and
|
|
// other users of your class.
|
|
|
|
#endif
|
|
|
|
protected:
|
|
BOOL _IsIDFree (UINT nSearchID, int& nFoundSlot) ;
|
|
BOOL _IsIDFree (UINT nSearchID) ;
|
|
|
|
private:
|
|
};
|
|
|
|
// Data members -------------------------------------------------------------
|
|
// public:
|
|
|
|
// protected:
|
|
|
|
// CArray<ClassType*, ClassType*> m_arObjs
|
|
// --- Array of the elements
|
|
|
|
// CUIntArray m_arFreeIDs;
|
|
// --- not assigned ID
|
|
|
|
// int m_nLastUsedSlot;
|
|
// --- last used index in m_arObjs
|
|
|
|
// CCriticalSection m_crsecGuard;
|
|
// --- synchronization object
|
|
|
|
// protected:
|
|
|
|
// Member functions ---------------------------------------------------------
|
|
// public:
|
|
|
|
template<class ClassType>
|
|
COXIDManager<ClassType>::COXIDManager()
|
|
{
|
|
m_arObjs.SetSize(INITIAL_SIZE, GROW_BY);
|
|
m_nLastUsedSlot = -1; //no slot in use
|
|
}
|
|
|
|
template<class ClassType>
|
|
COXIDManager<ClassType>::COXIDManager(int nSize, int nGrowBy)
|
|
{
|
|
m_arObjs.SetSize(nSize, nGrowBy);
|
|
m_nLastUsedSlot = -1; //no slot in use
|
|
}
|
|
|
|
template<class ClassType>
|
|
COXIDManager<ClassType>::~COXIDManager()
|
|
{
|
|
// remove all objects from the arrays
|
|
DeleteAll();
|
|
}
|
|
|
|
// ---- public services -----------------------------------
|
|
template<class ClassType>
|
|
UINT COXIDManager<ClassType>::AddItem (ClassType* pObj)
|
|
{
|
|
UINT nID;
|
|
|
|
// Synchronization
|
|
CSingleLock lockObj( &m_crsecGuard);
|
|
lockObj.Lock();
|
|
|
|
// use ID from the FreeID-Array if possible
|
|
if (m_arFreeIDs.GetUpperBound() >= 0)
|
|
{
|
|
//get last element and shorten array by one element
|
|
nID = (UINT) m_arFreeIDs[m_arFreeIDs.GetUpperBound()];
|
|
m_arFreeIDs.RemoveAt(m_arFreeIDs.GetUpperBound());
|
|
m_arFreeIDs.FreeExtra();
|
|
//because IDs in Free-Array are always < m_nLastUsedSlot,
|
|
//wo do not have to correct the m_nLastUsedSlot value
|
|
m_arObjs.SetAt(nID, pObj);
|
|
}
|
|
else
|
|
{
|
|
// set object to m_nLastUsedSlot+1
|
|
m_nLastUsedSlot++;
|
|
nID = m_nLastUsedSlot;
|
|
m_arObjs.SetAtGrow(nID, pObj);
|
|
}
|
|
|
|
return nID; // return the used array-slot
|
|
}
|
|
|
|
template<class ClassType>
|
|
ClassType* COXIDManager<ClassType>::GetItemPtr (UINT nID)
|
|
{
|
|
// Synchronization
|
|
CSingleLock lockObj( &m_crsecGuard);
|
|
lockObj.Lock();
|
|
|
|
//if ID is valid, return Object. Otherwise return NULL
|
|
if ( ((int)nID) >= 0 && ((int)nID) <= m_nLastUsedSlot && !_IsIDFree (nID) )
|
|
{
|
|
return m_arObjs[nID];
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
template<class ClassType>
|
|
ClassType* COXIDManager<ClassType>::RemoveItem (UINT nID)
|
|
{
|
|
ASSERT( ((int)nID) >= 0 && ((int)nID) <= (int)m_nLastUsedSlot);
|
|
ASSERT( !_IsIDFree(nID));
|
|
|
|
// Synchronization
|
|
CSingleLock lockObj( &m_crsecGuard);
|
|
lockObj.Lock();
|
|
|
|
ClassType* pObj;
|
|
pObj = m_arObjs[nID];
|
|
|
|
// check if element is the last one, if so shrink array
|
|
if (nID == (UINT)m_nLastUsedSlot)
|
|
{
|
|
m_arObjs.RemoveAt(nID);
|
|
m_nLastUsedSlot--;
|
|
//find the last used slot using FreeID-Array
|
|
int nFreeID;
|
|
while (_IsIDFree(m_nLastUsedSlot, nFreeID))
|
|
{
|
|
m_nLastUsedSlot--;
|
|
m_arFreeIDs.RemoveAt(nFreeID);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// remove and save free ID
|
|
m_arObjs[nID] = NULL;
|
|
m_arFreeIDs.Add(nID);
|
|
}
|
|
|
|
// Free Memory if Size > UsedSlot * 1.2
|
|
if (m_arObjs.GetSize() > ((m_nLastUsedSlot+1) * 1.2))
|
|
{
|
|
m_arObjs.SetSize((int)((m_nLastUsedSlot+1) * 1.2), (int)((m_nLastUsedSlot+1) * 0.2));
|
|
m_arObjs.FreeExtra();
|
|
}
|
|
|
|
return pObj;
|
|
}
|
|
|
|
template<class ClassType>
|
|
void COXIDManager<ClassType>::RemoveAll()
|
|
{
|
|
// Synchronization
|
|
CSingleLock lockObj( &m_crsecGuard);
|
|
lockObj.Lock();
|
|
|
|
m_arObjs.RemoveAll();
|
|
m_arObjs.SetSize(INITIAL_SIZE, GROW_BY);
|
|
m_arObjs.FreeExtra();
|
|
|
|
m_arFreeIDs.RemoveAll();
|
|
m_arFreeIDs.FreeExtra();
|
|
|
|
m_nLastUsedSlot = -1; //no slot in use
|
|
}
|
|
|
|
template<class ClassType>
|
|
void COXIDManager<ClassType>::DeleteAll()
|
|
{
|
|
// Synchronization
|
|
CSingleLock lockObj( &m_crsecGuard);
|
|
lockObj.Lock();
|
|
|
|
for (int i=0; i <= m_nLastUsedSlot; i++)
|
|
{
|
|
if (m_arObjs[i] != NULL)
|
|
{
|
|
ASSERT_VALID(m_arObjs[i]);
|
|
delete m_arObjs[i];
|
|
}
|
|
}
|
|
m_arObjs.RemoveAll();
|
|
m_arObjs.SetSize(INITIAL_SIZE, GROW_BY);
|
|
m_arObjs.FreeExtra();
|
|
|
|
m_arFreeIDs.RemoveAll();
|
|
m_arFreeIDs.FreeExtra();
|
|
|
|
m_nLastUsedSlot = -1; //no slot in use
|
|
}
|
|
|
|
template<class ClassType>
|
|
int COXIDManager<ClassType>::GetHeadPosition()
|
|
{
|
|
// GetHeadPosition should be used similar to the service of
|
|
// MFC-Lists.
|
|
// So NULL is emty!!
|
|
// +++++ Position == Slot+1 +++++
|
|
|
|
// Synchronization
|
|
CSingleLock lockObj( &m_crsecGuard);
|
|
lockObj.Lock();
|
|
|
|
int nID = 0;
|
|
|
|
while (_IsIDFree(nID))
|
|
nID++;
|
|
|
|
nID = (nID > m_nLastUsedSlot) ? NULL : nID+1;
|
|
|
|
return nID;
|
|
}
|
|
|
|
template<class ClassType>
|
|
ClassType* COXIDManager<ClassType>::GetNext(int& nPos)
|
|
{
|
|
nPos--; //see comment in GetHeadPosition
|
|
|
|
ASSERT(nPos >= 0 && nPos <= m_nLastUsedSlot);
|
|
|
|
// Synchronization
|
|
CSingleLock lockObj( &m_crsecGuard);
|
|
lockObj.Lock();
|
|
|
|
ClassType* pObj = GetItemPtr(nPos);
|
|
|
|
//find next used ID
|
|
nPos++;
|
|
while (_IsIDFree(nPos))
|
|
nPos++;
|
|
nPos = (nPos > m_nLastUsedSlot) ? NULL : nPos+1;
|
|
|
|
return pObj;
|
|
}
|
|
|
|
template<class ClassType>
|
|
UINT COXIDManager<ClassType>::ItemCount()
|
|
{
|
|
return m_nLastUsedSlot-m_arFreeIDs.GetUpperBound();
|
|
}
|
|
|
|
// ---- diagnostics ---------------------------------------
|
|
#ifdef _DEBUG
|
|
template<class ClassType>
|
|
void COXIDManager<ClassType>::AssertValid()
|
|
{
|
|
// Synchronization
|
|
CSingleLock lockObj( &m_crsecGuard);
|
|
lockObj.Lock();
|
|
|
|
CObject::AssertValid();
|
|
|
|
//checks if all Elemets are valid
|
|
for (int i=0; i <= m_arObjs.GetUpperBound(); i++)
|
|
{
|
|
if (m_arObjs[i] != NULL)
|
|
{
|
|
ASSERT_VALID(m_arObjs[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
template<class ClassType>
|
|
void COXIDManager<ClassType>::Dump(CDumpContext& dc)
|
|
{
|
|
// Synchronization
|
|
CSingleLock lockObj( &m_crsecGuard);
|
|
lockObj.Lock();
|
|
|
|
CObject::Dump(dc);
|
|
dc << _T("\nNumber of elements: ");
|
|
dc << m_nLastUsedSlot-m_arFreeIDs.GetUpperBound() << _T("\n");
|
|
|
|
if (dc.GetDepth() > 0)
|
|
{
|
|
int nPos;
|
|
nPos = GetHeadPosition();
|
|
while (nPos != 0)
|
|
{
|
|
dc << _T("\tID: ") << nPos;
|
|
dc << _T("\t Element: ");
|
|
GetNext(nPos)->Dump(dc);
|
|
}
|
|
}
|
|
|
|
}
|
|
#endif // _DEBUG
|
|
|
|
|
|
// protected:
|
|
|
|
template<class ClassType>
|
|
BOOL COXIDManager<ClassType>::_IsIDFree (UINT nSearchID, int& nFoundSlot)
|
|
// --- In : nSearchID: the ID to be checked
|
|
// --- Out : nFoundSlot: the position of the ID
|
|
// --- Returns : TRUE if the ID is free
|
|
// --- Effect : searchs for nSearchID in the Free-ID Array.
|
|
// If so, nFoundSlot returns the index from the slot.
|
|
{
|
|
int i;
|
|
|
|
// Synchronization
|
|
CSingleLock lockObj( &m_crsecGuard);
|
|
lockObj.Lock();
|
|
|
|
for ( i=0; i <= m_arFreeIDs.GetUpperBound(); i++)
|
|
{
|
|
if (m_arFreeIDs[i] == nSearchID)
|
|
{
|
|
nFoundSlot = i;
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
template<class ClassType>
|
|
BOOL COXIDManager<ClassType>::_IsIDFree (UINT nSearchID)
|
|
// --- In : nSearchID: the ID to be checked
|
|
// --- Out :
|
|
// --- Returns : TRUE if the ID is free
|
|
// --- Effect : searchs for nSearchID in the Free-ID Array.
|
|
{
|
|
// searchs for nSearchID in the Free-ID Array.
|
|
|
|
int i;
|
|
return _IsIDFree(nSearchID, i);
|
|
}
|
|
|
|
// private:
|
|
|
|
#endif // __OXIDMANAGER_H__
|