#include <string>
#include <list>
#include <iostream>
#include <stdexcept>
#include <memory>
using namespace std;
class Connection {
std::string name;
public:
const std::string& getName() const { return name; }
explicit Connection(const std::string& n):name(n) {
std::cout << "Connection " << name << std::endl;
}
~Connection() {
name = '~' + name;
std::cout << "~Connection " << name << std::endl;
}
};
typedef shared_ptr<Connection> ptr_t;
class ConnectionPool {
std::list<ptr_t> connections;
// Этот класс предназначен для демонстрации первого варианта создания deleter (get1)
class ConnectionReleaser {
std::list<ptr_t>& whereToReturn;
ptr_t connectionToRelease;
public:
ConnectionReleaser(std::list<ptr_t>& lst, const ptr_t& x):whereToReturn(lst), connectionToRelease(x) {}
~ConnectionReleaser()
{
cout << "~ConnectionReleaser()" << endl;
cout << connectionToRelease.get() << endl;
if (0 == connectionToRelease.get())
{
cout << "NULL" << endl;
}
else
{
cout << connectionToRelease->getName() << endl;
}
}
void operator()(Connection*) {
whereToReturn.push_back( connectionToRelease );
std::cout << "get1: Returned connection " << connectionToRelease->getName() << " to the list" << std::endl;
// Закомментируйте след. строку и обратите внимание на разницу в выходной печати
//connectionToRelease.reset();
}
};
// Эта функция предназначена для демонстрации второго варианта создания deleter (get2)
static void releaseConnection(std::list<ptr_t>& whereToReturn, ptr_t& connectionToRelease) {
whereToReturn.push_back( connectionToRelease );
std::cout << "get2: Returned connection " << connectionToRelease->getName() << " to the list" << std::endl;
// Закомментируйте следующую строку и обратите внимание на разницу в выходной печати
connectionToRelease.reset();
}
ptr_t popConnection() {
if( connections.empty() ) throw std::runtime_error("No connections left");
ptr_t w( connections.back() );
connections.pop_back();
return w;
}
public:
ptr_t get1() {
ptr_t w = popConnection();
std::cout << "get1: Taken connection " << w->getName() << " from list" << std::endl;
ptr_t r( w.get(), ConnectionReleaser( connections, w ) );
return r;
}
ptr_t get2() {
ptr_t w = popConnection();
std::cout << "get2: Taken connection " << w->getName() << " from list" << std::endl;
ptr_t r( w.get(), bind(&releaseConnection, ref(connections), w ));
return r;
}
void add(const std::string& name) {
connections.push_back( ptr_t(new Connection(name)) );
}
ConnectionPool() {
std::cout << "ConnectionPool" << std::endl;
}
~ConnectionPool() {
std::cout << "~ConnectionPool" << std::endl;
}
};
int main() {
weak_ptr<Connection> weak1;
weak_ptr<Connection> weak2;
{
ConnectionPool cp;
cp.add("One");
cp.add("Two");
ptr_t p1 = cp.get1();
weak1 = p1;
//ptr_t p2 = cp.get2();
//weak2 = p2;
}
std::cout << "weak1.expired()" << weak1.expired() << endl;
std::cout << "Here the ConnectionPool is out of scope, but weak_ptrs are not" << std::endl;
return 0;
}