Skip to content

Instantly share code, notes, and snippets.

@hoffis
Created March 22, 2019 23:36
Show Gist options
  • Save hoffis/1fdfae397b638019c230b22baa108799 to your computer and use it in GitHub Desktop.
Save hoffis/1fdfae397b638019c230b22baa108799 to your computer and use it in GitHub Desktop.
Simple session pool
#include <algorithm>
#include <cassert>
#include <vector>
#include <mutex>
#include <condition_variable>
#include <memory>
#include <iostream>
template<typename Session, typename Pool>
class SessionWrapper
{
public:
SessionWrapper(Session* s, Pool* p)
: session{s}
, pool{p}
{}
~SessionWrapper()
{
if (pool)
pool->release(session);
}
SessionWrapper(SessionWrapper& other)
: SessionWrapper(other.session, other.pool)
{
other.session = nullptr;
other.pool = nullptr;
}
template<typename T>
auto& operator << (T const& arg)
{
*session << arg;
return *this;
}
private:
Session* session;
Pool* pool;
};
template<typename Session>
class SessionPool
{
public:
template<typename F>
SessionPool(std::size_t n, F&& f)
: no_more_sessions{n == 0}
{
sessions.reserve(n);
for(auto i = 0u; i < n; ++i)
{
sessions.push_back(std::forward<F>(f)());
}
}
SessionPool(SessionPool const&) = delete;
SessionWrapper<Session, SessionPool<Session>> get()
{
std::unique_lock<std::mutex> lock{mx};
if(no_more_sessions)
{
cv.wait(lock, [this] {return !no_more_sessions;});
}
auto it = std::find_if(std::begin(sessions), std::end(sessions), [](auto const& s) {
return s != nullptr;
});
assert(it != std::end(sessions));
return {it->release(), this};
}
void release(Session* session)
{
{
std::unique_lock<std::mutex> lock{mx};
for(auto& s : sessions)
{
if (s == nullptr)
{
s.reset(session);
if(no_more_sessions)
{
no_more_sessions = false;
cv.notify_one();
}
return;
}
}
}
assert(false && "no empty rooms for released session");
}
private:
mutable std::mutex mx;
std::condition_variable cv;
bool no_more_sessions;
std::vector<std::unique_ptr<Session>> sessions;
};
struct Session
{
template<typename T>
auto& operator << (T const& t)
{
return std::cout << t;
}
};
int main()
{
SessionPool<Session> pool{1, []{return std::make_unique<Session>();}};
pool.get() << "SELECT 1" << 23;
auto s = pool.get();
s << "ABC";
s << "XYZ";
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment