Created
March 22, 2019 23:36
-
-
Save hoffis/1fdfae397b638019c230b22baa108799 to your computer and use it in GitHub Desktop.
Simple session pool
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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