Skip to content
This repository was archived by the owner on Mar 7, 2023. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
220 changes: 110 additions & 110 deletions ConnectionPool.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,180 +19,180 @@
*
* Connection and ConnectionFactory are virtual classes that should be overridden to their actual type.
*
* NOTE: To avoid using templates AND inheritance at the same time in the ConnectionFactory, ConnectionFactory::create must create a derved type
* but return the base class.
* NOTE: To avoid using templates AND inheritance at the same time in the ConnectionFactory, ConnectionFactory::create must create a derved type
* but return the base class.
*/

#pragma once

// Define your custom logging function by overriding this #define
#ifndef _DEBUG
#define _DEBUG(x)
#define _DEBUG(x)
#endif



#include <deque>
#include <set>
#include <boost/shared_ptr.hpp>
#include <boost/thread/mutex.hpp>
#include <exception>
#include <string>
using namespace std;
using boost::shared_ptr;
#include <mutex>
#include <thread>

namespace active911 {


struct ConnectionUnavailable : std::exception {
struct ConnectionUnavailable : std::exception {

char const *what() const throw() {

char const* what() const throw() {
return "Unable to allocate connection";
};
};

return "Unable to allocate connection";
};
};

class Connection {

class Connection {
public:
Connection() {};

public:
Connection(){};
virtual ~Connection(){};
virtual ~Connection() {};

};
};

class ConnectionFactory {
class ConnectionFactory {

public:
virtual shared_ptr<Connection> create()=0;
};
public:
virtual std::shared_ptr<Connection> create()=0;
};

struct ConnectionPoolStats {
struct ConnectionPoolStats {

size_t pool_size;
size_t borrowed_size;
size_t pool_size;
size_t borrowed_size;

};
};

template<class T>
class ConnectionPool {
template<class T>
class ConnectionPool {

public:
public:

ConnectionPoolStats get_stats() {
ConnectionPoolStats get_stats() {

// Lock
boost::mutex::scoped_lock lock(this->io_mutex);
// Lock
std::lock_guard<std::mutex> lock(this->io_mutex);

// Get stats
ConnectionPoolStats stats;
stats.pool_size=this->pool.size();
stats.borrowed_size=this->borrowed.size();
// Get stats
ConnectionPoolStats stats;
stats.pool_size = this->pool.size();
stats.borrowed_size = this->borrowed.size();

return stats;
};
return stats;
};

ConnectionPool(size_t pool_size, shared_ptr<ConnectionFactory> factory){
ConnectionPool(size_t pool_size, std::shared_ptr<ConnectionFactory> factory) {

// Setup
this->pool_size=pool_size;
this->factory=factory;
// Setup
this->pool_size = pool_size;
this->factory = factory;

// Fill the pool
while(this->pool.size() < this->pool_size){
// Fill the pool
while (this->pool.size() < this->pool_size) {

this->pool.push_back(this->factory->create());
}
this->pool.push_back(this->factory->create());
}


};
};

~ConnectionPool() {
~ConnectionPool() {


};
};

/**
* Borrow
*
* Borrow a connection for temporary use
*
* When done, either (a) call unborrow() to return it, or (b) (if it's bad) just let it go out of scope. This will cause it to automatically be replaced.
* @retval a shared_ptr to the connection object
*/
shared_ptr<T> borrow(){
/**
* Borrow
*
* Borrow a connection for temporary use
*
* When done, either (a) call unborrow() to return it, or (b) (if it's bad) just let it go out of scope. This will cause it to automatically be replaced.
* @retval a shared_ptr to the connection object
*/
std::shared_ptr<T> borrow() {

// Lock
boost::mutex::scoped_lock lock(this->io_mutex);
// Lock
std::lock_guard<std::mutex> lock(this->io_mutex);

// Check for a free connection
if(this->pool.size()==0){
// Check for a free connection
if (this->pool.size() == 0) {

// Are there any crashed connections listed as "borrowed"?
for(std::set<shared_ptr<Connection> >::iterator it=this->borrowed.begin(); it!=this->borrowed.end(); ++it){
// Are there any crashed connections listed as "borrowed"?
for (std::set<std::shared_ptr<Connection>>::iterator it = this->borrowed.begin();
it != this->borrowed.end(); ++it) {

if((*it).unique()) {
if ((*it).unique()) {

// This connection has been abandoned! Destroy it and create a new connection
try {
// This connection has been abandoned! Destroy it and create a new connection
try {

// If we are able to create a new connection, return it
_DEBUG("Creating new connection to replace discarded connection");
shared_ptr<Connection> conn=this->factory->create();
this->borrowed.erase(it);
this->borrowed.insert(conn);
return boost::static_pointer_cast<T>(conn);
// If we are able to create a new connection, return it
_DEBUG("Creating new connection to replace discarded connection");
std::shared_ptr<Connection> conn = this->factory->create();

} catch(std::exception& e) {
this->borrowed.erase(it);
this->borrowed.insert(conn);

// Error creating a replacement connection
throw ConnectionUnavailable();
}
}
}
return std::static_pointer_cast<T>(conn);

// Nothing available
throw ConnectionUnavailable();
}
} catch (std::exception &e) {

// Take one off the front
shared_ptr<Connection>conn=this->pool.front();
this->pool.pop_front();
// Error creating a replacement connection
throw ConnectionUnavailable();
}
}
}

// Add it to the borrowed list
this->borrowed.insert(conn);
// Nothing available
throw ConnectionUnavailable();
}

return boost::static_pointer_cast<T>(conn);
};
// Take one off the front
std::shared_ptr<Connection> conn = this->pool.front();
this->pool.pop_front();

/**
* Unborrow a connection
*
* Only call this if you are returning a working connection. If the connection was bad, just let it go out of scope (so the connection manager can replace it).
* @param the connection
*/
void unborrow(shared_ptr<T> conn) {
// Add it to the borrowed list
this->borrowed.insert(conn);

// Lock
boost::mutex::scoped_lock lock(this->io_mutex);
return std::static_pointer_cast<T>(conn);
};

// Push onto the pool
this->pool.push_back(boost::static_pointer_cast<Connection>(conn));
/**
* Unborrow a connection
*
* Only call this if you are returning a working connection. If the connection was bad, just let it go out of scope (so the connection manager can replace it).
* @param the connection
*/
void unborrow(std::shared_ptr<T> conn) {

// Unborrow
this->borrowed.erase(conn);
// Lock
std::lock_guard<std::mutex> lock(this->io_mutex);

};
// Push onto the pool
this->pool.push_back(std::static_pointer_cast<Connection>(conn));

protected:
shared_ptr<ConnectionFactory> factory;
size_t pool_size;
deque<shared_ptr<Connection> > pool;
set<shared_ptr<Connection> > borrowed;
boost::mutex io_mutex;
// Unborrow
this->borrowed.erase(conn);

};
};

protected:
std::shared_ptr<ConnectionFactory> factory;
size_t pool_size;
std::deque<std::shared_ptr<Connection>> pool;
std::set<std::shared_ptr<Connection>> borrowed;
std::mutex io_mutex;

};


}
52 changes: 25 additions & 27 deletions DummyConnection.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,58 +13,56 @@
* limitations under the License.
*/

#pragma once

#include "ConnectionPool.h"
using boost::shared_ptr;

namespace active911 {


class DummyConnection : public Connection {

public:

DummyConnection() {

_DEBUG("Dummy connection created");
class DummyConnection : public Connection {

};
public:

~DummyConnection() {
DummyConnection() {

// Destroy the connection
_DEBUG("Dummy connection created");

_DEBUG("Dummy connection destroyed");
};

};
~DummyConnection() {

// shared_ptr to some kind of actual connection object would go here
// Destroy the connection

};
_DEBUG("Dummy connection destroyed");

};

class DummyConnectionFactory : public ConnectionFactory {
// shared_ptr to some kind of actual connection object would go here

public:
DummyConnectionFactory() {
};


};
class DummyConnectionFactory : public ConnectionFactory {

// Any exceptions thrown here should be caught elsewhere
shared_ptr<Connection> create() {
public:
DummyConnectionFactory() {

// Create the connection
shared_ptr<DummyConnection>conn(new DummyConnection());

// Perform some kind of ->connect operation here
};

return boost::static_pointer_cast<Connection>(conn);
};
// Any exceptions thrown here should be caught elsewhere
std::shared_ptr<Connection> create() {

};
// Create the connection
std::shared_ptr<DummyConnection> conn(new DummyConnection());

// Perform some kind of ->connect operation here

return std::static_pointer_cast<Connection>(conn);
};

};


}
Loading