include/ylt/standalone/cinatra/session_manager.hpp (93 lines of code) (raw):
#pragma once
#include <asio/steady_timer.hpp>
#include <atomic>
#include <chrono>
#include <string>
#include "session.hpp"
#include "ylt/coro_io/coro_io.hpp"
namespace cinatra {
class session_manager {
public:
static session_manager &get() {
static session_manager instance;
return instance;
}
std::string generate_session_id() {
auto tp = std::chrono::high_resolution_clock::now();
auto nano = tp.time_since_epoch().count();
id_++;
return std::to_string(nano).append(std::to_string(id_));
}
std::shared_ptr<session> get_session(const std::string &session_id) {
std::unique_lock<std::mutex> lock(mtx_);
std::shared_ptr<session> new_session = nullptr;
auto iter = map_.find(session_id);
if (iter != map_.end()) {
return iter->second;
}
else {
new_session =
std::make_shared<session>(session_id, session_timeout_, true);
map_.insert({session_id, new_session});
}
return new_session;
}
void remove_expire_session() {
std::unique_lock<std::mutex> lock(mtx_);
auto now = std::time(nullptr);
for (auto it = map_.begin(); it != map_.end();) {
if (it->second->get_time_stamp() <= now)
it = map_.erase(it);
else
++it;
}
}
bool check_session_existence(const std::string &session_id) {
std::unique_lock<std::mutex> lock(mtx_);
return map_.find(session_id) != map_.end();
}
void start_check_session_timer() {
std::lock_guard lock(timer_mtx_);
std::weak_ptr<asio::steady_timer> timer = check_session_timer_;
check_session_timer_->expires_after(check_session_duration_);
check_session_timer_->async_wait([this, timer](auto ec) {
auto ptr = timer.lock();
if (ptr == nullptr) {
return;
}
if (ec || stop_timer_) {
return;
}
remove_expire_session();
start_check_session_timer();
});
}
void set_check_session_duration(auto duration) {
check_session_duration_ = duration;
{
std::lock_guard lock(timer_mtx_);
std::error_code ec;
check_session_timer_->cancel(ec);
}
start_check_session_timer();
}
void stop_timer() { stop_timer_ = true; }
private:
session_manager()
: check_session_timer_(std::make_shared<asio::steady_timer>(
coro_io::get_global_executor()->get_asio_executor())) {
start_check_session_timer();
};
session_manager(const session_manager &) = delete;
session_manager(session_manager &&) = delete;
std::atomic_int64_t id_ = 0;
std::unordered_map<std::string, std::shared_ptr<session>> map_;
std::mutex mtx_;
// session_timeout_ should be no less than 0
std::size_t session_timeout_ = 86400;
std::atomic<bool> stop_timer_ = false;
std::mutex timer_mtx_;
std::shared_ptr<asio::steady_timer> check_session_timer_;
std::atomic<std::chrono::steady_clock::duration> check_session_duration_ = {
std::chrono::seconds(15)};
};
} // namespace cinatra