00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifndef POOL_HPP
00026 #define POOL_HPP
00027
00028
00029 #include <mapnik/utils.hpp>
00030
00031 #include <boost/shared_ptr.hpp>
00032 #include <boost/utility.hpp>
00033
00034 #ifdef MAPNIK_THREADSAFE
00035 #include <boost/thread/mutex.hpp>
00036 #endif
00037
00038
00039 #include <iostream>
00040 #include <map>
00041 #include <deque>
00042 #include <ctime>
00043
00044 namespace mapnik
00045 {
00046 template <typename T, typename PoolT>
00047 class PoolGuard
00048 {
00049 private:
00050 const T& obj_;
00051 PoolT& pool_;
00052 public:
00053 explicit PoolGuard(const T& ptr,PoolT& pool)
00054 : obj_(ptr),
00055 pool_(pool) {}
00056
00057 ~PoolGuard()
00058 {
00059 pool_->returnObject(obj_);
00060 }
00061
00062 private:
00063 PoolGuard();
00064 PoolGuard(const PoolGuard&);
00065 PoolGuard& operator=(const PoolGuard&);
00066 };
00067
00068 template <typename T,template <typename> class Creator>
00069 class Pool : private boost::noncopyable
00070 {
00071 typedef boost::shared_ptr<T> HolderType;
00072 typedef std::deque<HolderType> ContType;
00073
00074 Creator<T> creator_;
00075 const unsigned initialSize_;
00076 const unsigned maxSize_;
00077 ContType usedPool_;
00078 ContType unusedPool_;
00079 #ifdef MAPNIK_THREADSAFE
00080 mutable boost::mutex mutex_;
00081 #endif
00082 public:
00083
00084 Pool(const Creator<T>& creator,unsigned initialSize=1, unsigned maxSize=10)
00085 :creator_(creator),
00086 initialSize_(initialSize),
00087 maxSize_(maxSize)
00088 {
00089 for (unsigned i=0; i < initialSize_; ++i)
00090 {
00091 HolderType conn(creator_());
00092 if (conn->isOK())
00093 unusedPool_.push_back(conn);
00094 }
00095 }
00096
00097 HolderType borrowObject()
00098 {
00099 #ifdef MAPNIK_THREADSAFE
00100 mutex::scoped_lock lock(mutex_);
00101 #endif
00102 typename ContType::iterator itr=unusedPool_.begin();
00103 if (itr!=unusedPool_.end())
00104 {
00105 #ifdef MAPNIK_DEBUG
00106 std::clog<<"borrow "<<(*itr).get()<<"\n";
00107 #endif
00108 usedPool_.push_back(*itr);
00109 itr=unusedPool_.erase(itr);
00110 return usedPool_[usedPool_.size()-1];
00111 }
00112 else if (unusedPool_.size() < maxSize_)
00113 {
00114 HolderType conn(creator_());
00115 if (conn->isOK())
00116 {
00117 usedPool_.push_back(conn);
00118 #ifdef MAPNIK_DEBUG
00119 std::clog << "create << " << conn.get() << "\n";
00120 #endif
00121 return conn;
00122 }
00123 }
00124 return HolderType();
00125 }
00126
00127 void returnObject(HolderType obj)
00128 {
00129 #ifdef MAPNIK_THREADSAFE
00130 mutex::scoped_lock lock(mutex_);
00131 #endif
00132 typename ContType::iterator itr=usedPool_.begin();
00133 while (itr != usedPool_.end())
00134 {
00135 if (obj.get()==(*itr).get())
00136 {
00137 #ifdef MAPNIK_DEBUG
00138 std::clog<<"return "<<(*itr).get()<<"\n";
00139 #endif
00140 unusedPool_.push_back(*itr);
00141 usedPool_.erase(itr);
00142 return;
00143 }
00144 ++itr;
00145 }
00146 }
00147
00148 std::pair<unsigned,unsigned> size() const
00149 {
00150 #ifdef MAPNIK_THREADSAFE
00151 mutex::scoped_lock lock(mutex_);
00152 #endif
00153 std::pair<unsigned,unsigned> size(unusedPool_.size(),usedPool_.size());
00154 return size;
00155 }
00156 };
00157 }
00158 #endif //POOL_HPP