rcpp_framework/libs/brynet/net/detail/ConnectorDetail.hpp

148 lines
3.6 KiB
C++
Raw Normal View History

2020-11-24 15:41:18 +01:00
#pragma once
#include <brynet/base/CPP_VERSION.hpp>
2021-04-30 16:10:14 +02:00
#include <brynet/base/NonCopyable.hpp>
2020-11-24 15:41:18 +01:00
#include <brynet/net/EventLoop.hpp>
2021-04-30 16:10:14 +02:00
#include <brynet/net/Exception.hpp>
2020-11-24 15:41:18 +01:00
#include <brynet/net/detail/ConnectorWorkInfo.hpp>
2021-04-30 16:10:14 +02:00
#include <functional>
#include <memory>
#include <thread>
2020-11-24 15:41:18 +01:00
#ifdef BRYNET_HAVE_LANG_CXX17
#include <shared_mutex>
#else
#include <mutex>
#endif
namespace brynet { namespace net { namespace detail {
2021-04-30 16:10:14 +02:00
class AsyncConnectorDetail : public brynet::base::NonCopyable
{
protected:
void startWorkerThread()
2020-11-24 15:41:18 +01:00
{
#ifdef BRYNET_HAVE_LANG_CXX17
2021-04-30 16:10:14 +02:00
std::lock_guard<std::shared_mutex> lck(mThreadGuard);
2020-11-24 15:41:18 +01:00
#else
2021-04-30 16:10:14 +02:00
std::lock_guard<std::mutex> lck(mThreadGuard);
2020-11-24 15:41:18 +01:00
#endif
2021-04-30 16:10:14 +02:00
if (mThread != nullptr)
{
return;
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
mIsRun = std::make_shared<bool>(true);
mWorkInfo = std::make_shared<detail::ConnectorWorkInfo>();
mEventLoop = std::make_shared<EventLoop>();
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
auto eventLoop = mEventLoop;
auto workerInfo = mWorkInfo;
auto isRun = mIsRun;
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
mThread = std::make_shared<std::thread>([eventLoop, workerInfo, isRun]() {
while (*isRun)
{
detail::RunOnceCheckConnect(eventLoop, workerInfo);
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
workerInfo->causeAllFailed();
});
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
void stopWorkerThread()
{
2020-11-24 15:41:18 +01:00
#ifdef BRYNET_HAVE_LANG_CXX17
2021-04-30 16:10:14 +02:00
std::lock_guard<std::shared_mutex> lck(mThreadGuard);
2020-11-24 15:41:18 +01:00
#else
2021-04-30 16:10:14 +02:00
std::lock_guard<std::mutex> lck(mThreadGuard);
2020-11-24 15:41:18 +01:00
#endif
2021-04-30 16:10:14 +02:00
if (mThread == nullptr)
{
return;
}
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
mEventLoop->runAsyncFunctor([this]() {
*mIsRun = false;
});
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
try
{
if (mThread->joinable())
2020-11-24 15:41:18 +01:00
{
2021-04-30 16:10:14 +02:00
mThread->join();
2020-11-24 15:41:18 +01:00
}
}
2021-04-30 16:10:14 +02:00
catch (std::system_error& e)
2020-11-24 15:41:18 +01:00
{
2021-04-30 16:10:14 +02:00
(void) e;
}
mEventLoop = nullptr;
mWorkInfo = nullptr;
mIsRun = nullptr;
mThread = nullptr;
}
void asyncConnect(detail::ConnectOption option)
{
2020-11-24 15:41:18 +01:00
#ifdef BRYNET_HAVE_LANG_CXX17
2021-04-30 16:10:14 +02:00
std::shared_lock<std::shared_mutex> lck(mThreadGuard);
2020-11-24 15:41:18 +01:00
#else
2021-04-30 16:10:14 +02:00
std::lock_guard<std::mutex> lck(mThreadGuard);
2020-11-24 15:41:18 +01:00
#endif
2021-04-30 16:10:14 +02:00
if (option.completedCallback == nullptr && option.failedCallback == nullptr)
{
throw ConnectException("all callback is nullptr");
2020-11-24 15:41:18 +01:00
}
2021-04-30 16:10:14 +02:00
if (option.ip.empty())
2020-11-24 15:41:18 +01:00
{
2021-04-30 16:10:14 +02:00
throw ConnectException("addr is empty");
2020-11-24 15:41:18 +01:00
}
2021-04-30 16:10:14 +02:00
if (!(*mIsRun))
2020-11-24 15:41:18 +01:00
{
2021-04-30 16:10:14 +02:00
throw ConnectException("work thread already stop");
2020-11-24 15:41:18 +01:00
}
2021-04-30 16:10:14 +02:00
auto workInfo = mWorkInfo;
auto address = detail::AsyncConnectAddr(std::move(option.ip),
option.port,
option.timeout,
std::move(option.completedCallback),
std::move(option.failedCallback),
std::move(option.processCallbacks));
mEventLoop->runAsyncFunctor([workInfo, address]() {
workInfo->processConnect(address);
});
}
protected:
AsyncConnectorDetail()
{
mIsRun = std::make_shared<bool>(false);
}
virtual ~AsyncConnectorDetail()
{
stopWorkerThread();
}
private:
std::shared_ptr<EventLoop> mEventLoop;
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
std::shared_ptr<detail::ConnectorWorkInfo> mWorkInfo;
std::shared_ptr<std::thread> mThread;
2020-11-24 15:41:18 +01:00
#ifdef BRYNET_HAVE_LANG_CXX17
2021-04-30 16:10:14 +02:00
std::shared_mutex mThreadGuard;
2020-11-24 15:41:18 +01:00
#else
2021-04-30 16:10:14 +02:00
std::mutex mThreadGuard;
2020-11-24 15:41:18 +01:00
#endif
2021-04-30 16:10:14 +02:00
std::shared_ptr<bool> mIsRun;
};
2020-11-24 15:41:18 +01:00
2021-04-30 16:10:14 +02:00
}}}// namespace brynet::net::detail