1 //******************************************************************* 2 // 3 // License: See top level LICENSE.txt file. 4 // 5 // Author: Garrett Potts 6 // 7 //********************************************************************** 8 // $Id: ossimPool.h 9968 2006-11-29 14:01:53Z gpotts $ 9 #ifndef ossimPool_HEADER 10 #define ossimPool_HEADER 11 #include <iostream> 12 #include <vector> 13 #include <exception> 14 #include <stdexcept> 15 #include <ossim/base/ossimCommon.h> 16 #include <ossim/base/ossimConstants.h> 17 #include <ossim/base/ossimPoolObject.h> 18 #include <ossim/base/ossimNotifyContext.h> 19 20 #define OSSIM_DEFAULT_POOL_SIZE (ossim_uint32)10 21 22 /** 23 * Container pool to be used for things like threads. 24 */ 25 template <class T> 26 class ossimPool 27 { 28 public: 29 /** 30 * Contructor 31 * @param n Number of pooled objects to create. 32 */ throw(std::bad_alloc)33 ossimPool(ossim_uint32 n=OSSIM_DEFAULT_POOL_SIZE) throw(std::bad_alloc) 34 : thePool(n) 35 { 36 for(ossim_uint32 idx = 0; idx < n; ++idx) 37 { 38 try 39 { 40 ossimPoolObject<T>* poolObject = new ossimPoolObject<T>(); 41 poolObject->theAvailableFlag = true; 42 poolObject->theObjectPtr = new T(); 43 thePool[idx] = poolObject; 44 } 45 catch(std::bad_alloc) 46 { 47 ossimNotify(ossimNotifyLevel_FATAL) 48 << "FATAL ossimPool::ossimPool(): Bad allocation" << std::endl; 49 } 50 } 51 } 52 53 /** 54 * Destructor 55 */ ~ossimPool()56 ~ossimPool() 57 { 58 thePool.clear(); 59 } 60 61 /** 62 * @return A pooled object of type T*. Will return null if the pool is 63 * used up or pool size is zero. 64 */ checkout()65 T* checkout() 66 { 67 T* t = NULL; 68 69 theCriticalSectionMutex.lock(); 70 for (ossim_uint32 idx = 0; idx < thePool.size(); ++idx) 71 { 72 if (thePool[idx]->theAvailableFlag == true) 73 { 74 thePool[idx]->theAvailableFlag = false; 75 t = thePool[idx]->theObjectPtr; 76 break; 77 } 78 } 79 theCriticalSectionMutex.unlock(); 80 return t; 81 } 82 83 /** 84 * Resets and eturns object to the pool. 85 * @param obj Object to be returned to the pool. 86 * 87 * @note The object is required to have a "reset()" method. 88 * 89 * @return Returns void unless object was not from pool then throws 90 * a std::out_of_range error. 91 */ checkin(T * obj)92 void checkin(T* obj) throw(std::out_of_range) 93 { 94 theCriticalSectionMutex.lock(); 95 for (ossim_uint32 idx = 0; idx < thePool.size(); ++idx) 96 { 97 if (obj == thePool[idx]->theObjectPtr) 98 { 99 obj->reset(); 100 thePool[idx]->theAvailableFlag = true; 101 theCriticalSectionMutex.unlock(); 102 return; 103 } 104 } 105 106 theCriticalSectionMutex.unlock(); 107 throw std::out_of_range(string("ossimPool<T>::checkin Error Object not managed by this pool!")); 108 } 109 110 /** 111 * Outputs object addresses and theAvailableFlag. 112 */ print(std::ostream & out)113 std::ostream& print(std::ostream& out) const 114 { 115 for (ossim_uint32 idx = 0; idx < thePool.size(); ++idx) 116 { 117 out << "obj address: " << (hex) << thePool[idx]->theObjectPtr 118 << " is " 119 << (thePool[idx]->theAvailableFlag ? "available":"unavailable") 120 << std::endl; 121 } 122 return out; 123 } 124 125 template <class C> friend std::ostream& operator<<(std::ostream& out, 126 const ossimPool<C>& obj) 127 { 128 return obj.print(out); 129 } 130 131 protected: 132 133 std::vector<ossimPoolObject<T>*> thePool; 134 }; 135 136 #endif /* #ifndef ossimPool_HEADER */ 137 138