hikyuu2/hikyuu_cpp/hikyuu/data_driver/DriverConnectPool.h

147 lines
4.0 KiB
C++
Raw Normal View History

2021-01-20 00:32:01 +08:00
/*
* Copyright(C) 2021 hikyuu.org
*
* Create on: 2021-01-19
* Author: fasiondog
*/
#pragma once
#include <thread>
#include <mutex>
#include <queue>
#include <memory>
#include "../utilities/Parameter.h"
namespace hku {
/**
*
2021-01-24 20:47:38 +08:00
* @tparam DriverConnectT DriverType *clone()
2021-01-20 00:32:01 +08:00
* @ingroup DataDriver
*/
2021-01-24 20:47:38 +08:00
template <class DriverConnectT>
class DriverConnectPool {
2021-01-20 00:32:01 +08:00
public:
2021-01-24 20:47:38 +08:00
DriverConnectPool() = delete;
DriverConnectPool(const DriverConnectPool &) = delete;
DriverConnectPool &operator=(const DriverConnectPool &) = delete;
typedef typename DriverConnectT::DriverTypePtr DriverPtr;
typedef std::shared_ptr<DriverConnectT> DriverConnectPtr;
2021-01-20 00:32:01 +08:00
/**
*
* @param param pool
* @param maxConnect 0
* @param maxIdleConnect 0 CPU数
2021-01-20 00:32:01 +08:00
*/
2021-01-24 20:47:38 +08:00
explicit DriverConnectPool(const DriverPtr &prototype, size_t maxConnect = 0,
size_t maxIdleConnect = std::thread::hardware_concurrency())
2021-01-20 00:32:01 +08:00
: m_maxSize(maxConnect),
m_maxIdelSize(maxIdleConnect),
m_count(0),
m_prototype(prototype),
m_closer(this) {}
/**
*
*/
2021-01-24 20:47:38 +08:00
virtual ~DriverConnectPool() {
2021-01-20 00:32:01 +08:00
while (!m_driverList.empty()) {
2021-01-24 20:47:38 +08:00
DriverConnectT *p = m_driverList.front();
2021-01-20 00:32:01 +08:00
m_driverList.pop();
if (p) {
delete p;
}
}
}
2021-01-22 23:50:46 +08:00
/** 获取可用连接,如超出允许的最大连接数,将阻塞等待,直到获得空闲资源 */
2021-01-24 20:47:38 +08:00
DriverConnectPtr getConnect() noexcept {
2021-01-22 23:50:46 +08:00
std::unique_lock<std::mutex> lock(m_mutex);
2021-01-20 00:32:01 +08:00
if (m_driverList.empty()) {
if (m_maxSize > 0 && m_count >= m_maxSize) {
2021-01-22 23:50:46 +08:00
m_cond.wait(lock, [this] { return !m_driverList.empty(); });
} else {
m_count++;
2021-01-24 20:47:38 +08:00
return DriverConnectPtr(new DriverConnectT(m_prototype->clone()), m_closer);
2021-01-20 00:32:01 +08:00
}
}
2021-01-24 20:47:38 +08:00
DriverConnectT *p = m_driverList.front();
2021-01-20 00:32:01 +08:00
m_driverList.pop();
2021-01-24 20:47:38 +08:00
return DriverConnectPtr(p, m_closer);
2021-01-20 00:32:01 +08:00
}
DriverPtr getPrototype() {
return m_prototype;
}
/** 当前活动的连接数 */
size_t count() const {
return m_count;
}
/** 当前空闲的资源数 */
size_t idleCount() const {
return m_driverList.size();
}
/** 释放当前所有的空闲资源 */
void releaseIdleConnect() {
std::lock_guard<std::mutex> lock(m_mutex);
while (!m_driverList.empty()) {
2021-01-24 20:47:38 +08:00
DriverConnectT *p = m_driverList.front();
2021-01-20 00:32:01 +08:00
m_driverList.pop();
m_count--;
if (p) {
delete p;
}
}
}
private:
/** 归还至连接池 */
2021-01-24 20:47:38 +08:00
void returnDriver(DriverConnectT *p) {
2021-01-22 23:50:46 +08:00
std::unique_lock<std::mutex> lock(m_mutex);
2021-01-20 00:32:01 +08:00
if (p) {
if (m_driverList.size() < m_maxIdelSize) {
m_driverList.push(p);
2021-01-22 23:50:46 +08:00
m_cond.notify_all();
2021-01-20 00:32:01 +08:00
} else {
delete p;
m_count--;
}
} else {
m_count--;
HKU_WARN("Trying to return an empty pointer!");
}
}
private:
2021-01-24 20:47:38 +08:00
size_t m_maxSize; //允许的最大连接数
size_t m_maxIdelSize; //允许的最大空闲连接数
size_t m_count; //当前活动的连接数
DriverPtr m_prototype; // 驱动原型
2021-01-20 00:32:01 +08:00
std::mutex m_mutex;
2021-01-22 23:50:46 +08:00
std::condition_variable m_cond;
2021-01-24 20:47:38 +08:00
std::queue<DriverConnectT *> m_driverList;
2021-01-20 00:32:01 +08:00
class DriverCloser {
public:
2021-01-24 20:47:38 +08:00
explicit DriverCloser(DriverConnectPool *pool) : m_pool(pool) {}
void operator()(DriverConnectT *conn) {
2021-01-20 00:32:01 +08:00
if (m_pool && conn) {
m_pool->returnDriver(conn);
}
}
private:
2021-01-24 20:47:38 +08:00
DriverConnectPool *m_pool;
2021-01-20 00:32:01 +08:00
};
DriverCloser m_closer;
};
} // namespace hku