![]() |
Nevelex Utilities 1.1.4 09/06/2003 | |
ObjectPool.h00001
00031 /***************************************************************************
00032 ObjectPool.h - Template class used to as the basis for object pooling.
00033 -------------------
00034 Author: Michel Dalal
00035 Date: Mon Sep 23 2002
00036 Copyright: (C) 2002 Nevelex Corporation
00037 ***************************************************************************/
00038
00039 #ifndef OBJECTPOOL_H
00040 #define OBJECTPOOL_H
00041
00042 #include <deque>
00043 #if defined(__GNUG__) && (__GNUG__ >= 3)
00044 #include <ext/hash_set>
00045 #else
00046 #include <hash_set>
00047 #endif
00048 #include <iterator>
00049 #include <stdexcept>
00050 #include <time.h>
00051 #include "ace/Synch.h"
00052 #include "PointerHash.h"
00053 #include "ObjectPoolManager.h"
00054
00062 namespace nevelex_util
00063 {
00092 template <class T>
00093 class ObjectPool: public ManagedPool
00094 {
00095 private:
00097 ACE_Thread_Mutex mutex;
00098
00100 time_t expiresTime;
00101
00107 typedef std::deque<T*> UnlockedDeque;
00108
00114 typedef std::deque<time_t> UnlockedCheckInDeque;
00115
00120 typedef HASH_NAMESPACE::hash_set<T*, PointerHash<T*> > LockedSet;
00121
00125 UnlockedDeque unlocked;
00126
00130 UnlockedCheckInDeque unlockedCheckInTimes;
00131
00135 LockedSet locked;
00136
00146 inline T* createElement()
00147 {
00148 T* t;
00149
00150 // Create a new t object.
00151 t = new T();
00152 if (t == NULL)
00153 {
00154 throw std::runtime_error("Unable to create new object.");
00155 }
00156 return t;
00157 }
00158
00165 void insertElement(T* t)
00166 {
00167 time_t checkInTime;
00168
00169 // Get the time.
00170 checkInTime=time(NULL);
00171 assert(checkInTime != ((time_t)-1));
00172
00173 // Check in the object in to the unlocked deques.
00174 unlockedCheckInTimes.push_back(checkInTime);
00175 unlocked.push_back(t);
00176
00177 #ifdef _DEBUG_LOWLEVEL
00178 cerr << "insertElement(): unlocked.size() = " << unlocked.size() << "; unlockedCheckInTimes.size() = " << unlockedCheckInTimes.size() << "\n";
00179 #endif
00180 }
00181
00190 void addElement()
00191 {
00192 T* t;
00193
00194 // Create a new t object.
00195 t = createElement();
00196
00197 // Add the object to the pool.
00198 insertElement(t);
00199 }
00200
00201 public:
00208 ObjectPool(time_t expiresTime):
00209 mutex(),expiresTime(expiresTime)
00210 {
00211 // Add this object to the ObjectPoolManager for automatic cleanUps.
00212 ObjectPoolManager::addPool(this);
00213 }
00214
00219 virtual ~ObjectPool()
00220 {
00221 T* t;
00222
00223 // Remove this object from the ObjectPoolManager.
00224 ObjectPoolManager::removePool(this);
00225
00226 while (!locked.empty())
00227 {
00228 t = *(locked.begin());
00229 locked.erase(t);
00230 delete t;
00231 }
00232 while (!unlocked.empty())
00233 {
00234 delete unlocked[0];
00235 unlocked.pop_front();
00236 }
00237 //unlocked.clear();
00238 unlockedCheckInTimes.clear();
00239 }
00240
00246 ObjectPool(const ObjectPool<T>& m)
00247 {
00248 expiresTime = m.expiresTime;
00249 unlocked = m.unlocked;
00250 unlockedCheckInTimes = m.unlockedCheckInTimes;
00251 locked = m.locked;
00252 }
00253
00259 const ObjectPool<T>& operator=(const ObjectPool<T>& rhs)
00260 {
00261 // Prevent self assignment
00262 if (&rhs != this)
00263 {
00264 expiresTime=rhs.expiresTime;
00265 unlocked=rhs.unlocked;
00266 unlockedCheckInTimes = rhs.unlockedCheckInTimes;
00267 locked=rhs.locked;
00268 }
00269 return *this;
00270 }
00271
00281 T* checkOut(void)
00282 {
00283 T* t;
00284
00285 ACE_Guard<ACE_Thread_Mutex> guard(mutex);
00286 {
00287 // Entered critical section.
00288
00289 // Add an element to the unlocked pool if needed.
00290 if (unlocked.empty())
00291 {
00292 addElement();
00293 }
00294
00295 // Lock the element.
00296 t = unlocked[0];
00297 locked.insert(t);
00298 assert(locked.find(t) != locked.end());
00299 unlocked.erase(unlocked.begin());
00300 unlockedCheckInTimes.erase(unlockedCheckInTimes.begin());
00301 //assert(unlocked.find(t) == unlocked.end());
00302 } // Leaving critical section
00303
00304 // return the object.
00305 return t;
00306 }
00307
00319 inline T* checkOutFast(void)
00320 {
00321 // return the object.
00322 return createElement();
00323 }
00324
00334 void checkIn(T* object)
00335 {
00336 LockedSet::iterator iterator;
00337
00338 ACE_Guard<ACE_Thread_Mutex> guard(mutex);
00339 {
00340 // Entered critical section.
00341
00342 if ((iterator = locked.find(object)) != locked.end())
00343 {
00344 // Add element to the unlocked list.
00345 insertElement(object);
00346
00347 // Remove from the locked list.
00348 locked.erase(iterator);
00349 assert(locked.find(object) == locked.end());
00350 }
00351 else
00352 {
00353 throw std::runtime_error("Unable to checkIn object.");
00354 }
00355 } // Leaving critical section
00356 }
00357
00368 inline void checkInFast(T* t)
00369 {
00370 // return the object.
00371 delete t;
00372 }
00373
00383 void cleanUp()
00384 {
00385 time_t currentTime;
00386
00387 ACE_Guard<ACE_Thread_Mutex> guard(mutex);
00388 {
00389 // Entered critical section.
00390
00391 // Get the current time.
00392 currentTime = time(NULL);
00393 assert(currentTime != ((time_t) -1));
00394
00395 #ifdef _DEBUG_LOWLEVEL
00396 cerr << "cleanUp(): Starting: unlocked.size() = " << unlocked.size() << "\n";
00397 #endif
00398 // Remove all unneeded objects from the pool.
00399 // An object is unneeded if it has been checked in for longer than
00400 // expiresTime seconds.
00401 while (!unlockedCheckInTimes.empty() && currentTime - unlockedCheckInTimes[0] > expiresTime)
00402 {
00403 #ifdef _DEBUG_LOWLEVEL
00404 cerr << "cleanUp(): Removing Key = " << unlocked[0] << "; Elapsed Time Since checkIn = " << (currentTime - unlockedCheckInTimes[0]) << "\n";
00405 #endif
00406 // Free up the memory associated with the object being erased from the pool
00407 delete unlocked[0];
00408
00409 unlocked.pop_front();
00410 unlockedCheckInTimes.erase(unlockedCheckInTimes.begin());
00411 #ifdef _DEBUG_LOWLEVEL
00412 cerr << "cleanUp(): unlocked.size() = " << unlocked.size() << "; unlockedCheckInTimes.size() = " << unlockedCheckInTimes.size() << "\n";
00413 #endif
00414 }
00415 #ifdef _DEBUG_LOWLEVEL
00416 cerr << "cleanUp(): Ending: unlocked.size() = " << unlocked.size() << "\n";
00417 #endif
00418 } // Leaving critical section
00419 }
00420
00421 #ifdef _DEBUG
00422
00430 void debugTest(size_t totalNum, size_t unlockedNum)
00431 {
00432 LockedSet::iterator iterator1;
00433 size_t i;
00434
00435 ACE_Guard<ACE_Thread_Mutex> guard(mutex);
00436 {
00437 // Entered critical section.
00438
00439 cerr << "===================================================================\n";
00440 cerr << "Dumping Pool State...\n";
00441 cerr << "\tExpecting: Total of " << totalNum << ": Unlocked = " << unlockedNum << "; Locked = " << totalNum-unlockedNum << "\n";
00442 if (unlocked.empty())
00443 {
00444 cerr << " - unlocked: empty\n";
00445 }
00446 else
00447 {
00448 cerr << " - unlocked: size = " << unlocked.size() << "\n";
00449 for (i = 0; i < unlocked.size(); ++i)
00450 {
00451 cerr << "\tKey = " << unlocked[i] << "; Elapsed Time Since checkIn = " << time(NULL) - unlockedCheckInTimes[i] << "\n";
00452 }
00453 //std::copy(unlocked.begin(), unlocked.end(), ostream_iterator<T>(cerr, "\n"));
00454 }
00455
00456 if (locked.empty())
00457 {
00458 cerr << " - locked: empty" << "\n";
00459 }
00460 else
00461 {
00462 cerr << " - locked: size = " << locked.size() << "\n";
00463 for (iterator1 = locked.begin(); iterator1 != locked.end(); iterator1++)
00464 {
00465 cerr << "\t" << *iterator1 << "\n";
00466 }
00467 //std::copy(locked.begin(), locked.end(), ostream_iterator<T>(cerr, "\n"));
00468 }
00469
00470 // Throw exceptions on unexpected results.
00471 if (totalNum != locked.size() + unlocked.size())
00472 {
00473 throw std::runtime_error("Total size does not match.");
00474 }
00475 if (unlockedNum != unlocked.size())
00476 {
00477 throw std::runtime_error("Unlocked size does not match.");
00478 }
00479 if (totalNum - unlockedNum != locked.size())
00480 {
00481 throw std::runtime_error("Locked size does not match.");
00482 }
00483 } // Leaving critical section
00484 }
00485 #endif
00486 };
00487 } // namespace nevelex_util
00488 #endif
|
||
Copyright © 2003. All Rights Reserved. Nevelex Corporation.
Generated: Sat Sep 6 15:54:01 2003