1. register singleton destruction with std::atexit

2. allow connection pool to grow (up to max)
This commit is contained in:
Artem Pavlenko 2006-11-27 21:13:15 +00:00
parent 6ebe6dab07
commit f4502df850
5 changed files with 45 additions and 87 deletions

View File

@ -68,25 +68,25 @@ namespace mapnik
typedef std::deque<HolderType> ContType;
Creator<T> creator_;
const int initialSize_;
const int maxSize_;
const unsigned initialSize_;
const unsigned maxSize_;
ContType usedPool_;
ContType unusedPool_;
boost::mutex mutex_;
public:
Pool(const Creator<T>& creator,int initialSize=5,int maxSize=20)
Pool(const Creator<T>& creator,unsigned initialSize=1, unsigned maxSize=10)
:creator_(creator),
initialSize_(initialSize),
maxSize_(maxSize)
{
for (int i=0;i<initialSize_;++i)
for (unsigned i=0; i < initialSize_; ++i)
{
unusedPool_.push_back(HolderType(creator_()));
}
}
const HolderType& borrowObject()
HolderType borrowObject()
{
mutex::scoped_lock lock(mutex_);
typename ContType::iterator itr=unusedPool_.begin();
@ -99,11 +99,20 @@ namespace mapnik
itr=unusedPool_.erase(itr);
return usedPool_[usedPool_.size()-1];
}
static const HolderType defaultObj;
return defaultObj;
else if (unusedPool_.size() < maxSize_)
{
HolderType conn(creator_());
usedPool_.push_back(conn);
#ifdef MAPNIK_DEBUG
std::clog << "create << " << conn.get() << "\n";
#endif
return conn;
}
return HolderType();
}
void returnObject(const HolderType& obj)
void returnObject(HolderType obj)
{
mutex::scoped_lock lock(mutex_);
typename ContType::iterator itr=usedPool_.begin();

View File

@ -22,6 +22,7 @@
#define UTILS_HPP
// stl
#include <stdexcept>
#include <cstdlib>
#include <limits>
#include <ctime>
#include <sstream>
@ -66,18 +67,21 @@ namespace mapnik
int Test::* pMember_;
int (Test::*pMemberFn_)(int);
};
public:
static T* create()
{
static MaxAlign staticMemory;
return new(&staticMemory) T;
}
static void destroy(volatile T* obj)
{
obj->~T();
}
};
template <typename T,
template <typename T> class CreatePolicy=CreateStatic> class singleton
{
@ -90,14 +94,20 @@ namespace mapnik
{
throw std::runtime_error("dead reference!");
}
static void DestroySingleton()
{
CreatePolicy<T>::destroy(pInstance_);
pInstance_ = 0;
destroyed_=true;
#ifdef MAPNIK_DEBUG
std::clog << " destroyed singleton \n";
#endif
}
protected:
static mutex mutex_;
singleton() {}
virtual ~singleton()
{
CreatePolicy<T>::destroy(pInstance_);
destroyed_=true;
}
public:
static T* instance()
{
@ -113,6 +123,8 @@ namespace mapnik
else
{
pInstance_=CreatePolicy<T>::create();
// register destruction
std::atexit(&DestroySingleton);
}
}
}
@ -126,72 +138,7 @@ namespace mapnik
template <typename T> class CreatePolicy> T* singleton<T,CreatePolicy>::pInstance_=0;
template <typename T,
template <typename T> class CreatePolicy> bool singleton<T,CreatePolicy>::destroyed_=false;
template <class T> class Handle
{
T* ptr_;
int* pCount_;
public:
T* operator->() {return ptr_;}
const T* operator->() const {return ptr_;}
Handle(T* ptr)
:ptr_(ptr),pCount_(new int(1)) {}
Handle(const Handle& rhs)
:ptr_(rhs.ptr_),pCount_(rhs.pCount_)
{
(*pCount_)++;
}
Handle& operator=(const Handle& rhs)
{
if (ptr_==rhs.ptr_) return *this;
if (--(*pCount_)==0)
{
delete ptr_;
delete pCount_;
}
ptr_=rhs.ptr_;
pCount_=rhs.pCount_;
(*pCount_)++;
return *this;
}
~Handle()
{
if (--(*pCount_)==0)
{
delete ptr_;
delete pCount_;
}
}
};
//converters
class BadConversion : public std::runtime_error
{
public:
BadConversion(const std::string& s)
:std::runtime_error(s)
{}
};
template <typename T>
inline std::string toString(const T& x)
{
std::ostringstream o;
if (!(o << x))
throw BadConversion(std::string("toString(")
+ typeid(x).name() + ")");
return o.str();
}
template<typename T>
inline void fromString(const std::string& s, T& x,
bool failIfLeftoverChars = true)
{
std::istringstream i(s);
char c;
if (!(i >> x) || (failIfLeftoverChars && i.get(c)))
throw BadConversion("fromString("+s+")");
}
}

View File

@ -89,6 +89,9 @@ public:
~Connection()
{
PQfinish(conn_);
#ifdef MAPNIK_DEBUG
std::clog << "close connection " << conn_ << "\n";
#endif
}
};

View File

@ -76,7 +76,7 @@ class ConnectionManager : public singleton <ConnectionManager,CreateStatic>
public:
bool registerPool(const ConnectionCreator<Connection>& creator,int initialSize,int maxSize)
bool registerPool(const ConnectionCreator<Connection>& creator,unsigned initialSize,unsigned maxSize)
{
mutex::scoped_lock lock(mutex_);
if (pools_.find(creator.id())==pools_.end())
@ -89,7 +89,7 @@ public:
}
const boost::shared_ptr<PoolType>& getPool(const std::string& key)
boost::shared_ptr<PoolType> getPool(std::string const& key)
{
mutex::scoped_lock lock(mutex_);
ContType::const_iterator itr=pools_.find(key);
@ -101,7 +101,7 @@ public:
return emptyPool;
}
const HolderType& get(const std::string& key)
HolderType get(std::string const& key)
{
mutex::scoped_lock lock(mutex_);
ContType::const_iterator itr=pools_.find(key);
@ -110,10 +110,9 @@ public:
boost::shared_ptr<PoolType> pool=itr->second;
return pool->borrowObject();
}
static const HolderType EmptyConn;
return EmptyConn;
return HolderType();
}
private:
ConnectionManager() {}
ConnectionManager(const ConnectionManager&);

View File

@ -54,7 +54,7 @@ postgis_datasource::postgis_datasource(parameters const& params)
params.get("password"))
{
ConnectionManager *mgr=ConnectionManager::instance();
mgr->registerPool(creator_,10,20);
mgr->registerPool(creator_,5,10);
shared_ptr<Pool<Connection,ConnectionCreator> > pool=mgr->getPool(creator_.id());
if (pool)