<基于shared_ptr的通用资源池>一文给出了通用资源池的实现, 其中的allocator是通过模板化的构造函数传给ResourcePool的, 并且在内部使用虚函数达到存储和调用allocator的目的. 其实这里可以用boost::function取代模板化的allocator, 从而去掉内部的类继承和虚函数, 从而达到代码上的简化, 更容易理解. 至于性能, 未加测试, 应该差别不大吧, 可能还是原版本更快, 内存占用更少吧, 不过这些对于ResourcePool来说不是太重要.

修改版的ResourcePool接口没有变化

//
// Copyright Qianbin 2011
// http://www.modoohut.com/
// cola.tin.com@gmail.com
// Distributed under the Boost Software License, Version 1.0.
// (See copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include <list>
#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/function.hpp>
namespace lite {
namespace util { 

/// \brief Template resource pool for any resource like file, database connection, etc.
/// It's convenient and efficient to manage resource. It's base on boost.shared_ptr's custom
/// deleter. Call ResourcePool.get to get resource, and the resource will be automatically
/// recycled when the resource pointer no longer referenced.
template<typename R>
struct ResourcePool : boost::noncopyable {
  typedef R ValueType; 
  /// pointer to resource
  typedef boost::shared_ptr<R> ValuePtr;
  typedef boost::function<ValuePtr(void)> Allocator; 

  /// \return count of allocated resources
  size_t size() const {
    return _proxy->size();
  }

  /// \return count of allocated but unused resources
  size_t unused() const {
    return _proxy->unused();
  }

  /// deallocate unused resources
  void shrink() {
    _proxy->shrink();
  }

  /// get resource from pool, or alloc one if no unused in pool
  /// \return resource pointer. null pointer returned only when alloc failed.
  ValuePtr get() {
    ValuePtr res = _proxy->get();
    if(res)
      return ValuePtr(res.get(), Deleter(_proxy, res));
    else
      return res;
  }

  explicit ResourcePool(const Allocator & allocator) :
    _proxy(new Proxy(allocator)) {
  }
private:
  struct Proxy {
    size_t size() const {
      return _size;
    }
    size_t unused() const {
      return _unused;
    }
    void recycle(const ValuePtr & res) {
      boost::mutex::scoped_lock lock(_mutex);
      _pool.push_back(res);
      _unused ++;
    }
    void shrink() {
      PoolType tmp;
      {
        boost::mutex::scoped_lock lock(_mutex);
        tmp.swap(_pool);
        _size -= _unused;
        _unused = 0;
      }
    }
    ValuePtr get() {
      //try to get from pool
      {
        boost::mutex::scoped_lock lock(_mutex);
        if(!_pool.empty()) {
          ValuePtr res = _pool.front();
          _pool.pop_front();
          -- _unused;
          return res;
        }
      }
      //no unused in pool
      // alloc one
      ValuePtr res = _allocator();
      if(res) {
        boost::mutex::scoped_lock lock(_mutex);
        //one alloced, increase count
        ++ _size;
      }
      return res;
    }

    Proxy(const Allocator & allocator):
      _allocator(allocator), _size(0), _unused(0) {
    }
  protected:
    const Allocator _allocator;
    typedef std::list<ValuePtr> PoolType;
    PoolType _pool;
    boost::mutex _mutex;
    size_t _size;
    size_t _unused;
  };
  typedef boost::weak_ptr<Proxy> ProxyWeakPtr;
  typedef boost::shared_ptr<Proxy> ProxyPtr;
  /// \brief A custom deleter of resource pointer to recycle resource
  struct Deleter {
    Deleter(const ProxyWeakPtr & proxy, const ValuePtr & res):
      _proxy(proxy), _res(res)
    {}
    void operator()(void *) {
      /// try lock proxy
      ProxyPtr proxy = _proxy.lock();
      if(proxy)
        proxy->recycle(_res);
      ///else, the resource pool gone. nothing to do, and _res will do the right thing.
    }
  private:
    /// proxy weak pointer
    ProxyWeakPtr _proxy;
    /// the real resource
    ValuePtr _res;
  };
  ProxyPtr _proxy;
};
}
}

下载完整代码