mirror of
https://github.com/rbock/sqlpp11.git
synced 2026-02-18 04:08:47 -06:00
change container to stack of unique_ptr
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
#include <stack>
|
||||
#include <memory>
|
||||
|
||||
namespace sqlpp
|
||||
{
|
||||
@@ -10,74 +11,8 @@ namespace sqlpp
|
||||
private:
|
||||
std::mutex connection_pool_mutex;
|
||||
const std::shared_ptr<Connection_config> config;
|
||||
|
||||
struct async_connection : Connection
|
||||
{
|
||||
async_connection(std::shared_ptr<Connection_config> config)
|
||||
: Connection(config)
|
||||
{}
|
||||
bool is_free = true;
|
||||
};
|
||||
|
||||
std::vector<async_connection> connections;
|
||||
|
||||
unsigned int default_pool_size = 0;
|
||||
unsigned int current_pool_size = 0;
|
||||
unsigned int max_pool_size = 0;
|
||||
|
||||
void resize(unsigned int target_pool_size)
|
||||
{
|
||||
int lock = try_lock(connection_pool_mutex);
|
||||
if (lock == -1)
|
||||
{
|
||||
throw sqlpp::exception("Connection_pool resize should not be called before locking.");
|
||||
connection_pool_mutex.unlock();
|
||||
}
|
||||
else
|
||||
{
|
||||
int diff = current_pool_size - target_pool_size;
|
||||
if (!diff)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// does not guarantee to resize to target_pool_size
|
||||
if (diff > 0)
|
||||
{
|
||||
for (auto it = connections.begin(); it != connections.end();)
|
||||
{
|
||||
if (diff && (*it).is_free)
|
||||
{
|
||||
it = connections.erase(it);
|
||||
diff--;
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (diff < 0)
|
||||
{
|
||||
connections.reserve(target_pool_size);
|
||||
for (int i = 0, count = -diff; i < count; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
connections.push_back(async_connection(config));
|
||||
diff++;
|
||||
}
|
||||
catch (const sqlpp::exception& e)
|
||||
{
|
||||
std::cerr << "Failed to spawn new connection." << std::endl;
|
||||
std::cerr << e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
current_pool_size = target_pool_size + diff;
|
||||
}
|
||||
}
|
||||
std::stack<std::unique_ptr<Connection>> free_connections;
|
||||
|
||||
public:
|
||||
connection_pool(const std::shared_ptr<Connection_config>& config, unsigned int pool_size)
|
||||
@@ -86,11 +21,14 @@ namespace sqlpp
|
||||
std::lock_guard<std::mutex> lock(connection_pool_mutex);
|
||||
try
|
||||
{
|
||||
resize(pool_size);
|
||||
for (int i = 0; i < pool_size; i++)
|
||||
{
|
||||
free_connections.push(std::make_unique<Connection>(config));
|
||||
}
|
||||
}
|
||||
catch (const sqlpp::exception& e)
|
||||
{
|
||||
std::cerr << "Failed to resize connection pool." << std::endl;
|
||||
std::cerr << "Failed to spawn new connection." << std::endl;
|
||||
std::cerr << e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
@@ -100,35 +38,50 @@ namespace sqlpp
|
||||
connection_pool& operator=(const connection_pool&) = delete;
|
||||
connection_pool& operator=(connection_pool&&) = delete;
|
||||
|
||||
std::shared_ptr<Connection> get_connection()
|
||||
std::unique_ptr<Connection> get_connection()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(connection_pool_mutex);
|
||||
for (auto& connection : connections)
|
||||
if (!free_connections.empty())
|
||||
{
|
||||
if (connection.is_free)
|
||||
{
|
||||
connection.is_free = false;
|
||||
return std::shared_ptr<Connection>(static_cast<Connection*>(&connection));
|
||||
}
|
||||
auto connection = std::move(free_connections.top());
|
||||
free_connections.pop();
|
||||
return connection;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
resize(current_pool_size + 1);
|
||||
auto connection = std::make_unique<Connection>(config);
|
||||
return connection;
|
||||
}
|
||||
catch (const sqlpp::exception& e)
|
||||
{
|
||||
std::cerr << "Failed to resize connection pool." << std::endl;
|
||||
std::cerr << "Failed to spawn new connection." << std::endl;
|
||||
std::cerr << e.what() << std::endl;
|
||||
return std::unique_ptr<Connection>();
|
||||
}
|
||||
|
||||
return std::shared_ptr<Connection>(static_cast<Connection*>(&connections.back()));
|
||||
}
|
||||
|
||||
void free_connection(const std::shared_ptr<Connection>& connection)
|
||||
void free_connection(std::unique_ptr<Connection> connection)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(connection_pool_mutex);
|
||||
static_cast<async_connection*>(connection.get())->is_free = true;
|
||||
if (free_connections.size() >= default_pool_size)
|
||||
{
|
||||
// Exceeds default size, do nothing and let unique_ptr self destroy.
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: we don't know if the connection is originally from this connection pool.
|
||||
// There's no way to check because we don't have access to config info in the Connection class:
|
||||
// connection.get()->_handle->config --- _handle is private
|
||||
if (connection.get())
|
||||
{
|
||||
free_connections.push(std::move(connection));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw sqlpp::exception("Trying to free an empty connection.");
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user