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