mapnik/include/mapnik/pool.hpp

184 lines
4.6 KiB
C++
Raw Normal View History

/*****************************************************************************
2012-02-02 02:53:35 +01:00
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2011 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
#ifndef MAPNIK_POOL_HPP
#define MAPNIK_POOL_HPP
2007-10-08 20:10:31 +02:00
// mapnik
2012-04-08 02:20:56 +02:00
#include <mapnik/debug.hpp>
2007-10-08 20:10:31 +02:00
#include <mapnik/utils.hpp>
2007-10-08 20:10:31 +02:00
// boost
#include <boost/shared_ptr.hpp>
#include <boost/utility.hpp>
2008-02-04 17:12:13 +01:00
#ifdef MAPNIK_THREADSAFE
#include <boost/thread/mutex.hpp>
#endif
// stl
#include <iostream>
#include <map>
#include <deque>
#include <ctime>
namespace mapnik
{
2010-06-02 13:03:30 +02:00
template <typename T, typename PoolT>
class PoolGuard
{
private:
const T& obj_;
2012-02-02 02:53:35 +01:00
PoolT& pool_;
2010-06-02 13:03:30 +02:00
public:
explicit PoolGuard(const T& ptr,PoolT& pool)
: obj_(ptr),
pool_(pool) {}
2012-02-02 02:53:35 +01:00
~PoolGuard()
2010-06-02 13:03:30 +02:00
{
pool_->returnObject(obj_);
}
2010-06-02 13:03:30 +02:00
private:
PoolGuard();
PoolGuard(const PoolGuard&);
PoolGuard& operator=(const PoolGuard&);
};
2010-06-02 13:03:30 +02:00
template <typename T,template <typename> class Creator>
class Pool : private boost::noncopyable
{
typedef boost::shared_ptr<T> HolderType;
2012-02-02 02:53:35 +01:00
typedef std::deque<HolderType> ContType;
2010-06-02 13:03:30 +02:00
Creator<T> creator_;
2012-02-02 02:53:35 +01:00
const unsigned initialSize_;
2012-11-28 18:04:12 +01:00
unsigned maxSize_;
2010-06-02 13:03:30 +02:00
ContType usedPool_;
ContType unusedPool_;
2008-02-04 17:12:13 +01:00
#ifdef MAPNIK_THREADSAFE
2010-06-02 13:03:30 +02:00
mutable boost::mutex mutex_;
2008-02-04 17:12:13 +01:00
#endif
2010-06-02 13:03:30 +02:00
public:
Pool(const Creator<T>& creator,unsigned initialSize, unsigned maxSize)
2010-06-02 13:03:30 +02:00
:creator_(creator),
initialSize_(initialSize),
maxSize_(maxSize)
{
2012-02-02 02:53:35 +01:00
for (unsigned i=0; i < initialSize_; ++i)
2010-06-02 13:03:30 +02:00
{
HolderType conn(creator_());
if (conn->isOK())
unusedPool_.push_back(conn);
}
}
2010-06-02 13:03:30 +02:00
HolderType borrowObject()
2012-02-02 02:53:35 +01:00
{
#ifdef MAPNIK_THREADSAFE
2010-06-02 13:03:30 +02:00
mutex::scoped_lock lock(mutex_);
2008-02-04 17:12:13 +01:00
#endif
2010-06-02 13:03:30 +02:00
typename ContType::iterator itr=unusedPool_.begin();
2011-09-01 21:21:03 +02:00
while ( itr!=unusedPool_.end())
2012-02-02 02:53:35 +01:00
{
MAPNIK_LOG_DEBUG(pool) << "pool: Borrow instance=" << (*itr).get();
if ((*itr)->isOK())
{
usedPool_.push_back(*itr);
unusedPool_.erase(itr);
return usedPool_.back();
}
else
{
MAPNIK_LOG_DEBUG(pool) << "pool: Bad connection (erase) instance=" << (*itr).get();
2011-09-01 21:21:03 +02:00
itr=unusedPool_.erase(itr);
}
2010-06-02 13:03:30 +02:00
}
// all connection have been taken, check if we allowed to grow pool
if (usedPool_.size() < maxSize_)
2010-06-02 13:03:30 +02:00
{
HolderType conn(creator_());
if (conn->isOK())
{
2010-06-02 13:03:30 +02:00
usedPool_.push_back(conn);
MAPNIK_LOG_DEBUG(pool) << "pool: Create connection=" << conn.get();
2010-06-02 13:03:30 +02:00
return conn;
}
2010-06-02 13:03:30 +02:00
}
return HolderType();
2012-02-02 02:53:35 +01:00
}
2010-06-02 13:03:30 +02:00
void returnObject(HolderType obj)
{
2008-02-04 17:12:13 +01:00
#ifdef MAPNIK_THREADSAFE
2010-06-02 13:03:30 +02:00
mutex::scoped_lock lock(mutex_);
2008-02-04 17:12:13 +01:00
#endif
2010-06-02 13:03:30 +02:00
typename ContType::iterator itr=usedPool_.begin();
while (itr != usedPool_.end())
{
2012-02-02 02:53:35 +01:00
if (obj.get()==(*itr).get())
{
MAPNIK_LOG_DEBUG(pool) << "pool: Return instance=" << (*itr).get();
2010-06-02 13:03:30 +02:00
unusedPool_.push_back(*itr);
usedPool_.erase(itr);
return;
}
2010-06-02 13:03:30 +02:00
++itr;
}
}
2012-02-02 02:53:35 +01:00
2010-06-02 13:03:30 +02:00
std::pair<unsigned,unsigned> size() const
{
2008-02-04 17:12:13 +01:00
#ifdef MAPNIK_THREADSAFE
2010-06-02 13:03:30 +02:00
mutex::scoped_lock lock(mutex_);
2008-02-04 17:12:13 +01:00
#endif
2010-06-02 13:03:30 +02:00
std::pair<unsigned,unsigned> size(unusedPool_.size(),usedPool_.size());
return size;
}
2012-11-28 18:04:12 +01:00
unsigned max_size() const
{
#ifdef MAPNIK_THREADSAFE
mutex::scoped_lock lock(mutex_);
#endif
return maxSize_;
}
void set_max_size(unsigned size)
{
#ifdef MAPNIK_THREADSAFE
mutex::scoped_lock lock(mutex_);
#endif
maxSize_ = size;
}
2010-06-02 13:03:30 +02:00
};
}
#endif // MAPNIK_POOL_HPP