This commit is contained in:
Timur A. Fatkhullin
2024-10-21 01:21:53 +03:00
parent 117d8c4a3d
commit b8fdae9d16
4 changed files with 411 additions and 41 deletions

View File

@@ -97,6 +97,39 @@ public:
virtual ~AdcNetSessionManager() = default;
protected:
AdcNetSessionManager() = default;
AdcNetSessionManager(const AdcNetSessionManager&) = delete;
AdcNetSessionManager(AdcNetSessionManager&& other)
{
if (this == &other) {
return;
}
for (auto& func : _moveCtorFunc) {
func(this);
}
_stopSessionFunc = std::move(other._stopSessionFunc);
_moveCtorFunc = std::move(other._moveCtorFunc);
}
AdcNetSessionManager& operator=(const AdcNetSessionManager&) = delete;
AdcNetSessionManager& operator=(AdcNetSessionManager&& other)
{
if (this != &other) {
for (auto& func : _moveCtorFunc) {
func(this);
}
_stopSessionFunc = std::move(other._stopSessionFunc);
_moveCtorFunc = std::move(other._moveCtorFunc);
}
return *this;
};
template <interfaces::adc_netsession_c SessionT>
constexpr static bool anySessionPredicate(const typename SessionT::netsession_ident_t&)
{
@@ -107,6 +140,7 @@ protected:
template <interfaces::adc_netsession_c SessionT>
static std::unordered_map<const AdcNetSessionManager*, std::set<std::weak_ptr<SessionT>>> _serverSessions;
std::vector<std::function<bool()>> _stopSessionFunc;
std::vector<std::function<void(const AdcNetSessionManager*)>> _moveCtorFunc;
template <interfaces::adc_netsession_c SessionT>
void startSession(std::shared_ptr<SessionT>& sess_ptr)
@@ -115,16 +149,24 @@ protected:
if (res.second) {
sess_ptr.start();
_stopSessionFunc.emplace_back([res]() {
_stopSessionFunc.emplace_back([res, this]() {
if (!res.first.expired()) { // session is still existing
auto sess = res.first.lock();
sess->stop();
_serverSessions<SessionT>[this].erase(res.first);
return true;
} else {
return false;
}
});
}
// define move-function only once per SessionT!
if (_serverSessions<SessionT>[this].size() == 1) {
_moveCtorFunc.emplace_back([this](const AdcNetSessionManager* new_instance) {
_serverSessions<SessionT>[new_instance] = std::move(_serverSessions<SessionT>[this]);
});
}
}
@@ -134,20 +176,31 @@ protected:
{
size_t N = 0;
std::set<std::weak_ptr<SessionT>> remove_wptr;
for (auto& wptr : _serverSessions<SessionT>[this]) {
if (std::shared_ptr<SessionT> sptr = wptr.lock()) {
if constexpr (std::same_as<PredT, decltype(anySessionPredicate<SessionT>)>) {
sptr->stop();
remove_wptr.emplace(wptr);
++N;
} else {
if (std::forward<PredT>(comp_func)(sptr->ident())) {
sptr->stop();
remove_wptr.emplace(wptr);
++N;
}
}
} else { // remove already stopped sessions?!!
remove_wptr.emplace(wptr);
}
}
for (auto& wptr : remove_wptr) {
_serverSessions<SessionT>[this].erase(wptr);
}
return N;
}
@@ -161,6 +214,7 @@ protected:
}
_stopSessionFunc.clear();
_moveCtorFunc.clear(); // there are nothing to move after stopping of all sessions
return N;
}
@@ -172,7 +226,6 @@ protected:
class AdcGenericNetServer : public AdcPosixGenericDaemon, public AdcNetSessionManager
{
protected:
public:
typedef std::string server_ident_t;
@@ -186,8 +239,46 @@ public:
}
}
AdcGenericNetServer(const AdcGenericNetServer&) = delete;
AdcGenericNetServer(AdcGenericNetServer&& other)
: AdcPosixGenericDaemon(std::move(other)), AdcNetSessionManager(std::move(other))
{
if (this == &other) {
return;
}
_serverIdent = std::move(other._serverIdent);
_stopListenFunc = std::move(other._stopListenFunc);
for (auto& func : other._moveCtorFunc) {
func(this);
}
_moveCtorFunc = std::move(other._moveCtorFunc);
}
virtual ~AdcGenericNetServer() = default;
AdcGenericNetServer& operator=(const AdcGenericNetServer&) = delete;
AdcGenericNetServer& operator=(AdcGenericNetServer&& other)
{
if (this != &other) {
AdcPosixGenericDaemon::operator=(std::move(other));
AdcNetSessionManager::operator=(std::move(other));
_serverIdent = std::move(other._serverIdent);
_stopListenFunc = std::move(other._stopListenFunc);
for (auto& func : other._moveCtorFunc) {
func(this);
}
_moveCtorFunc = std::move(other._moveCtorFunc);
}
return *this;
}
virtual server_ident_t ident() const
{
@@ -214,6 +305,13 @@ public:
doAccept<SessionT>(acceptor, id, sess_ctx);
}
// only once per SessionT
if (_isListening<SessionT>[this].size() == 1) {
_moveCtorFunc = [this](const AdcGenericNetServer* new_instance) {
_isListening<SessionT>[new_instance] = std::move(_isListening<SessionT>[this]);
};
}
};
@@ -247,6 +345,7 @@ protected:
_isListening{};
std::vector<std::function<void()>> _stopListenFunc;
std::vector<std::function<void(const AdcGenericNetServer*)>> _moveCtorFunc;
server_ident_t _serverIdent;