From b6e503cfffe83c6ffa89803fa9678a9a9bb2dae9 Mon Sep 17 00:00:00 2001 From: likepeng Date: Thu, 15 Jun 2023 15:44:48 +0800 Subject: [PATCH 01/17] use shared_mutex, thread use member function --- myframe/actor_context_manager.cpp | 16 +++------- myframe/actor_context_manager.h | 4 +-- myframe/mod_lib.cpp | 28 +++++------------ myframe/mod_lib.h | 5 ++- myframe/mod_manager.cpp | 20 +++--------- myframe/mod_manager.h | 5 +-- myframe/worker_context.cpp | 19 +++++------- myframe/worker_context.h | 2 +- myframe/worker_context_manager.cpp | 50 +++++++++--------------------- myframe/worker_context_manager.h | 5 ++- 10 files changed, 47 insertions(+), 107 deletions(-) diff --git a/myframe/actor_context_manager.cpp b/myframe/actor_context_manager.cpp index ac710cf..dc8fcf4 100644 --- a/myframe/actor_context_manager.cpp +++ b/myframe/actor_context_manager.cpp @@ -22,12 +22,10 @@ namespace myframe { ActorContextManager::ActorContextManager() : ctx_count_(0) { LOG(INFO) << "ActorContextManager create"; - pthread_rwlock_init(&rw_, NULL); } ActorContextManager::~ActorContextManager() { LOG(INFO) << "ActorContextManager deconstruct"; - pthread_rwlock_destroy(&rw_); } void ActorContextManager::DispatchMsg(std::shared_ptr msg) { @@ -42,47 +40,41 @@ void ActorContextManager::DispatchMsg(std::shared_ptr msg) { } bool ActorContextManager::RegContext(std::shared_ptr ctx) { - pthread_rwlock_wrlock(&rw_); + std::unique_lock lk(rw_); if (ctxs_.find(ctx->GetActor()->GetActorName()) != ctxs_.end()) { LOG(WARNING) << "reg the same actor name: " << ctx->GetActor()->GetActorName(); - pthread_rwlock_unlock(&rw_); return false; } LOG(INFO) << "reg actor " << ctx->GetActor()->GetActorName(); ctxs_[ctx->GetActor()->GetActorName()] = ctx; - pthread_rwlock_unlock(&rw_); return true; } std::shared_ptr ActorContextManager::GetContext( const std::string& actor_name) { - pthread_rwlock_rdlock(&rw_); + std::shared_lock lk(rw_); if (ctxs_.find(actor_name) == ctxs_.end()) { LOG(WARNING) << "not found " << actor_name; - pthread_rwlock_unlock(&rw_); return nullptr; } auto ctx = ctxs_[actor_name]; - pthread_rwlock_unlock(&rw_); return ctx; } std::vector ActorContextManager::GetAllActorAddr() { std::vector res; - pthread_rwlock_rdlock(&rw_); + std::shared_lock lk(rw_); for (auto ctx : ctxs_) { res.push_back(ctx.first); } - pthread_rwlock_unlock(&rw_); return res; } bool ActorContextManager::HasActor(const std::string& name) { bool res = false; - pthread_rwlock_rdlock(&rw_); + std::shared_lock lk(rw_); res = (ctxs_.find(name) != ctxs_.end()); - pthread_rwlock_unlock(&rw_); return res; } diff --git a/myframe/actor_context_manager.h b/myframe/actor_context_manager.h index 264a83c..8e53e90 100644 --- a/myframe/actor_context_manager.h +++ b/myframe/actor_context_manager.h @@ -6,9 +6,9 @@ Author: likepeng ****************************************************************************/ #pragma once -#include #include +#include #include #include #include @@ -48,7 +48,7 @@ class ActorContextManager final { /// 待处理actor链表 std::list> wait_queue_; /// 读写锁 - pthread_rwlock_t rw_; + std::shared_mutex rw_; /// key: context name, value: context std::unordered_map> ctxs_; diff --git a/myframe/mod_lib.cpp b/myframe/mod_lib.cpp index c721a92..18b3a48 100644 --- a/myframe/mod_lib.cpp +++ b/myframe/mod_lib.cpp @@ -16,16 +16,14 @@ Author: likepeng namespace myframe { -ModLib::ModLib() { pthread_rwlock_init(&rw_, NULL); } +ModLib::ModLib() {} ModLib::~ModLib() { - pthread_rwlock_wrlock(&rw_); + std::unique_lock lk(rw_); for (const auto& p : mods_) { dlclose(p.second); } mods_.clear(); - pthread_rwlock_unlock(&rw_); - pthread_rwlock_destroy(&rw_); } std::string ModLib::GetModName(const std::string& full_path) { @@ -36,36 +34,31 @@ std::string ModLib::GetModName(const std::string& full_path) { bool ModLib::LoadMod(const std::string& dlpath) { auto dlname = GetModName(dlpath); - pthread_rwlock_wrlock(&rw_); + std::unique_lock lk(rw_); if (mods_.find(dlname) != mods_.end()) { - pthread_rwlock_unlock(&rw_); DLOG(INFO) << dlname << " has loaded"; return true; } void* dll_handle = dlopen(dlpath.c_str(), RTLD_NOW | RTLD_LOCAL); if (dll_handle == nullptr) { - pthread_rwlock_unlock(&rw_); LOG(ERROR) << "Open dll " << dlpath << " failed, " << dlerror(); return false; } mods_[dlname] = dll_handle; - pthread_rwlock_unlock(&rw_); LOG(INFO) << "Load lib " << dlpath; return true; } bool ModLib::IsLoad(const std::string& dlname) { - pthread_rwlock_rdlock(&rw_); + std::shared_lock lk(rw_); auto res = mods_.find(dlname) != mods_.end(); - pthread_rwlock_unlock(&rw_); return res; } bool ModLib::UnloadMod(const std::string& dlname) { - pthread_rwlock_wrlock(&rw_); + std::unique_lock lk(rw_); if (mods_.find(dlname) == mods_.end()) { - pthread_rwlock_unlock(&rw_); return true; } @@ -73,13 +66,12 @@ bool ModLib::UnloadMod(const std::string& dlname) { LOG(ERROR) << "lib close failed, " << dlerror(); } mods_.erase(dlname); - pthread_rwlock_unlock(&rw_); return true; } std::shared_ptr ModLib::CreateWorkerInst( const std::string& mod_name, const std::string& worker_name) { - pthread_rwlock_rdlock(&rw_); + std::shared_lock lk(rw_); if (mods_.find(mod_name) == mods_.end()) { LOG(ERROR) << "Find " << mod_name << "." << worker_name << " failed"; return nullptr; @@ -88,7 +80,6 @@ std::shared_ptr ModLib::CreateWorkerInst( auto void_func = dlsym(handle, "worker_create"); auto create = reinterpret_cast(void_func); if (nullptr == create) { - pthread_rwlock_unlock(&rw_); LOG(ERROR) << "Load " << mod_name << "." << worker_name << " module worker_create function failed"; @@ -96,7 +87,6 @@ std::shared_ptr ModLib::CreateWorkerInst( } auto worker = create(worker_name); if (nullptr == worker) { - pthread_rwlock_unlock(&rw_); LOG(ERROR) << "Create " << mod_name << "." << worker_name << " failed"; @@ -104,13 +94,12 @@ std::shared_ptr ModLib::CreateWorkerInst( } worker->SetModName(mod_name); worker->SetTypeName(worker_name); - pthread_rwlock_unlock(&rw_); return worker; } std::shared_ptr ModLib::CreateActorInst( const std::string& mod_name, const std::string& actor_name) { - pthread_rwlock_rdlock(&rw_); + std::shared_lock lk(rw_); if (mods_.find(mod_name) == mods_.end()) { LOG(ERROR) << "Find " << mod_name << "." << actor_name << " failed"; return nullptr; @@ -119,7 +108,6 @@ std::shared_ptr ModLib::CreateActorInst( auto void_func = dlsym(handle, "actor_create"); auto create = reinterpret_cast(void_func); if (nullptr == create) { - pthread_rwlock_unlock(&rw_); LOG(ERROR) << "Load " << mod_name << "." << actor_name << " module actor_create function failed"; @@ -127,7 +115,6 @@ std::shared_ptr ModLib::CreateActorInst( } auto actor = create(actor_name); if (nullptr == actor) { - pthread_rwlock_unlock(&rw_); LOG(ERROR) << "Create " << mod_name << "." << actor_name << " failed"; @@ -135,7 +122,6 @@ std::shared_ptr ModLib::CreateActorInst( } actor->SetModName(mod_name); actor->SetTypeName(actor_name); - pthread_rwlock_unlock(&rw_); return actor; } diff --git a/myframe/mod_lib.h b/myframe/mod_lib.h index cbdeb6e..ff6c78e 100644 --- a/myframe/mod_lib.h +++ b/myframe/mod_lib.h @@ -6,8 +6,7 @@ Author: likepeng ****************************************************************************/ #pragma once -#include - +#include #include #include #include @@ -69,7 +68,7 @@ class ModLib final { std::string GetModName(const std::string& full_path); std::unordered_map mods_; - pthread_rwlock_t rw_; + std::shared_mutex rw_; DISALLOW_COPY_AND_ASSIGN(ModLib) }; diff --git a/myframe/mod_manager.cpp b/myframe/mod_manager.cpp index 83034f1..33e5354 100644 --- a/myframe/mod_manager.cpp +++ b/myframe/mod_manager.cpp @@ -17,14 +17,10 @@ namespace myframe { ModManager::ModManager() { LOG(INFO) << "ModManager create"; - pthread_rwlock_init(&class_actor_rw_, NULL); - pthread_rwlock_init(&class_worker_rw_, NULL); } ModManager::~ModManager() { LOG(INFO) << "ModManager deconstruct"; - pthread_rwlock_destroy(&class_actor_rw_); - pthread_rwlock_destroy(&class_worker_rw_); } bool ModManager::LoadMod(const std::string& dl_path) { @@ -34,32 +30,28 @@ bool ModManager::LoadMod(const std::string& dl_path) { bool ModManager::RegActor( const std::string& class_name, std::function(const std::string&)> func) { - pthread_rwlock_wrlock(&class_actor_rw_); + std::unique_lock lk(class_actor_rw_); if (class_actors_.find(class_name) != class_actors_.end()) { - pthread_rwlock_unlock(&class_actor_rw_); LOG(WARNING) << "reg " << class_name << " failed, " << " has exist"; return false; } class_actors_[class_name] = func; - pthread_rwlock_unlock(&class_actor_rw_); return true; } bool ModManager::RegWorker( const std::string& class_name, std::function(const std::string&)> func) { - pthread_rwlock_wrlock(&class_worker_rw_); + std::unique_lock lk(class_worker_rw_); if (class_workers_.find(class_name) != class_workers_.end()) { - pthread_rwlock_unlock(&class_worker_rw_); LOG(WARNING) << "reg " << class_name << " failed, " << " has exist"; return false; } class_workers_[class_name] = func; - pthread_rwlock_unlock(&class_worker_rw_); return true; } @@ -69,17 +61,15 @@ std::shared_ptr ModManager::CreateActorInst( DLOG(INFO) << actor_name << " actor from lib"; return lib_mods_.CreateActorInst(mod_or_class_name, actor_name); } - pthread_rwlock_rdlock(&class_actor_rw_); + std::shared_lock lk(class_actor_rw_); if (mod_or_class_name == "class" && class_actors_.find(actor_name) != class_actors_.end()) { DLOG(INFO) << actor_name << " actor from reg class"; auto actor = class_actors_[actor_name](actor_name); actor->SetModName(mod_or_class_name); actor->SetTypeName(actor_name); - pthread_rwlock_unlock(&class_actor_rw_); return actor; } - pthread_rwlock_unlock(&class_actor_rw_); return nullptr; } @@ -89,17 +79,15 @@ std::shared_ptr ModManager::CreateWorkerInst( LOG(INFO) << "instance worker from lib"; return lib_mods_.CreateWorkerInst(mod_or_class_name, worker_name); } - pthread_rwlock_rdlock(&class_worker_rw_); + std::shared_lock lk(class_worker_rw_); if (mod_or_class_name == "class" && class_workers_.find(worker_name) != class_workers_.end()) { LOG(INFO) << "instance worker from reg class"; auto worker = class_workers_[worker_name](worker_name); worker->SetModName(mod_or_class_name); worker->SetTypeName(worker_name); - pthread_rwlock_unlock(&class_worker_rw_); return worker; } - pthread_rwlock_unlock(&class_worker_rw_); return nullptr; } diff --git a/myframe/mod_manager.h b/myframe/mod_manager.h index 5481c92..68fdd47 100644 --- a/myframe/mod_manager.h +++ b/myframe/mod_manager.h @@ -6,6 +6,7 @@ Author: likepeng ****************************************************************************/ #pragma once +#include #include #include #include @@ -46,8 +47,8 @@ class ModManager final { std::unordered_map< std::string, std::function(const std::string&)>> class_workers_; - pthread_rwlock_t class_actor_rw_; - pthread_rwlock_t class_worker_rw_; + std::shared_mutex class_actor_rw_; + std::shared_mutex class_worker_rw_; ModLib lib_mods_; DISALLOW_COPY_AND_ASSIGN(ModManager) diff --git a/myframe/worker_context.cpp b/myframe/worker_context.cpp index 8a8299f..f4ce6fe 100644 --- a/myframe/worker_context.cpp +++ b/myframe/worker_context.cpp @@ -40,10 +40,7 @@ EventType WorkerContext::GetType() { void WorkerContext::Start() { if (runing_.load() == false) { runing_.store(true); - th_ = std::thread( - std::bind( - &WorkerContext::ListenThread, - std::dynamic_pointer_cast(shared_from_this()))); + th_ = std::thread(std::bind(&WorkerContext::ListenThread, this)); } } @@ -62,16 +59,16 @@ void WorkerContext::Initialize() { worker_->Init(); } -void WorkerContext::ListenThread(std::shared_ptr w) { - if (w->worker_ == nullptr) { +void WorkerContext::ListenThread() { + if (worker_ == nullptr) { return; } - w->Initialize(); - while (w->runing_.load()) { - w->worker_->Run(); + Initialize(); + while (runing_.load()) { + worker_->Run(); } - w->worker_->Exit(); - w->cmd_channel_.SendToMain(Cmd::kQuit); + worker_->Exit(); + cmd_channel_.SendToMain(Cmd::kQuit); } std::size_t WorkerContext::CacheSize() const { diff --git a/myframe/worker_context.h b/myframe/worker_context.h index 587d916..8790abd 100644 --- a/myframe/worker_context.h +++ b/myframe/worker_context.h @@ -76,7 +76,7 @@ class WorkerContext final : public Event { std::shared_ptr GetApp(); private: - static void ListenThread(std::shared_ptr w); + void ListenThread(); void Initialize(); /// state flag diff --git a/myframe/worker_context_manager.cpp b/myframe/worker_context_manager.cpp index 36c3a01..57fb70d 100644 --- a/myframe/worker_context_manager.cpp +++ b/myframe/worker_context_manager.cpp @@ -18,12 +18,10 @@ namespace myframe { WorkerContextManager::WorkerContextManager() { LOG(INFO) << "WorkerContextManager create"; - pthread_rwlock_init(&rw_, NULL); } WorkerContextManager::~WorkerContextManager() { LOG(INFO) << "WorkerContextManager deconstruct"; - pthread_rwlock_destroy(&rw_); } bool WorkerContextManager::Init(int warning_msg_size) { @@ -34,140 +32,122 @@ bool WorkerContextManager::Init(int warning_msg_size) { int WorkerContextManager::WorkerSize() { return cur_worker_count_; } std::shared_ptr WorkerContextManager::Get(int handle) { - pthread_rwlock_rdlock(&rw_); + std::shared_lock lk(rw_); if (worker_ctxs_.find(handle) == worker_ctxs_.end()) { DLOG(WARNING) << "can't find worker, handle " << handle; - pthread_rwlock_unlock(&rw_); return nullptr; } auto ret = worker_ctxs_[handle]; - pthread_rwlock_unlock(&rw_); return ret; } std::shared_ptr WorkerContextManager::Get( const std::string& name) { - pthread_rwlock_rdlock(&rw_); + std::shared_lock lk(rw_); if (name_handle_map_.find(name) == name_handle_map_.end()) { LOG(ERROR) << "can't find worker, name " << name; - pthread_rwlock_unlock(&rw_); return nullptr; } auto handle = name_handle_map_[name]; auto ret = worker_ctxs_[handle]; - pthread_rwlock_unlock(&rw_); return ret; } bool WorkerContextManager::Add(std::shared_ptr worker_ctx) { auto worker = worker_ctx->GetWorker(); int handle = worker_ctx->GetFd(); - pthread_rwlock_wrlock(&rw_); + std::unique_lock lk(rw_); if (worker_ctxs_.find(handle) != worker_ctxs_.end()) { LOG(ERROR) << *worker_ctx << " reg handle " << handle << " has exist"; - pthread_rwlock_unlock(&rw_); return false; } worker_ctxs_[handle] = worker_ctx; name_handle_map_[worker->GetWorkerName()] = handle; ++cur_worker_count_; - pthread_rwlock_unlock(&rw_); return true; } void WorkerContextManager::Del(std::shared_ptr worker_ctx) { auto worker = worker_ctx->GetWorker(); int handle = worker_ctx->GetFd(); - pthread_rwlock_wrlock(&rw_); + std::unique_lock lk(rw_); if (worker_ctxs_.find(handle) == worker_ctxs_.end()) { - pthread_rwlock_unlock(&rw_); return; } stoped_workers_ctx_.push_back(worker_ctx); worker_ctxs_.erase(worker_ctxs_.find(handle)); name_handle_map_.erase(worker->GetWorkerName()); --cur_worker_count_; - pthread_rwlock_unlock(&rw_); } int WorkerContextManager::IdleWorkerSize() { int sz = 0; - pthread_rwlock_rdlock(&rw_); + std::shared_lock lk(rw_); sz = idle_workers_ctx_.size(); - pthread_rwlock_unlock(&rw_); return sz; } std::shared_ptr WorkerContextManager::FrontIdleWorker() { std::shared_ptr w = nullptr; - pthread_rwlock_rdlock(&rw_); + std::shared_lock lk(rw_); if (idle_workers_ctx_.empty()) { - pthread_rwlock_unlock(&rw_); return nullptr; } w = idle_workers_ctx_.front().lock(); - pthread_rwlock_unlock(&rw_); return w; } void WorkerContextManager::PopFrontIdleWorker() { - pthread_rwlock_wrlock(&rw_); + std::unique_lock lk(rw_); if (idle_workers_ctx_.empty()) { - pthread_rwlock_unlock(&rw_); return; } idle_workers_ctx_.pop_front(); - pthread_rwlock_unlock(&rw_); } void WorkerContextManager::PushBackIdleWorker( std::shared_ptr worker) { - pthread_rwlock_wrlock(&rw_); + std::unique_lock lk(rw_); idle_workers_ctx_.emplace_back(worker); - pthread_rwlock_unlock(&rw_); } bool WorkerContextManager::HasWorker(const std::string& name) { bool res = false; - pthread_rwlock_rdlock(&rw_); + std::shared_lock lk(rw_); res = (name_handle_map_.find(name) != name_handle_map_.end()); - pthread_rwlock_unlock(&rw_); return res; } std::vector WorkerContextManager::GetAllUserWorkerAddr() { std::vector res; - pthread_rwlock_rdlock(&rw_); + std::shared_lock lk(rw_); for (auto p : worker_ctxs_) { if (p.second->GetType() == EventType::kWorkerUser && p.second->GetWorker()->GetTypeName() != "node") { res.push_back(p.second->GetWorker()->GetWorkerName()); } } - pthread_rwlock_unlock(&rw_); return res; } void WorkerContextManager::StopAllWorker() { - pthread_rwlock_rdlock(&rw_); + std::shared_lock lk(rw_); for (auto p : worker_ctxs_) { // 目前仅支持使用channel通信的worker停止退出 // 不使用的可以调用Stop函数退出(目前暂无需求) // p.second->Stop(); p.second->GetCmdChannel()->SendToOwner(Cmd::kQuit); } - pthread_rwlock_unlock(&rw_); } void WorkerContextManager::WaitAllWorkerQuit() { // FIXME(likepeng): 只支持退出时释放worker资源 // 运行时释放worker资源有可能导致主线程阻塞,影响其它组件调度 - pthread_rwlock_rdlock(&rw_); + std::shared_lock lk(rw_); for (auto p : stoped_workers_ctx_) { p->Join(); } - pthread_rwlock_unlock(&rw_); } void WorkerContextManager::PushWaitWorker( @@ -176,7 +156,7 @@ void WorkerContextManager::PushWaitWorker( } void WorkerContextManager::WeakupWorker() { - pthread_rwlock_wrlock(&rw_); + std::unique_lock lk(rw_); for (auto it = weakup_workers_ctx_.begin(); it != weakup_workers_ctx_.end();) { auto worker_ctx = it->lock(); @@ -195,7 +175,6 @@ void WorkerContextManager::WeakupWorker() { DLOG(INFO) << "notify " << *worker_ctx << " process msg"; worker_ctx->GetCmdChannel()->SendToOwner(Cmd::kRunWithMsg); } - pthread_rwlock_unlock(&rw_); } void WorkerContextManager::DispatchWorkerMsg(std::shared_ptr msg) { @@ -223,9 +202,8 @@ void WorkerContextManager::DispatchWorkerMsg(std::shared_ptr msg) { return; } worker_ctx->SetWaitMsgQueueFlag(true); - pthread_rwlock_wrlock(&rw_); + std::unique_lock lk(rw_); weakup_workers_ctx_.emplace_back(worker_ctx); - pthread_rwlock_unlock(&rw_); } } // namespace myframe diff --git a/myframe/worker_context_manager.h b/myframe/worker_context_manager.h index 98516bd..6bb1e0f 100644 --- a/myframe/worker_context_manager.h +++ b/myframe/worker_context_manager.h @@ -6,8 +6,7 @@ Author: likepeng ****************************************************************************/ #pragma once -#include - +#include #include #include #include @@ -58,7 +57,7 @@ class WorkerContextManager final { /// 工作线程数(包含用户线程) std::atomic_int cur_worker_count_{0}; /// 读写锁 - pthread_rwlock_t rw_; + std::shared_mutex rw_; /// 空闲线程链表 std::list> idle_workers_ctx_; /// 有消息user线程 From 065a17180e0f9e82b017f6f5d9846083b99f3dac Mon Sep 17 00:00:00 2001 From: likepeng Date: Thu, 15 Jun 2023 17:35:27 +0800 Subject: [PATCH 02/17] fix poll example --- ...mple_worker_interactive_with_3rd_frame.cpp | 63 ++++++++++--------- 1 file changed, 32 insertions(+), 31 deletions(-) diff --git a/examples/example_worker_interactive_with_3rd_frame.cpp b/examples/example_worker_interactive_with_3rd_frame.cpp index 87925b3..6b66cf4 100644 --- a/examples/example_worker_interactive_with_3rd_frame.cpp +++ b/examples/example_worker_interactive_with_3rd_frame.cpp @@ -89,15 +89,40 @@ class ExampleWorkerInteractiveWith3rdFrame : public myframe::Worker { continue; } if (i == 0) { - OnMainMsg(); + myframe::Cmd cmd; + cmd_channel->RecvFromMain(&cmd); + if (cmd == myframe::Cmd::kRun) { + recv_run_flag_ = true; + } else if (cmd == myframe::Cmd::kRunWithMsg) { + auto mailbox = GetMailbox(); + while (!mailbox->RecvEmpty()) { + const auto& msg = mailbox->PopRecv(); + // 接收到其它组件消息 + LOG(INFO) << "get main " << msg->GetData(); + } + cmd_channel->SendToMain(myframe::Cmd::kWaitForMsg); + } else if (cmd == myframe::Cmd::kQuit) { + quit_.store(true); + Stop(); + } } else if (i == 1) { auto data = queue_.Pop(); - // 可以将queue里的消息发给myfrmae的worker或actor - // eg: Send("actor.xx.xx", std::make_shared(data->c_str())); - LOG(INFO) << "get 3rd frame: " << data->c_str(); - cmd_channel->SendToMain(myframe::Cmd::kIdle); + // 接收到来自外部的消息 + LOG(INFO) << "get 3rd frame: " << *data; + send_msgs_.push_back(std::make_shared(data->c_str())); } } + // 分发外部消息给程序的其它组件 + if (recv_run_flag_ && !send_msgs_.empty()) { + recv_run_flag_ = false; + LOG(INFO) << "pub 3rd msg to main " << send_msgs_.size(); + // auto mailbox = GetMailbox(); + for (std::size_t i = 0; i < send_msgs_.size(); ++i) { + // mailbox->Send("actor.xx.xx", send_msgs_[i]); + } + send_msgs_.clear(); + cmd_channel->SendToMain(myframe::Cmd::kIdle); + } } void Exit() override { @@ -106,33 +131,9 @@ class ExampleWorkerInteractiveWith3rdFrame : public myframe::Worker { } } - // 分发消息、处理来自myframe的消息 - void OnMainMsg() { - auto cmd_channel = GetCmdChannel(); - myframe::Cmd cmd; - cmd_channel->RecvFromMain(&cmd); - if (cmd == myframe::Cmd::kRun) { - // do nothing - return; - } else if (cmd == myframe::Cmd::kRunWithMsg) { - ProcessMainMsg(); - cmd_channel->SendToMain(myframe::Cmd::kWaitForMsg); - } else if (cmd == myframe::Cmd::kQuit) { - quit_.store(true); - Stop(); - } - } - - void ProcessMainMsg() { - auto mailbox = GetMailbox(); - while (!mailbox->RecvEmpty()) { - const auto& msg = mailbox->PopRecv(); - // ... - LOG(INFO) << "get main " << msg->GetData(); - } - } - private: + bool recv_run_flag_{true}; + std::vector> send_msgs_; int seq_num_{0}; std::atomic_bool quit_{true}; std::thread th_; From 7284eab37bb83333ccb9ad5f101527961516e46e Mon Sep 17 00:00:00 2001 From: likepeng Date: Thu, 15 Jun 2023 18:02:36 +0800 Subject: [PATCH 03/17] fix compile error --- myframe/actor_context_manager.h | 1 + myframe/mod_lib.h | 1 + myframe/mod_manager.h | 1 + myframe/worker_context_manager.cpp | 6 +++--- myframe/worker_context_manager.h | 1 + 5 files changed, 7 insertions(+), 3 deletions(-) diff --git a/myframe/actor_context_manager.h b/myframe/actor_context_manager.h index 8e53e90..174cfae 100644 --- a/myframe/actor_context_manager.h +++ b/myframe/actor_context_manager.h @@ -8,6 +8,7 @@ Author: likepeng #pragma once #include +#include #include #include #include diff --git a/myframe/mod_lib.h b/myframe/mod_lib.h index ff6c78e..57706c0 100644 --- a/myframe/mod_lib.h +++ b/myframe/mod_lib.h @@ -6,6 +6,7 @@ Author: likepeng ****************************************************************************/ #pragma once +#include #include #include #include diff --git a/myframe/mod_manager.h b/myframe/mod_manager.h index 68fdd47..28f32e5 100644 --- a/myframe/mod_manager.h +++ b/myframe/mod_manager.h @@ -6,6 +6,7 @@ Author: likepeng ****************************************************************************/ #pragma once +#include #include #include #include diff --git a/myframe/worker_context_manager.cpp b/myframe/worker_context_manager.cpp index 57fb70d..c7e6b7d 100644 --- a/myframe/worker_context_manager.cpp +++ b/myframe/worker_context_manager.cpp @@ -29,7 +29,7 @@ bool WorkerContextManager::Init(int warning_msg_size) { return true; } -int WorkerContextManager::WorkerSize() { return cur_worker_count_; } +int WorkerContextManager::WorkerSize() { return cur_worker_count_.load(); } std::shared_ptr WorkerContextManager::Get(int handle) { std::shared_lock lk(rw_); @@ -64,7 +64,7 @@ bool WorkerContextManager::Add(std::shared_ptr worker_ctx) { } worker_ctxs_[handle] = worker_ctx; name_handle_map_[worker->GetWorkerName()] = handle; - ++cur_worker_count_; + cur_worker_count_.fetch_add(1); return true; } @@ -78,7 +78,7 @@ void WorkerContextManager::Del(std::shared_ptr worker_ctx) { stoped_workers_ctx_.push_back(worker_ctx); worker_ctxs_.erase(worker_ctxs_.find(handle)); name_handle_map_.erase(worker->GetWorkerName()); - --cur_worker_count_; + cur_worker_count_.fetch_sub(1); } int WorkerContextManager::IdleWorkerSize() { diff --git a/myframe/worker_context_manager.h b/myframe/worker_context_manager.h index 6bb1e0f..66361b3 100644 --- a/myframe/worker_context_manager.h +++ b/myframe/worker_context_manager.h @@ -6,6 +6,7 @@ Author: likepeng ****************************************************************************/ #pragma once +#include #include #include #include From 1b0c143e352c8d1b6544aa90fa7ddc866b48416b Mon Sep 17 00:00:00 2001 From: likepeng01 Date: Mon, 26 Jun 2023 17:45:44 +0800 Subject: [PATCH 04/17] output version file add commit date --- CMakeLists.txt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index dfb70de..26d09c2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -112,8 +112,14 @@ execute_process( OUTPUT_VARIABLE GIT_COMMIT_ID OUTPUT_STRIP_TRAILING_WHITESPACE ) +execute_process( + COMMAND git show -s --format=%ci HEAD + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + OUTPUT_VARIABLE GIT_COMMIT_DATE + OUTPUT_STRIP_TRAILING_WHITESPACE +) install(CODE " file( WRITE ${CMAKE_INSTALL_PREFIX}/version.txt - \"${GIT_BRANCH}\n${GIT_COMMIT_ID}\n\") + \"${GIT_BRANCH}\n${GIT_COMMIT_ID}\n${GIT_COMMIT_DATE}\n\") ") From c9b8c5e6503e46af60247770902c31f7a063c384 Mon Sep 17 00:00:00 2001 From: likepeng01 Date: Mon, 10 Jul 2023 15:21:32 +0800 Subject: [PATCH 05/17] arrange cmake conf --- .gitattributes | 1 + 3rd/README.md | 1 - CMakeLists.txt | 13 ++----------- cpplint.bash | 4 ++-- examples/CMakeLists.txt | 27 ++++++++++++--------------- launcher/CMakeLists.txt | 9 ++++----- myframe/CMakeLists.txt | 9 ++------- templates/CMakeLists.txt | 9 ++------- 8 files changed, 25 insertions(+), 48 deletions(-) create mode 100644 .gitattributes delete mode 100644 3rd/README.md diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..2f6d494 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.h linguist-language=C++ diff --git a/3rd/README.md b/3rd/README.md deleted file mode 100644 index 3a748ae..0000000 --- a/3rd/README.md +++ /dev/null @@ -1 +0,0 @@ -# 第三方的开源库 diff --git a/CMakeLists.txt b/CMakeLists.txt index 26d09c2..d2b7eb8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,7 +12,6 @@ if (CMAKE_COMPILER_IS_GNUCC) endif () ### cpp option -set(CMAKE_C_STANDARD 11) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED YES) # glog option: @@ -20,11 +19,6 @@ set(CMAKE_CXX_STANDARD_REQUIRED YES) # -DDCHECK_ALWAYS_ON # unit test option: # -fno-omit-frame-pointer -fsanitize=address -fsanitize=undefined -set(CMAKE_C_FLAGS - "-fPIC -Wall -Wextra -Werror -pedantic-errors \ - -Wswitch-default -Wfloat-equal -Wshadow -Wcast-qual \ - -DNDEBUG" -) set(CMAKE_CXX_FLAGS "-fPIC -Wall -Wextra -Werror -pedantic-errors \ -Wswitch-default -Wfloat-equal -Wshadow -Wcast-qual \ @@ -50,7 +44,7 @@ set(CMAKE_INSTALL_PREFIX "$ENV{HOME}/${CMAKE_PROJECT_NAME}") set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") set(MYFRAME_TEST_DIR "test") set(MYFRAME_BIN_DIR "bin") -set(MYFRAME_INC_DIR "inc") +set(MYFRAME_INC_DIR "include") set(MYFRAME_LIB_DIR "lib") set(MYFRAME_LOG_DIR "log") set(MYFRAME_SERVICE_DIR "service") @@ -89,10 +83,7 @@ endif() ### install file/dir install(FILES "LICENSE" - PERMISSIONS - OWNER_READ - GROUP_READ - WORLD_READ + PERMISSIONS OWNER_READ GROUP_READ WORLD_READ DESTINATION . ) install(DIRECTORY templates DESTINATION .) diff --git a/cpplint.bash b/cpplint.bash index 9e393f2..4f3c610 100755 --- a/cpplint.bash +++ b/cpplint.bash @@ -5,7 +5,7 @@ function main() { set -e cd "$PWD0" # shellcheck disable=SC2038 - find '(' \ + find . '(' \ -name "*.c" -or \ -name "*.cc" -or \ -name "*.h" -or \ @@ -18,7 +18,7 @@ function main() { -name "*.hxx" -or \ -name "*.cxx" -or \ -name "*.cuh" \ - ')' | xargs ./cpplint.py + ')' | xargs python3 ./cpplint.py } main "$@" diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 67ac9ee..02af264 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -2,39 +2,36 @@ CMAKE_MINIMUM_REQUIRED(VERSION 3.10) ### actor add_library(example_actor_helloworld SHARED example_actor_helloworld.cpp) -target_link_libraries(example_actor_helloworld myframe) +target_link_libraries(example_actor_helloworld ${PROJECT_NAME}) add_library(example_actor_timer SHARED example_actor_timer.cpp) -target_link_libraries(example_actor_timer myframe) +target_link_libraries(example_actor_timer ${PROJECT_NAME}) add_library(example_actor_serial SHARED example_actor_serial.cpp) -target_link_libraries(example_actor_serial myframe) +target_link_libraries(example_actor_serial ${PROJECT_NAME}) add_library(example_actor_concurrent SHARED example_actor_concurrent.cpp) -target_link_libraries(example_actor_concurrent myframe) +target_link_libraries(example_actor_concurrent ${PROJECT_NAME}) ### worker add_library(example_worker_publish SHARED example_worker_publish.cpp) -target_link_libraries(example_worker_publish myframe) +target_link_libraries(example_worker_publish ${PROJECT_NAME}) add_library(example_worker_talk SHARED example_worker_talk.cpp) -target_link_libraries(example_worker_talk myframe) +target_link_libraries(example_worker_talk ${PROJECT_NAME}) add_library(example_worker_actor_interactive SHARED example_worker_actor_interactive.cpp) -target_link_libraries(example_worker_actor_interactive myframe) +target_link_libraries(example_worker_actor_interactive ${PROJECT_NAME}) add_library(example_worker_interactive_with_3rd_frame SHARED example_worker_interactive_with_3rd_frame.cpp) -target_link_libraries(example_worker_interactive_with_3rd_frame myframe) +target_link_libraries(example_worker_interactive_with_3rd_frame ${PROJECT_NAME}) add_library(example_worker_quit SHARED example_worker_quit.cpp) -target_link_libraries(example_worker_quit myframe) +target_link_libraries(example_worker_quit ${PROJECT_NAME}) add_library(example_config SHARED example_config.cpp) -target_link_libraries(example_config myframe) +target_link_libraries(example_config ${PROJECT_NAME}) add_library(example_trans_obj SHARED example_trans_obj.cpp) -target_link_libraries(example_trans_obj myframe) +target_link_libraries(example_trans_obj ${PROJECT_NAME}) ### install FILE(GLOB conf_files "*.json") INSTALL(FILES ${conf_files} - PERMISSIONS - OWNER_READ - GROUP_READ - WORLD_READ + PERMISSIONS OWNER_READ GROUP_READ WORLD_READ DESTINATION ${MYFRAME_SERVICE_DIR} ) INSTALL(TARGETS diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 9636aef..3a61699 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -4,16 +4,15 @@ CMAKE_MINIMUM_REQUIRED(VERSION 3.10) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/launcher_config.h.in ${CMAKE_CURRENT_SOURCE_DIR}/launcher_config.h @ONLY) ### source -get_filename_component(PROJECT_NAME ${CMAKE_CURRENT_LIST_DIR} NAME_WE) -project(${PROJECT_NAME}) +get_filename_component(DIR_NAME ${CMAKE_CURRENT_LIST_DIR} NAME_WE) aux_source_directory(. __srcs) ### bin -add_executable(${PROJECT_NAME} ${__srcs}) -target_link_libraries(${PROJECT_NAME} myframe) +add_executable(${DIR_NAME} ${__srcs}) +target_link_libraries(${DIR_NAME} ${PROJECT_NAME}) ### install -install(TARGETS ${PROJECT_NAME} +install(TARGETS ${DIR_NAME} LIBRARY DESTINATION ${MYFRAME_LIB_DIR} ARCHIVE DESTINATION ${MYFRAME_LIB_DIR} RUNTIME DESTINATION ${MYFRAME_BIN_DIR} diff --git a/myframe/CMakeLists.txt b/myframe/CMakeLists.txt index e24ff3f..0a71c97 100644 --- a/myframe/CMakeLists.txt +++ b/myframe/CMakeLists.txt @@ -1,8 +1,6 @@ cmake_minimum_required(VERSION 3.10) ### source -get_filename_component(PROJECT_NAME ${CMAKE_CURRENT_LIST_DIR} NAME_WE) -project(${PROJECT_NAME}) aux_source_directory(. __srcs) ### lib @@ -25,11 +23,8 @@ file(GLOB header_files ) install(FILES ${header_files} - PERMISSIONS - OWNER_READ - GROUP_READ - WORLD_READ - DESTINATION ${MYFRAME_INC_DIR}/myframe + PERMISSIONS OWNER_READ GROUP_READ WORLD_READ + DESTINATION ${MYFRAME_INC_DIR}/${PROJECT_NAME} ) install(TARGETS ${PROJECT_NAME} LIBRARY DESTINATION ${MYFRAME_LIB_DIR} diff --git a/templates/CMakeLists.txt b/templates/CMakeLists.txt index 9373701..4957a29 100644 --- a/templates/CMakeLists.txt +++ b/templates/CMakeLists.txt @@ -2,11 +2,9 @@ CMAKE_MINIMUM_REQUIRED(VERSION 3.10) PROJECT(@template_name@) #### compile setting -SET(CMAKE_C_STANDARD 11) SET(CMAKE_CXX_STANDARD 17) SET(CMAKE_CXX_STANDARD_REQUIRED YES) -SET(CMAKE_C_FLAGS "-fPIC -Werror=return-type -Werror=return-local-addr") -SET(CMAKE_CXX_FLAGS "-fPIC -Werror=return-type -Werror=return-local-addr") +SET(CMAKE_CXX_FLAGS "-fPIC -Wall -Wextra -Werror") #### path setting SET(CMAKE_INSTALL_PREFIX "$ENV{HOME}/myframe") @@ -48,9 +46,6 @@ INSTALL(TARGETS ${PROJECT_NAME} FILE(GLOB conf_files "*.json") INSTALL(FILES ${conf_files} - PERMISSIONS - OWNER_READ - GROUP_READ - WORLD_READ + PERMISSIONS OWNER_READ GROUP_READ WORLD_READ DESTINATION ${MYFRAME_INSTALL_SERVICE_DIR} ) From bdb6935b81f19ac1d38c0408c193679467cccf86 Mon Sep 17 00:00:00 2001 From: likepeng01 Date: Thu, 20 Jul 2023 19:26:16 +0800 Subject: [PATCH 06/17] arrange ci --- .github/workflows/android.yml | 58 +++++++++++++++++++++ .github/workflows/cmake.yml | 90 --------------------------------- .github/workflows/codestyle.yml | 13 +++++ .github/workflows/linux.yml | 56 ++++++++++++++++++++ CMakeLists.txt | 15 +----- 5 files changed, 128 insertions(+), 104 deletions(-) create mode 100644 .github/workflows/android.yml delete mode 100644 .github/workflows/cmake.yml create mode 100644 .github/workflows/codestyle.yml create mode 100644 .github/workflows/linux.yml diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml new file mode 100644 index 0000000..2331ad0 --- /dev/null +++ b/.github/workflows/android.yml @@ -0,0 +1,58 @@ +name: Android + +on: [push, pull_request] + +jobs: + build-android: + name: NDK-C++${{matrix.std}}-${{matrix.abi}}-${{matrix.build_type}} + runs-on: ubuntu-latest + defaults: + run: + shell: bash + env: + NDK_VERSION: 25.0.8775105 + strategy: + fail-fast: true + matrix: + std: [17, 20] + abi: [arm64-v8a, armeabi-v7a, x86_64, x86] + build_type: [Debug, Release] + + steps: + - uses: actions/checkout@v3 + + - name: Setup Ninja + uses: ashutoshvarma/setup-ninja@master + with: + version: 1.10.0 + + - name: Setup NDK + env: + ANDROID_SDK_ROOT: /usr/local/lib/android/sdk + run: | + echo 'y' | ${{env.ANDROID_SDK_ROOT}}/cmdline-tools/latest/bin/sdkmanager --install 'ndk;${{env.NDK_VERSION}}' + + - name: Configure + env: + CXXFLAGS: -fPIC -Wall -Wextra -Werror -pedantic-errors \ + -Wswitch-default -Wfloat-equal -Wshadow -Wcast-qual \ + -Wnon-virtual-dtor -Wold-style-cast -Woverloaded-virtual -Wsign-promo -Wsuggest-override \ + -DNDEBUG ${{env.CXXFLAGS}} + run: | + cmake -S . -B build_${{matrix.abi}} \ + -DCMAKE_ANDROID_API=28 \ + -DCMAKE_ANDROID_ARCH_ABI=${{matrix.abi}} \ + -DCMAKE_ANDROID_NDK=/usr/local/lib/android/sdk/ndk/${{env.NDK_VERSION}} \ + -DCMAKE_ANDROID_STL_TYPE=c++_shared \ + -DCMAKE_BUILD_TYPE=${{matrix.build_type}} \ + -DCMAKE_CXX_EXTENSIONS=OFF \ + -DCMAKE_CXX_STANDARD=${{matrix.std}} \ + -DCMAKE_CXX_STANDARD_REQUIRED=ON \ + -DCMAKE_SYSTEM_NAME=Android \ + -G Ninja \ + -Werror + + - name: Build + run: | + cmake --build build_${{matrix.abi}} \ + --config ${{matrix.build_type}} diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml deleted file mode 100644 index 76d401e..0000000 --- a/.github/workflows/cmake.yml +++ /dev/null @@ -1,90 +0,0 @@ -name: CMake - -on: - push: - branches: [ master, dev ] - pull_request: - branches: [ master ] - -env: - # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) - BUILD_TYPE: Release - -jobs: - Ubuntu-latest: - # The CMake configure and build commands are platform agnostic and should work equally well on Windows or Mac. - # You can convert this to a matrix build if you need cross-platform coverage. - # See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - - run: sudo apt update - - run: sudo apt install build-essential cmake git - - run: sudo apt install libjsoncpp-dev libgflags-dev libgtest-dev libgoogle-glog-dev libunwind-dev - - name: Check code style - run: bash ${{github.workspace}}/cpplint.bash - - - name: Configure CMake - # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. - # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type - run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} - - - name: Build - # Build your program with the given configuration - run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} - - - name: Install - run: cd ${{github.workspace}}/build && sudo make install - - Ubuntu2004: - # The CMake configure and build commands are platform agnostic and should work equally well on Windows or Mac. - # You can convert this to a matrix build if you need cross-platform coverage. - # See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix - runs-on: ubuntu-20.04 - - steps: - - uses: actions/checkout@v2 - - run: sudo apt update - - run: sudo apt install build-essential cmake git - - run: sudo apt install libjsoncpp-dev libgflags-dev libgtest-dev libgoogle-glog-dev - - name: Check code style - run: bash ${{github.workspace}}/cpplint.bash - - - name: Configure CMake - # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. - # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type - run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} - - - name: Build - # Build your program with the given configuration - run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} - - - name: Install - run: cd ${{github.workspace}}/build && sudo make install - - Ubuntu2204: - # The CMake configure and build commands are platform agnostic and should work equally well on Windows or Mac. - # You can convert this to a matrix build if you need cross-platform coverage. - # See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix - runs-on: ubuntu-22.04 - - steps: - - uses: actions/checkout@v2 - - run: sudo apt update - - run: sudo apt install build-essential cmake git - - run: sudo apt install libjsoncpp-dev libgflags-dev libgtest-dev libgoogle-glog-dev libunwind-dev - - name: Check code style - run: bash ${{github.workspace}}/cpplint.bash - - - name: Configure CMake - # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. - # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type - run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} - - - name: Build - # Build your program with the given configuration - run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} - - - name: Install - run: cd ${{github.workspace}}/build && sudo make install diff --git a/.github/workflows/codestyle.yml b/.github/workflows/codestyle.yml new file mode 100644 index 0000000..8fcea64 --- /dev/null +++ b/.github/workflows/codestyle.yml @@ -0,0 +1,13 @@ +name: codestyle + +on: [push, pull_request] + +jobs: + Ubuntu-latest: + name: codestyle + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - name: Check code style + run: bash ${{github.workspace}}/cpplint.bash \ No newline at end of file diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml new file mode 100644 index 0000000..2611150 --- /dev/null +++ b/.github/workflows/linux.yml @@ -0,0 +1,56 @@ +name: Linux + +on: [push, pull_request] + +jobs: + Ubuntu-latest: + name: GCC-C++${{matrix.std}}-${{matrix.build_type}} + # The CMake configure and build commands are platform agnostic and should work equally well on Windows or Mac. + # You can convert this to a matrix build if you need cross-platform coverage. + # See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix + runs-on: ubuntu-latest + strategy: + fail-fast: true + matrix: + build_type: [Release, Debug] + std: [17, 20] + + steps: + - uses: actions/checkout@v3 + - run: sudo apt update + - run: sudo apt install build-essential cmake ninja-build + - run: sudo apt install libjsoncpp-dev libgflags-dev libgtest-dev libgoogle-glog-dev libunwind-dev + + - name: Setup Ninja + uses: ashutoshvarma/setup-ninja@master + with: + version: 1.10.0 + + - name: Configure CMake + env: + # glog option: + # -DNDEBUG + # -DDCHECK_ALWAYS_ON + # unit test option: + # -fno-omit-frame-pointer -fsanitize=address -fsanitize=undefined + CXXFLAGS: -fPIC -Wall -Wextra -Werror -pedantic-errors \ + -Wswitch-default -Wfloat-equal -Wshadow -Wcast-qual \ + -Wnon-virtual-dtor -Wold-style-cast -Woverloaded-virtual -Wsign-promo -Wsuggest-override \ + -DNDEBUG ${{env.CXXFLAGS}} + # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. + # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type + run: | + cmake -S . -B ${{github.workspace}}/build_${{matrix.build_type}} \ + -DCMAKE_CXX_STANDARD=${{matrix.std}} \ + -DCMAKE_CXX_STANDARD_REQUIRED=ON \ + -DCMAKE_BUILD_TYPE=${{matrix.build_type}} \ + -DCMAKE_INSTALL_PREFIX=${{github.workspace}}/install \ + -G Ninja \ + -Werror + + - name: Build + # Build your program with the given configuration + run: cmake --build ${{github.workspace}}/build_${{matrix.build_type}} --config ${{matrix.build_type}} + + - name: Install + run: cd ${{github.workspace}}/build_${{matrix.build_type}} && sudo make install diff --git a/CMakeLists.txt b/CMakeLists.txt index d2b7eb8..28f48d1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,19 +12,6 @@ if (CMAKE_COMPILER_IS_GNUCC) endif () ### cpp option -set(CMAKE_CXX_STANDARD 17) -set(CMAKE_CXX_STANDARD_REQUIRED YES) -# glog option: -# -DNDEBUG -# -DDCHECK_ALWAYS_ON -# unit test option: -# -fno-omit-frame-pointer -fsanitize=address -fsanitize=undefined -set(CMAKE_CXX_FLAGS - "-fPIC -Wall -Wextra -Werror -pedantic-errors \ - -Wswitch-default -Wfloat-equal -Wshadow -Wcast-qual \ - -Wnon-virtual-dtor -Wold-style-cast -Woverloaded-virtual -Wsign-promo -Wsuggest-override \ - -DNDEBUG" -) if (GCC_VERSION GREATER "8.0") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wextra-semi") endif () @@ -40,7 +27,7 @@ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${MYFRAME_OUTPUT_ROOT}/lib) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${MYFRAME_OUTPUT_ROOT}/bin) ### install path -set(CMAKE_INSTALL_PREFIX "$ENV{HOME}/${CMAKE_PROJECT_NAME}") +# set(CMAKE_INSTALL_PREFIX "$ENV{HOME}/${CMAKE_PROJECT_NAME}") set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") set(MYFRAME_TEST_DIR "test") set(MYFRAME_BIN_DIR "bin") From 9736062a83d85a56c62f493cc137028fc54d0caa Mon Sep 17 00:00:00 2001 From: likepeng01 Date: Thu, 20 Jul 2023 19:30:47 +0800 Subject: [PATCH 07/17] fix ci --- .github/workflows/android.yml | 5 +---- .github/workflows/linux.yml | 5 +---- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 2331ad0..2ecbd2f 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -34,10 +34,7 @@ jobs: - name: Configure env: - CXXFLAGS: -fPIC -Wall -Wextra -Werror -pedantic-errors \ - -Wswitch-default -Wfloat-equal -Wshadow -Wcast-qual \ - -Wnon-virtual-dtor -Wold-style-cast -Woverloaded-virtual -Wsign-promo -Wsuggest-override \ - -DNDEBUG ${{env.CXXFLAGS}} + CXXFLAGS: ${{env.CXXFLAGS}} -DNDEBUG -fPIC -Wall -Wextra -Werror -pedantic-errors -Wswitch-default -Wfloat-equal -Wshadow -Wcast-qual -Wnon-virtual-dtor -Wold-style-cast -Woverloaded-virtual -Wsign-promo -Wsuggest-override run: | cmake -S . -B build_${{matrix.abi}} \ -DCMAKE_ANDROID_API=28 \ diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 2611150..df95aad 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -33,10 +33,7 @@ jobs: # -DDCHECK_ALWAYS_ON # unit test option: # -fno-omit-frame-pointer -fsanitize=address -fsanitize=undefined - CXXFLAGS: -fPIC -Wall -Wextra -Werror -pedantic-errors \ - -Wswitch-default -Wfloat-equal -Wshadow -Wcast-qual \ - -Wnon-virtual-dtor -Wold-style-cast -Woverloaded-virtual -Wsign-promo -Wsuggest-override \ - -DNDEBUG ${{env.CXXFLAGS}} + CXXFLAGS: ${{env.CXXFLAGS}} -DNDEBUG -fPIC -Wall -Wextra -Werror -pedantic-errors -Wswitch-default -Wfloat-equal -Wshadow -Wcast-qual -Wnon-virtual-dtor -Wold-style-cast -Woverloaded-virtual -Wsign-promo -Wsuggest-override # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type run: | From 614ad39e3e2f642b1c63b631b27a6b4ae1d88afa Mon Sep 17 00:00:00 2001 From: likepeng01 Date: Thu, 20 Jul 2023 19:36:48 +0800 Subject: [PATCH 08/17] fix ci --- .github/workflows/android.yml | 55 ----------------------------------- .github/workflows/linux.yml | 3 -- 2 files changed, 58 deletions(-) delete mode 100644 .github/workflows/android.yml diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml deleted file mode 100644 index 2ecbd2f..0000000 --- a/.github/workflows/android.yml +++ /dev/null @@ -1,55 +0,0 @@ -name: Android - -on: [push, pull_request] - -jobs: - build-android: - name: NDK-C++${{matrix.std}}-${{matrix.abi}}-${{matrix.build_type}} - runs-on: ubuntu-latest - defaults: - run: - shell: bash - env: - NDK_VERSION: 25.0.8775105 - strategy: - fail-fast: true - matrix: - std: [17, 20] - abi: [arm64-v8a, armeabi-v7a, x86_64, x86] - build_type: [Debug, Release] - - steps: - - uses: actions/checkout@v3 - - - name: Setup Ninja - uses: ashutoshvarma/setup-ninja@master - with: - version: 1.10.0 - - - name: Setup NDK - env: - ANDROID_SDK_ROOT: /usr/local/lib/android/sdk - run: | - echo 'y' | ${{env.ANDROID_SDK_ROOT}}/cmdline-tools/latest/bin/sdkmanager --install 'ndk;${{env.NDK_VERSION}}' - - - name: Configure - env: - CXXFLAGS: ${{env.CXXFLAGS}} -DNDEBUG -fPIC -Wall -Wextra -Werror -pedantic-errors -Wswitch-default -Wfloat-equal -Wshadow -Wcast-qual -Wnon-virtual-dtor -Wold-style-cast -Woverloaded-virtual -Wsign-promo -Wsuggest-override - run: | - cmake -S . -B build_${{matrix.abi}} \ - -DCMAKE_ANDROID_API=28 \ - -DCMAKE_ANDROID_ARCH_ABI=${{matrix.abi}} \ - -DCMAKE_ANDROID_NDK=/usr/local/lib/android/sdk/ndk/${{env.NDK_VERSION}} \ - -DCMAKE_ANDROID_STL_TYPE=c++_shared \ - -DCMAKE_BUILD_TYPE=${{matrix.build_type}} \ - -DCMAKE_CXX_EXTENSIONS=OFF \ - -DCMAKE_CXX_STANDARD=${{matrix.std}} \ - -DCMAKE_CXX_STANDARD_REQUIRED=ON \ - -DCMAKE_SYSTEM_NAME=Android \ - -G Ninja \ - -Werror - - - name: Build - run: | - cmake --build build_${{matrix.abi}} \ - --config ${{matrix.build_type}} diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index df95aad..e81d035 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -48,6 +48,3 @@ jobs: - name: Build # Build your program with the given configuration run: cmake --build ${{github.workspace}}/build_${{matrix.build_type}} --config ${{matrix.build_type}} - - - name: Install - run: cd ${{github.workspace}}/build_${{matrix.build_type}} && sudo make install From b3490aace06853d99bfba7d54289be957cfe2805 Mon Sep 17 00:00:00 2001 From: likepeng01 Date: Thu, 20 Jul 2023 20:36:25 +0800 Subject: [PATCH 09/17] update doc --- README.md | 18 ++++-------------- doc/TODOLIST.md | 1 - doc/development_guide.md | 19 +++++++++++++++++-- templates/CMakeLists.txt | 1 - tools/gen_mod_proj.py | 9 ++++----- 5 files changed, 25 insertions(+), 23 deletions(-) delete mode 100644 doc/TODOLIST.md diff --git a/README.md b/README.md index 9b678d4..27a6540 100644 --- a/README.md +++ b/README.md @@ -3,28 +3,19 @@ ![myframe](doc/pics/myframe.png) ## 概述 -C++实现的actors框架,程序由actor和worker组成; +C++实现的组件化的编程框架,程序由actor和worker组成; actor基于消息驱动,actor之间可以进行消息传递; worker自驱动,可以通过消息与actor交互; -组件化的编程模式可以提高代码复用,降低程序耦合度。 +适用于构建中大型项目. ## 开发/运行环境 操作系统: Ubuntu 18.04+ 开发语言:C++17 -## 安装依赖 -参考 [github ci](.github/workflows/cmake.yml) - ## 构建 -```sh -mkdir build -cd build -cmake .. -# 默认安装到HOME目录 -make -j4 install -``` +参考 [github ci](.github/workflows/linux.yml) -## 运行 +## 运行所有的example ```sh cd ~/myframe/bin ./launcher -p app @@ -102,4 +93,3 @@ extern "C" std::shared_ptr actor_create(const std::string& actor_name) { - [Discussions](https://github.com/lkpworkspace/myframe/discussions) - [WIKI](https://github.com/lkpworkspace/myframe/wiki) - [FAQ](https://github.com/lkpworkspace/myframe/wiki/FAQs) -- [TODOLIST](doc/TODOLIST.md) diff --git a/doc/TODOLIST.md b/doc/TODOLIST.md deleted file mode 100644 index 6ecf57b..0000000 --- a/doc/TODOLIST.md +++ /dev/null @@ -1 +0,0 @@ -# TODOLIST diff --git a/doc/development_guide.md b/doc/development_guide.md index b7eeebf..bd3a5d3 100644 --- a/doc/development_guide.md +++ b/doc/development_guide.md @@ -62,5 +62,20 @@ python3 ~/myframe/tools/gen_mod_proj.py --dir="/path/to/proj_dir/" --name="mod_n - 配置文件: - Template.json:Service配置 -### 安装 -通过make install安装到框架中的组件目录中 +### 组件工程构建安装 +```sh +cmake -S . -B build -DCMAKE_INSTALL_PREFIX=${myframe目录} +make -C build -j "$(nproc)" install +``` + +### 运行组件 +```sh +cd ${myframe目录}/bin +./launcher -c ${组件名}.json -p app +``` + +### 查看运行日志 +```sh +cd ${myframe目录}/log +vi ${日志} +``` diff --git a/templates/CMakeLists.txt b/templates/CMakeLists.txt index 4957a29..3d28118 100644 --- a/templates/CMakeLists.txt +++ b/templates/CMakeLists.txt @@ -7,7 +7,6 @@ SET(CMAKE_CXX_STANDARD_REQUIRED YES) SET(CMAKE_CXX_FLAGS "-fPIC -Wall -Wextra -Werror") #### path setting -SET(CMAKE_INSTALL_PREFIX "$ENV{HOME}/myframe") SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") SET(MYFRAME_INSTALL_SERVICE_DIR ${CMAKE_INSTALL_PREFIX}/service) SET(MYFRAME_INSTALL_LIB_DIR ${CMAKE_INSTALL_PREFIX}/lib) diff --git a/tools/gen_mod_proj.py b/tools/gen_mod_proj.py index c7dfba9..ff31d66 100644 --- a/tools/gen_mod_proj.py +++ b/tools/gen_mod_proj.py @@ -6,12 +6,12 @@ import shutil def dumpUsage(): - print("Usage: python3 ~/myframe/tools/gen_mod_proj.py --name=MOD_NAME --dir=MOD_DIR") + print("Usage: python3 gen_mod_proj.py --name=MOD_NAME --dir=MOD_DIR") print("Options:") print(" --name MOD_NAME Base module name, for example: usermod") print(" --dir MOD_DIR Base module project dirtory, for example: /home/yourname/") print("") - print("Sample: python3 ~/myframe/tools/gen_mod_proj.py --name=\"usermod\" --dir=\"/home/yourname/\"") + print("Sample: python3 gen_mod_proj.py --name=\"usermod\" --dir=\"/home/yourname/\"") print("") def checkParams(opts): @@ -72,11 +72,11 @@ def replaceFile(params, file): dumpUsage() sys.exit(1) - proj_src_dir = "" + proj_src_dir = os.path.split(os.path.realpath(__file__))[0] proj_rename_dict = {} proj_modify_var_list = [] # 设置要修改的文件 - proj_src_dir = os.environ['HOME'] + "/myframe/templates/" + proj_src_dir = proj_src_dir + "/../templates/" proj_rename_dict[params_dict["dir"] + "template.cpp"] = params_dict["dir"] + params_dict["name"] + ".cpp" proj_rename_dict[params_dict["dir"] + "template.json"] = params_dict["dir"] + params_dict["name"] + ".json" proj_modify_var_list.append(params_dict["dir"] + "CMakeLists.txt") @@ -95,4 +95,3 @@ def replaceFile(params, file): replaceFile(params_dict, v) print("Success!!!") - \ No newline at end of file From 0fbc894169413e771ac0008d75d951137a1328cf Mon Sep 17 00:00:00 2001 From: likepeng01 Date: Thu, 20 Jul 2023 23:23:01 +0800 Subject: [PATCH 10/17] fix template error --- templates/CMakeLists.txt | 2 +- templates/template.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/templates/CMakeLists.txt b/templates/CMakeLists.txt index 3d28118..c690e6f 100644 --- a/templates/CMakeLists.txt +++ b/templates/CMakeLists.txt @@ -17,7 +17,7 @@ FIND_PACKAGE(gflags REQUIRED) FIND_PACKAGE(GTest REQUIRED) #### include directory -INCLUDE_DIRECTORIES(${CMAKE_INSTALL_PREFIX}/inc) +INCLUDE_DIRECTORIES(${CMAKE_INSTALL_PREFIX}/include) #### deps libs LINK_LIBRARIES( diff --git a/templates/template.cpp b/templates/template.cpp index be21410..c70a627 100644 --- a/templates/template.cpp +++ b/templates/template.cpp @@ -18,6 +18,7 @@ class @template_name@Actor : public myframe::Actor { public: /* actor模块加载完毕后调用 */ int Init(const char* param) override { + (void)param; return 0; } From f285f062b6d68c2a5e9478e18d617718b3b29c6f Mon Sep 17 00:00:00 2001 From: likepeng01 Date: Fri, 21 Jul 2023 14:16:01 +0800 Subject: [PATCH 11/17] using shared_library --- myframe/CMakeLists.txt | 2 - myframe/mod_lib.cpp | 128 ------------------------------------- myframe/mod_lib.h | 77 ---------------------- myframe/mod_manager.cpp | 75 ++++++++++++++++++++-- myframe/mod_manager.h | 10 ++- myframe/shared_library.cpp | 81 +++++++++++++++++++++++ myframe/shared_library.h | 58 +++++++++++++++++ 7 files changed, 215 insertions(+), 216 deletions(-) delete mode 100644 myframe/mod_lib.cpp delete mode 100644 myframe/mod_lib.h create mode 100644 myframe/shared_library.cpp create mode 100644 myframe/shared_library.h diff --git a/myframe/CMakeLists.txt b/myframe/CMakeLists.txt index 0a71c97..47b12e9 100644 --- a/myframe/CMakeLists.txt +++ b/myframe/CMakeLists.txt @@ -17,8 +17,6 @@ file(GLOB header_files actor.h event.h worker.h - mod_lib.h - mod_manager.h app.h ) install(FILES diff --git a/myframe/mod_lib.cpp b/myframe/mod_lib.cpp deleted file mode 100644 index 18b3a48..0000000 --- a/myframe/mod_lib.cpp +++ /dev/null @@ -1,128 +0,0 @@ -/**************************************************************************** -Copyright (c) 2018, likepeng -All rights reserved. - -Author: likepeng -****************************************************************************/ - -#include "myframe/mod_lib.h" - -#include - -#include - -#include "myframe/actor.h" -#include "myframe/worker.h" - -namespace myframe { - -ModLib::ModLib() {} - -ModLib::~ModLib() { - std::unique_lock lk(rw_); - for (const auto& p : mods_) { - dlclose(p.second); - } - mods_.clear(); -} - -std::string ModLib::GetModName(const std::string& full_path) { - auto pos = full_path.find_last_of('/'); - pos = (pos == std::string::npos) ? -1 : pos; - return full_path.substr(pos + 1); -} - -bool ModLib::LoadMod(const std::string& dlpath) { - auto dlname = GetModName(dlpath); - std::unique_lock lk(rw_); - if (mods_.find(dlname) != mods_.end()) { - DLOG(INFO) << dlname << " has loaded"; - return true; - } - - void* dll_handle = dlopen(dlpath.c_str(), RTLD_NOW | RTLD_LOCAL); - if (dll_handle == nullptr) { - LOG(ERROR) << "Open dll " << dlpath << " failed, " << dlerror(); - return false; - } - mods_[dlname] = dll_handle; - LOG(INFO) << "Load lib " << dlpath; - return true; -} - -bool ModLib::IsLoad(const std::string& dlname) { - std::shared_lock lk(rw_); - auto res = mods_.find(dlname) != mods_.end(); - return res; -} - -bool ModLib::UnloadMod(const std::string& dlname) { - std::unique_lock lk(rw_); - if (mods_.find(dlname) == mods_.end()) { - return true; - } - - if (dlclose(mods_[dlname])) { - LOG(ERROR) << "lib close failed, " << dlerror(); - } - mods_.erase(dlname); - return true; -} - -std::shared_ptr ModLib::CreateWorkerInst( - const std::string& mod_name, const std::string& worker_name) { - std::shared_lock lk(rw_); - if (mods_.find(mod_name) == mods_.end()) { - LOG(ERROR) << "Find " << mod_name << "." << worker_name << " failed"; - return nullptr; - } - void* handle = mods_[mod_name]; - auto void_func = dlsym(handle, "worker_create"); - auto create = reinterpret_cast(void_func); - if (nullptr == create) { - LOG(ERROR) - << "Load " << mod_name << "." << worker_name - << " module worker_create function failed"; - return nullptr; - } - auto worker = create(worker_name); - if (nullptr == worker) { - LOG(ERROR) - << "Create " << mod_name << "." << worker_name - << " failed"; - return nullptr; - } - worker->SetModName(mod_name); - worker->SetTypeName(worker_name); - return worker; -} - -std::shared_ptr ModLib::CreateActorInst( - const std::string& mod_name, const std::string& actor_name) { - std::shared_lock lk(rw_); - if (mods_.find(mod_name) == mods_.end()) { - LOG(ERROR) << "Find " << mod_name << "." << actor_name << " failed"; - return nullptr; - } - void* handle = mods_[mod_name]; - auto void_func = dlsym(handle, "actor_create"); - auto create = reinterpret_cast(void_func); - if (nullptr == create) { - LOG(ERROR) - << "Load " << mod_name << "." << actor_name - << " module actor_create function failed"; - return nullptr; - } - auto actor = create(actor_name); - if (nullptr == actor) { - LOG(ERROR) - << "Create " << mod_name << "." << actor_name - << " failed"; - return nullptr; - } - actor->SetModName(mod_name); - actor->SetTypeName(actor_name); - return actor; -} - -} // namespace myframe diff --git a/myframe/mod_lib.h b/myframe/mod_lib.h deleted file mode 100644 index 57706c0..0000000 --- a/myframe/mod_lib.h +++ /dev/null @@ -1,77 +0,0 @@ -/**************************************************************************** -Copyright (c) 2018, likepeng -All rights reserved. - -Author: likepeng -****************************************************************************/ - -#pragma once -#include -#include -#include -#include -#include -#include - -#include "myframe/macros.h" - -namespace myframe { - -class Actor; -class Worker; -class ModLib final { - public: - ModLib(); - virtual ~ModLib(); - - /** - * @brief 是否加载动态库 - * - * @param dlname lib name - * @return true - * @return false - */ - bool IsLoad(const std::string& dlname); - - /** - * @brief 加载模块动态库 - * - * @param dlname full lib path - * @return true - * @return false - */ - bool LoadMod(const std::string& dlpath); - - /** - * @brief 创建actor实例 - * - * @param mod_name eg: libtest.so - * @param actor_name eg: /my/test - * @return std::shared_ptr - */ - std::shared_ptr CreateActorInst( - const std::string& mod_name, - const std::string& actor_name); - - /** - * @brief 创建Worker实例 - * - * @param mod_name eg: libtest.so - * @param worker_name eg: /my/test - * @return Worker* - */ - std::shared_ptr CreateWorkerInst( - const std::string& mod_name, - const std::string& worker_name); - - private: - bool UnloadMod(const std::string& dlname); - std::string GetModName(const std::string& full_path); - - std::unordered_map mods_; - std::shared_mutex rw_; - - DISALLOW_COPY_AND_ASSIGN(ModLib) -}; - -} // namespace myframe diff --git a/myframe/mod_manager.cpp b/myframe/mod_manager.cpp index 33e5354..9cf3319 100644 --- a/myframe/mod_manager.cpp +++ b/myframe/mod_manager.cpp @@ -10,6 +10,7 @@ Author: likepeng #include #include +#include "myframe/shared_library.h" #include "myframe/actor.h" #include "myframe/worker.h" @@ -24,7 +25,19 @@ ModManager::~ModManager() { } bool ModManager::LoadMod(const std::string& dl_path) { - return lib_mods_.LoadMod(dl_path); + auto dlname = GetLibName(dl_path); + std::unique_lock lk(mods_rw_); + if (mods_.find(dlname) != mods_.end()) { + DLOG(ERROR) << dlname << " has loaded"; + return false; + } + auto lib = std::make_shared(); + if (!lib->Load(dl_path, SharedLibrary::Flags::kLocal)) { + return false; + } + mods_[dlname] = lib; + LOG(INFO) << "Load lib " << dl_path; + return true; } bool ModManager::RegActor( @@ -57,9 +70,30 @@ bool ModManager::RegWorker( std::shared_ptr ModManager::CreateActorInst( const std::string& mod_or_class_name, const std::string& actor_name) { - if (lib_mods_.IsLoad(mod_or_class_name)) { - DLOG(INFO) << actor_name << " actor from lib"; - return lib_mods_.CreateActorInst(mod_or_class_name, actor_name); + { + std::shared_lock lk(mods_rw_); + if (mods_.find(mod_or_class_name) != mods_.end()) { + DLOG(INFO) << actor_name << " actor from lib"; + auto lib = mods_[mod_or_class_name]; + auto void_func = lib->GetSymbol("actor_create"); + auto create = reinterpret_cast(void_func); + if (nullptr == create) { + LOG(ERROR) + << "Load " << mod_or_class_name << "." << actor_name + << " module actor_create function failed"; + return nullptr; + } + auto actor = create(actor_name); + if (nullptr == actor) { + LOG(ERROR) + << "Create " << mod_or_class_name << "." << actor_name + << " failed"; + return nullptr; + } + actor->SetModName(mod_or_class_name); + actor->SetTypeName(actor_name); + return actor; + } } std::shared_lock lk(class_actor_rw_); if (mod_or_class_name == "class" && @@ -75,9 +109,30 @@ std::shared_ptr ModManager::CreateActorInst( std::shared_ptr ModManager::CreateWorkerInst( const std::string& mod_or_class_name, const std::string& worker_name) { - if (lib_mods_.IsLoad(mod_or_class_name)) { - LOG(INFO) << "instance worker from lib"; - return lib_mods_.CreateWorkerInst(mod_or_class_name, worker_name); + { + std::shared_lock lk(mods_rw_); + if (mods_.find(mod_or_class_name) != mods_.end()) { + LOG(INFO) << "instance worker from lib"; + auto lib = mods_[mod_or_class_name]; + auto void_func = lib->GetSymbol("worker_create"); + auto create = reinterpret_cast(void_func); + if (nullptr == create) { + LOG(ERROR) + << "Load " << mod_or_class_name << "." << worker_name + << " module worker_create function failed"; + return nullptr; + } + auto worker = create(worker_name); + if (nullptr == worker) { + LOG(ERROR) + << "Create " << mod_or_class_name << "." << worker_name + << " failed"; + return nullptr; + } + worker->SetModName(mod_or_class_name); + worker->SetTypeName(worker_name); + return worker; + } } std::shared_lock lk(class_worker_rw_); if (mod_or_class_name == "class" && @@ -91,4 +146,10 @@ std::shared_ptr ModManager::CreateWorkerInst( return nullptr; } +std::string ModManager::GetLibName(const std::string& path) const { + auto pos = path.find_last_of('/'); + pos = (pos == std::string::npos) ? -1 : pos; + return path.substr(pos + 1); +} + } // namespace myframe diff --git a/myframe/mod_manager.h b/myframe/mod_manager.h index 28f32e5..aa75c64 100644 --- a/myframe/mod_manager.h +++ b/myframe/mod_manager.h @@ -14,10 +14,12 @@ Author: likepeng #include #include "myframe/macros.h" -#include "myframe/mod_lib.h" namespace myframe { +class Actor; +class Worker; +class SharedLibrary; class ModManager final { public: ModManager(); @@ -41,6 +43,8 @@ class ModManager final { const std::string& mod_or_class_name, const std::string& worker_name); + std::string GetLibName(const std::string& path) const; + private: std::unordered_map< std::string, std::function(const std::string&)>> @@ -50,7 +54,9 @@ class ModManager final { class_workers_; std::shared_mutex class_actor_rw_; std::shared_mutex class_worker_rw_; - ModLib lib_mods_; + + std::unordered_map> mods_; + std::shared_mutex mods_rw_; DISALLOW_COPY_AND_ASSIGN(ModManager) }; diff --git a/myframe/shared_library.cpp b/myframe/shared_library.cpp new file mode 100644 index 0000000..661fa7c --- /dev/null +++ b/myframe/shared_library.cpp @@ -0,0 +1,81 @@ +/**************************************************************************** +Copyright (c) 2018, likepeng +All rights reserved. + +Author: likepeng +****************************************************************************/ + +#include "myframe/shared_library.h" + +#include + +#include + +namespace myframe { + +SharedLibrary::~SharedLibrary() { + Unload(); +} + +bool SharedLibrary::Load(const std::string& path) { + return Load(path, Flags::kGlobal); +} + +bool SharedLibrary::Load( + const std::string& path, + Flags flags) { + std::lock_guard lock(mutex_); + if (handle_ != nullptr) { + return false; + } + int real_flag = RTLD_NOW; + if (static_cast(flags) & static_cast(Flags::kLocal)) { + real_flag |= RTLD_LOCAL; + } else { + real_flag |= RTLD_GLOBAL; + } + handle_ = dlopen(path.c_str(), real_flag); + if (handle_ == nullptr) { + LOG(ERROR) << "Open dll " << path << " failed, " << dlerror(); + return false; + } + path_ = path; + return true; +} + +void SharedLibrary::Unload() { + std::lock_guard lock(mutex_); + if (handle_ == nullptr) { + return; + } + if (dlclose(handle_)) { + LOG(ERROR) << "lib " << path_ << " close failed, " << dlerror(); + } + handle_ = nullptr; +} + +bool SharedLibrary::IsLoaded() { + std::lock_guard lock(mutex_); + return handle_ != nullptr; +} + +bool SharedLibrary::HasSymbol(const std::string& name) { + return GetSymbol(name) != nullptr; +} + +void* SharedLibrary::GetSymbol(const std::string& name) { + std::lock_guard lock(mutex_); + if (handle_ == nullptr) { + return nullptr; + } + + void* result = dlsym(handle_, name.c_str()); + if (result == nullptr) { + LOG(ERROR) << "lib " << path_ + << " has no symbol " << name << ", " << dlerror(); + return nullptr; + } + return result; +} + +} // namespace myframe diff --git a/myframe/shared_library.h b/myframe/shared_library.h new file mode 100644 index 0000000..f8c646b --- /dev/null +++ b/myframe/shared_library.h @@ -0,0 +1,58 @@ +/**************************************************************************** +Copyright (c) 2018, likepeng +All rights reserved. + +Author: likepeng +****************************************************************************/ + +#pragma once +#include +#include +#include +#include + +#include "myframe/macros.h" + +namespace myframe { + +class SharedLibrary { + public: + enum class Flags : int { + // On platforms that use dlopen(), use RTLD_GLOBAL. This is the default + // if no flags are given. + kGlobal = 1, + + // On platforms that use dlopen(), use RTLD_LOCAL instead of RTLD_GLOBAL. + // + // Note that if this flag is specified, RTTI (including dynamic_cast and + // throw) will not work for types defined in the shared library with GCC + // and possibly other compilers as well. See + // http://gcc.gnu.org/faq.html#dso for more information. + kLocal = 2, + }; + + SharedLibrary() = default; + virtual ~SharedLibrary(); + + bool Load(const std::string& path); + bool Load(const std::string& path, Flags flags); + + void Unload(); + + bool IsLoaded(); + + bool HasSymbol(const std::string& name); + + void* GetSymbol(const std::string& name); + + inline const std::string& GetPath() const { return path_; } + + private: + void* handle_{ nullptr }; + std::string path_; + std::mutex mutex_; + + DISALLOW_COPY_AND_ASSIGN(SharedLibrary) +}; + +} // namespace myframe From e47dc7478b3f5b6f6fea6c51ee6c583a06b7e8da Mon Sep 17 00:00:00 2001 From: likepeng01 Date: Fri, 21 Jul 2023 15:41:28 +0800 Subject: [PATCH 12/17] move enum to class --- ...mple_worker_interactive_with_3rd_frame.cpp | 26 +++---- launcher/launcher.cpp | 5 +- myframe/app.cpp | 68 +++++++++---------- myframe/app.h | 4 +- myframe/cmd_channel.cpp | 4 +- myframe/cmd_channel.h | 23 ++++--- myframe/event.h | 34 +++++----- myframe/event_conn.cpp | 18 ++--- myframe/event_conn.h | 18 ++--- myframe/event_conn_manager.cpp | 8 +-- myframe/worker.cpp | 12 ++-- myframe/worker.h | 2 +- myframe/worker_common.h | 4 +- myframe/worker_context.cpp | 10 +-- myframe/worker_context.h | 22 +++--- myframe/worker_context_manager.cpp | 20 +++--- myframe/worker_timer.h | 4 +- 17 files changed, 144 insertions(+), 138 deletions(-) diff --git a/examples/example_worker_interactive_with_3rd_frame.cpp b/examples/example_worker_interactive_with_3rd_frame.cpp index 6b66cf4..ef00211 100644 --- a/examples/example_worker_interactive_with_3rd_frame.cpp +++ b/examples/example_worker_interactive_with_3rd_frame.cpp @@ -24,23 +24,23 @@ class MyQueue final { MyQueue() = default; ~MyQueue() = default; - int GetFd0() { return cmd_channel_.GetOwnerFd(); } - int GetFd1() { return cmd_channel_.GetMainFd(); } + int GetFd0() { return cmd_channel_.GetOwnerHandle(); } + int GetFd1() { return cmd_channel_.GetMainHandle(); } void Push(std::shared_ptr data) { data_ = data; - myframe::Cmd cmd = myframe::Cmd::kRun; + myframe::CmdChannel::Cmd cmd = myframe::CmdChannel::Cmd::kRun; cmd_channel_.SendToOwner(cmd); cmd_channel_.RecvFromOwner(&cmd); } std::shared_ptr Pop() { std::shared_ptr ret = nullptr; - myframe::Cmd cmd = myframe::Cmd::kRun; + myframe::CmdChannel::Cmd cmd = myframe::CmdChannel::Cmd::kRun; cmd_channel_.RecvFromMain(&cmd); ret = data_; data_ = nullptr; - cmd_channel_.SendToMain(myframe::Cmd::kIdle); + cmd_channel_.SendToMain(myframe::CmdChannel::Cmd::kIdle); return ret; } @@ -70,13 +70,13 @@ class ExampleWorkerInteractiveWith3rdFrame : public myframe::Worker { }); // 通知myframe该worker可以接收来自myframe的消息 - GetCmdChannel()->SendToMain(myframe::Cmd::kWaitForMsg); + GetCmdChannel()->SendToMain(myframe::CmdChannel::Cmd::kWaitForMsg); } void Run() override { auto cmd_channel = GetCmdChannel(); struct pollfd fds[] = { - {cmd_channel->GetOwnerFd(), POLLIN, 0}, + {cmd_channel->GetOwnerHandle(), POLLIN, 0}, {queue_.GetFd0(), POLLIN, 0}}; // 等待来自queue或者myframe的消息 int ret = poll(fds, 2, -1); @@ -89,19 +89,19 @@ class ExampleWorkerInteractiveWith3rdFrame : public myframe::Worker { continue; } if (i == 0) { - myframe::Cmd cmd; + myframe::CmdChannel::Cmd cmd; cmd_channel->RecvFromMain(&cmd); - if (cmd == myframe::Cmd::kRun) { + if (cmd == myframe::CmdChannel::Cmd::kRun) { recv_run_flag_ = true; - } else if (cmd == myframe::Cmd::kRunWithMsg) { + } else if (cmd == myframe::CmdChannel::Cmd::kRunWithMsg) { auto mailbox = GetMailbox(); while (!mailbox->RecvEmpty()) { const auto& msg = mailbox->PopRecv(); // 接收到其它组件消息 LOG(INFO) << "get main " << msg->GetData(); } - cmd_channel->SendToMain(myframe::Cmd::kWaitForMsg); - } else if (cmd == myframe::Cmd::kQuit) { + cmd_channel->SendToMain(myframe::CmdChannel::Cmd::kWaitForMsg); + } else if (cmd == myframe::CmdChannel::Cmd::kQuit) { quit_.store(true); Stop(); } @@ -121,7 +121,7 @@ class ExampleWorkerInteractiveWith3rdFrame : public myframe::Worker { // mailbox->Send("actor.xx.xx", send_msgs_[i]); } send_msgs_.clear(); - cmd_channel->SendToMain(myframe::Cmd::kIdle); + cmd_channel->SendToMain(myframe::CmdChannel::Cmd::kIdle); } } diff --git a/launcher/launcher.cpp b/launcher/launcher.cpp index d07f3f9..3293dc9 100644 --- a/launcher/launcher.cpp +++ b/launcher/launcher.cpp @@ -74,7 +74,8 @@ int main(int argc, char** argv) { } if (!g_app->LoadServiceFromFile(abs_conf_file)) { LOG(ERROR) << "Load " << abs_conf_file << " failed, exit"; - return -1; + g_app->Quit(); + break; } } } else { @@ -90,7 +91,7 @@ int main(int argc, char** argv) { } if (g_app->LoadServiceFromDir(abs_service_dir) <= 0) { LOG(ERROR) << "Load service from " << abs_service_dir << " failed, exit"; - return -1; + g_app->Quit(); } } diff --git a/myframe/app.cpp b/myframe/app.cpp index 19ea4c2..d4aa81b 100644 --- a/myframe/app.cpp +++ b/myframe/app.cpp @@ -367,21 +367,21 @@ bool App::CreateActorContext( bool App::AddEvent(std::shared_ptr ev) { struct epoll_event event; - event.data.fd = ev->GetFd(); + event.data.fd = ev->GetHandle(); event.events = ToEpollType(ev->ListenIOType()); int res = 0; // 如果该事件已经注册,就修改事件类型 - res = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, ev->GetFd(), &event); + res = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, ev->GetHandle(), &event); if (-1 == res) { // 没有注册就添加至epoll - res = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, ev->GetFd(), &event); + res = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, ev->GetHandle(), &event); if (-1 == res) { LOG(ERROR) << "epoll " << strerror(errno); return false; } } else { LOG(WARNING) - << " has already reg ev " << ev->GetFd() << ": " + << " has already reg ev " << ev->GetHandle() << ": " << strerror(errno); return false; } @@ -389,8 +389,8 @@ bool App::AddEvent(std::shared_ptr ev) { } bool App::DelEvent(std::shared_ptr ev) { - if (-1 == epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, ev->GetFd(), NULL)) { - LOG(ERROR) << "del event " << ev->GetFd() << ": " << strerror(errno); + if (-1 == epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, ev->GetHandle(), NULL)) { + LOG(ERROR) << "del event " << ev->GetHandle() << ": " << strerror(errno); return false; } return true; @@ -424,22 +424,22 @@ bool App::StartTimerWorker() { return true; } -EventIOType App::ToEventIOType(int ev) { +Event::IOType App::ToEventIOType(int ev) { switch (ev) { case EPOLLIN: - return EventIOType::kIn; + return Event::IOType::kIn; case EPOLLOUT: - return EventIOType::kOut; + return Event::IOType::kOut; default: - return EventIOType::kNone; + return Event::IOType::kNone; } } -int App::ToEpollType(const EventIOType& type) { +int App::ToEpollType(const Event::IOType& type) { switch (type) { - case EventIOType::kIn: + case Event::IOType::kIn: return EPOLLIN; - case EventIOType::kOut: + case Event::IOType::kOut: return EPOLLOUT; default: return EPOLLERR; @@ -547,7 +547,7 @@ void App::CheckStopWorkers() { worker_ctx_mgr_->PopFrontIdleWorker(); auto common_idle_worker = worker_ctx->GetWorker(); common_idle_worker->SetActorContext(actor_ctx); - worker_ctx->GetCmdChannel()->SendToOwner(Cmd::kRun); + worker_ctx->GetCmdChannel()->SendToOwner(CmdChannel::Cmd::kRun); } else { LOG(ERROR) << actor_ctx->GetActor()->GetActorName() << " has no msg"; } @@ -602,15 +602,15 @@ void App::ProcessTimerEvent(std::shared_ptr worker_ctx) { DLOG(INFO) << *worker_ctx << " dispatch msg..."; DispatchMsg(worker_ctx->GetMailbox()->GetSendList()); - Cmd cmd; + CmdChannel::Cmd cmd; auto cmd_channel = worker_ctx->GetCmdChannel(); cmd_channel->RecvFromOwner(&cmd); switch (cmd) { - case Cmd::kIdle: // idle + case CmdChannel::Cmd::kIdle: // idle DLOG(INFO) << *worker_ctx << " run again"; - cmd_channel->SendToOwner(Cmd::kRun); + cmd_channel->SendToOwner(CmdChannel::Cmd::kRun); break; - case Cmd::kQuit: // quit + case CmdChannel::Cmd::kQuit: // quit LOG(INFO) << *worker_ctx << " quit, delete from main"; DelEvent(worker_ctx); @@ -627,19 +627,19 @@ void App::ProcessUserEvent(std::shared_ptr worker_ctx) { DLOG(INFO) << *worker_ctx << " dispatch msg..."; DispatchMsg(worker_ctx->GetMailbox()->GetSendList()); - Cmd cmd; + CmdChannel::Cmd cmd; auto cmd_channel = worker_ctx->GetCmdChannel(); cmd_channel->RecvFromOwner(&cmd); switch (cmd) { - case Cmd::kIdle: // idle + case CmdChannel::Cmd::kIdle: // idle DLOG(INFO) << *worker_ctx << " run again"; - cmd_channel->SendToOwner(Cmd::kRun); + cmd_channel->SendToOwner(CmdChannel::Cmd::kRun); break; - case Cmd::kWaitForMsg: + case CmdChannel::Cmd::kWaitForMsg: DLOG(INFO) << *worker_ctx << " wait for msg..."; worker_ctx_mgr_->PushWaitWorker(worker_ctx); break; - case Cmd::kQuit: // quit + case CmdChannel::Cmd::kQuit: // quit LOG(INFO) << *worker_ctx << " quit, delete from main"; DelEvent(worker_ctx); worker_ctx_mgr_->Del(worker_ctx); @@ -661,11 +661,11 @@ void App::ProcessWorkerEvent(std::shared_ptr worker_ctx) { << *worker_ctx << " no context"; DispatchMsg(worker->GetActorContext()); - Cmd cmd; + CmdChannel::Cmd cmd; auto cmd_channel = worker->GetCmdChannel(); cmd_channel->RecvFromOwner(&cmd); switch (cmd) { - case Cmd::kIdle: // idle + case CmdChannel::Cmd::kIdle: // idle // 将工作线程中的actor状态设置为全局状态 // 将线程加入空闲队列 DLOG(INFO) @@ -674,7 +674,7 @@ void App::ProcessWorkerEvent(std::shared_ptr worker_ctx) { worker->Idle(); worker_ctx_mgr_->PushBackIdleWorker(worker_ctx); break; - case Cmd::kQuit: // quit + case CmdChannel::Cmd::kQuit: // quit LOG(INFO) << *worker_ctx << " quit, delete from main"; @@ -693,13 +693,13 @@ void App::ProcessEventConn(std::shared_ptr ev) { // 将event_conn的发送队列分发完毕 DispatchMsg(ev->GetMailbox()->GetSendList()); auto cmd_channel = ev->GetCmdChannel(); - Cmd cmd; + CmdChannel::Cmd cmd; cmd_channel->RecvFromOwner(&cmd); switch (cmd) { - case Cmd::kRun: - cmd_channel->SendToOwner(Cmd::kIdle); + case CmdChannel::Cmd::kRun: + cmd_channel->SendToOwner(CmdChannel::Cmd::kIdle); break; - case Cmd::kRunWithMsg: + case CmdChannel::Cmd::kRunWithMsg: // do nothing break; default: @@ -722,16 +722,16 @@ void App::ProcessEvent(struct epoll_event* evs, int ev_count) { } ev_obj->RetListenIOType(ToEventIOType(evs[i].events)); switch (ev_obj->GetType()) { - case EventType::kWorkerCommon: + case Event::Type::kWorkerCommon: ProcessWorkerEvent(std::dynamic_pointer_cast(ev_obj)); break; - case EventType::kWorkerTimer: + case Event::Type::kWorkerTimer: ProcessTimerEvent(std::dynamic_pointer_cast(ev_obj)); break; - case EventType::kWorkerUser: + case Event::Type::kWorkerUser: ProcessUserEvent(std::dynamic_pointer_cast(ev_obj)); break; - case EventType::kEventConn: + case Event::Type::kEventConn: ProcessEventConn(std::dynamic_pointer_cast(ev_obj)); break; default: diff --git a/myframe/app.h b/myframe/app.h index b2afec3..06ea7a9 100644 --- a/myframe/app.h +++ b/myframe/app.h @@ -119,8 +119,8 @@ class App final : public std::enable_shared_from_this { void CheckStopWorkers(); /// 分发事件 - EventIOType ToEventIOType(int ev); - int ToEpollType(const EventIOType& type); + Event::IOType ToEventIOType(int ev); + int ToEpollType(const Event::IOType& type); void DispatchMsg(std::list>* msg_list); void DispatchMsg(std::shared_ptr context); void ProcessEvent(struct epoll_event* evs, int ev_count); diff --git a/myframe/cmd_channel.cpp b/myframe/cmd_channel.cpp index c25d854..a74de0f 100644 --- a/myframe/cmd_channel.cpp +++ b/myframe/cmd_channel.cpp @@ -23,11 +23,11 @@ CmdChannel::~CmdChannel() { CloseSockpair(); } -int CmdChannel::GetOwnerFd() const { +ev_handle_t CmdChannel::GetOwnerHandle() const { return sockpair_[0]; } -int CmdChannel::GetMainFd() const { +ev_handle_t CmdChannel::GetMainHandle() const { return sockpair_[1]; } diff --git a/myframe/cmd_channel.h b/myframe/cmd_channel.h index 4d177fb..bd2e6aa 100644 --- a/myframe/cmd_channel.h +++ b/myframe/cmd_channel.h @@ -6,24 +6,25 @@ Author: likepeng ****************************************************************************/ #pragma once #include "myframe/macros.h" +#include "myframe/event.h" namespace myframe { -enum class Cmd : char { - kQuit = 'q', ///< 退出 - kIdle = 'i', ///< 空闲 - kWaitForMsg = 'w', ///< 等待消息 - kRun = 'r', ///< 运行 - kRunWithMsg = 'm', ///< 运行 -}; - class CmdChannel final { public: + enum class Cmd : char { + kQuit = 'q', ///< 退出 + kIdle = 'i', ///< 空闲 + kWaitForMsg = 'w', ///< 等待消息 + kRun = 'r', ///< 运行 + kRunWithMsg = 'm', ///< 运行(有消息) + }; + CmdChannel(); virtual ~CmdChannel(); - int GetOwnerFd() const; - int GetMainFd() const; + ev_handle_t GetOwnerHandle() const; + ev_handle_t GetMainHandle() const; int SendToOwner(const Cmd& cmd); int RecvFromOwner(Cmd* cmd); @@ -34,7 +35,7 @@ class CmdChannel final { private: void CreateSockpair(); void CloseSockpair(); - int sockpair_[2] {-1, -1}; + ev_handle_t sockpair_[2] {-1, -1}; DISALLOW_COPY_AND_ASSIGN(CmdChannel) }; diff --git a/myframe/event.h b/myframe/event.h index c3ede65..a2b0efa 100644 --- a/myframe/event.h +++ b/myframe/event.h @@ -9,35 +9,37 @@ Author: likepeng namespace myframe { -enum class EventIOType : int { - kNone, - kIn, - kOut, -}; - -enum class EventType : int { - kWorkerCommon, - kWorkerTimer, - kWorkerUser, - kEventConn, -}; +typedef int ev_handle_t; class Event : public std::enable_shared_from_this { public: + enum class IOType : int { + kNone, + kIn, + kOut, + }; + + enum class Type : int { + kWorkerCommon, + kWorkerTimer, + kWorkerUser, + kEventConn, + }; + Event() = default; virtual ~Event() {} /* 事件类型 */ - virtual EventType GetType() { return EventType::kWorkerUser; } + virtual Type GetType() { return Type::kWorkerUser; } /* 获得当前事件的文件描述符 */ - virtual int GetFd() const = 0; + virtual ev_handle_t GetHandle() const = 0; /* 监听的是文件描述符的写事件还是读事件 */ - virtual EventIOType ListenIOType() { return EventIOType::kIn; } + virtual IOType ListenIOType() { return IOType::kIn; } /* 返回的监听事件类型 */ - virtual void RetListenIOType(const EventIOType&) {} + virtual void RetListenIOType(const IOType&) {} }; } // namespace myframe diff --git a/myframe/event_conn.cpp b/myframe/event_conn.cpp index a162e97..0bae2a4 100644 --- a/myframe/event_conn.cpp +++ b/myframe/event_conn.cpp @@ -13,9 +13,11 @@ Author: likepeng namespace myframe { -int EventConn::GetFd() const { return cmd_channel_.GetMainFd(); } +ev_handle_t EventConn::GetHandle() const { + return cmd_channel_.GetMainHandle(); +} -EventType EventConn::GetType() { return EventType::kEventConn; } +Event::Type EventConn::GetType() { return Event::Type::kEventConn; } Mailbox* EventConn::GetMailbox() { return &mailbox_; @@ -28,22 +30,22 @@ CmdChannel* EventConn::GetCmdChannel() { int EventConn::Send( const std::string& dst, std::shared_ptr msg) { - conn_type_ = EventConnType::kSend; + conn_type_ = EventConn::Type::kSend; mailbox_.SendClear(); mailbox_.Send(dst, msg); - cmd_channel_.SendToMain(Cmd::kRun); - Cmd cmd; + cmd_channel_.SendToMain(CmdChannel::Cmd::kRun); + CmdChannel::Cmd cmd; return cmd_channel_.RecvFromMain(&cmd); } const std::shared_ptr EventConn::SendRequest( const std::string& dst, std::shared_ptr req) { - conn_type_ = EventConnType::kSendReq; + conn_type_ = EventConn::Type::kSendReq; mailbox_.SendClear(); mailbox_.Send(dst, req); - cmd_channel_.SendToMain(Cmd::kRunWithMsg); - Cmd cmd; + cmd_channel_.SendToMain(CmdChannel::Cmd::kRunWithMsg); + CmdChannel::Cmd cmd; cmd_channel_.RecvFromMain(&cmd); if (mailbox_.RecvEmpty()) { return nullptr; diff --git a/myframe/event_conn.h b/myframe/event_conn.h index 4f2040f..cd3553e 100644 --- a/myframe/event_conn.h +++ b/myframe/event_conn.h @@ -15,11 +15,6 @@ Author: likepeng namespace myframe { -enum class EventConnType : char { - kSendReq, - kSend, -}; - class Msg; class EventConnManager; class EventConn final : public Event { @@ -27,12 +22,17 @@ class EventConn final : public Event { friend class EventConnManager; public: + enum class Type : char { + kSendReq, + kSend, + }; + EventConn() = default; - int GetFd() const override; - EventType GetType() override; + ev_handle_t GetHandle() const override; + Event::Type GetType() override; - EventConnType GetConnType() { return conn_type_; } + EventConn::Type GetConnType() { return conn_type_; } int Send( const std::string& dst, @@ -48,7 +48,7 @@ class EventConn final : public Event { CmdChannel cmd_channel_; Mailbox mailbox_; - EventConnType conn_type_{ EventConnType::kSendReq }; + EventConn::Type conn_type_{ EventConn::Type::kSendReq }; DISALLOW_COPY_AND_ASSIGN(EventConn) }; diff --git a/myframe/event_conn_manager.cpp b/myframe/event_conn_manager.cpp index 145103c..dde4f8d 100644 --- a/myframe/event_conn_manager.cpp +++ b/myframe/event_conn_manager.cpp @@ -80,7 +80,7 @@ std::shared_ptr EventConnManager::Get() { // add to run_conn const auto& addr = conn->GetMailbox()->Addr(); run_conn_[addr] = conn; - run_conn_map_[conn->GetFd()] = addr; + run_conn_map_[conn->GetHandle()] = addr; // add to epoll app->AddEvent(conn); return conn; @@ -98,7 +98,7 @@ void EventConnManager::Release(std::shared_ptr ev) { // remove from run_conn const auto& name = ev->GetMailbox()->Addr(); run_conn_.erase(name); - run_conn_map_.erase(ev->GetFd()); + run_conn_map_.erase(ev->GetHandle()); // add to idle_conn idle_conn_.emplace_back(ev); } @@ -116,14 +116,14 @@ void EventConnManager::Notify( } ev = run_conn_[name]; } - if (ev->GetConnType() == EventConnType::kSend) { + if (ev->GetConnType() == EventConn::Type::kSend) { return; } // push msg to event_conn ev->GetMailbox()->Recv(msg); // send cmd to event_conn auto cmd_channel = ev->GetCmdChannel(); - cmd_channel->SendToOwner(Cmd::kIdle); + cmd_channel->SendToOwner(CmdChannel::Cmd::kIdle); } } // namespace myframe diff --git a/myframe/worker.cpp b/myframe/worker.cpp index a7eaccb..b335f90 100644 --- a/myframe/worker.cpp +++ b/myframe/worker.cpp @@ -42,10 +42,10 @@ int Worker::DispatchMsg() { if (channel == nullptr) { return -1; } - Cmd cmd = Cmd::kIdle; + CmdChannel::Cmd cmd = CmdChannel::Cmd::kIdle; channel->SendToMain(cmd); auto ret = channel->RecvFromMain(&cmd); - if (cmd == Cmd::kQuit) { + if (cmd == CmdChannel::Cmd::kQuit) { LOG(INFO) << GetWorkerName() << " recv stop msg, stoping..."; Stop(); return -1; @@ -58,10 +58,10 @@ int Worker::DispatchAndWaitMsg() { if (channel == nullptr) { return -1; } - Cmd cmd = Cmd::kWaitForMsg; + CmdChannel::Cmd cmd = CmdChannel::Cmd::kWaitForMsg; channel->SendToMain(cmd); auto ret = channel->RecvFromMain(&cmd); - if (cmd == Cmd::kQuit) { + if (cmd == CmdChannel::Cmd::kQuit) { LOG(INFO) << GetWorkerName() << " recv stop msg, stoping..."; Stop(); return -1; @@ -97,8 +97,8 @@ void Worker::SetContext(std::shared_ptr ctx) { ctx_ = ctx; } -EventType Worker::GetType() { - return EventType::kWorkerUser; +Event::Type Worker::GetType() { + return Event::Type::kWorkerUser; } std::shared_ptr Worker::GetApp() { diff --git a/myframe/worker.h b/myframe/worker.h index ea5e4b3..b0e22cb 100644 --- a/myframe/worker.h +++ b/myframe/worker.h @@ -34,7 +34,7 @@ class Worker { * * @return: 事件类型 */ - virtual EventType GetType(); + virtual Event::Type GetType(); /** * GetConfig() - 获得配置参数 diff --git a/myframe/worker_common.h b/myframe/worker_common.h index 288dad3..e0a9af1 100644 --- a/myframe/worker_common.h +++ b/myframe/worker_common.h @@ -26,8 +26,8 @@ class WorkerCommon final : public Worker { void Init() override; void Exit() override; - EventType GetType() override { - return EventType::kWorkerCommon; + Event::Type GetType() override { + return Event::Type::kWorkerCommon; } void SetActorContext(std::shared_ptr context) { diff --git a/myframe/worker_context.cpp b/myframe/worker_context.cpp index f4ce6fe..f4fe925 100644 --- a/myframe/worker_context.cpp +++ b/myframe/worker_context.cpp @@ -29,11 +29,11 @@ WorkerContext::~WorkerContext() { LOG(INFO) << worker_->GetWorkerName() << " deconstruct"; } -int WorkerContext::GetFd() const { - return cmd_channel_.GetMainFd(); +ev_handle_t WorkerContext::GetHandle() const { + return cmd_channel_.GetMainHandle(); } -EventType WorkerContext::GetType() { +Event::Type WorkerContext::GetType() { return worker_->GetType(); } @@ -68,7 +68,7 @@ void WorkerContext::ListenThread() { worker_->Run(); } worker_->Exit(); - cmd_channel_.SendToMain(Cmd::kQuit); + cmd_channel_.SendToMain(CmdChannel::Cmd::kQuit); } std::size_t WorkerContext::CacheSize() const { @@ -101,7 +101,7 @@ std::shared_ptr WorkerContext::GetApp() { std::ostream& operator<<(std::ostream& out, WorkerContext& ctx) { auto w = ctx.GetWorker(); - out << w->GetWorkerName() << "." << ctx.GetPosixThreadId(); + out << w->GetWorkerName() << "." << ctx.GetThreadId(); return out; } diff --git a/myframe/worker_context.h b/myframe/worker_context.h index 8790abd..4657a14 100644 --- a/myframe/worker_context.h +++ b/myframe/worker_context.h @@ -21,15 +21,15 @@ Author: likepeng namespace myframe { -enum class WorkerCtrlOwner : int { - kMain, - kWorker, -}; - class App; class Worker; class WorkerContext final : public Event { public: + enum class CtrlOwner : int { + kMain, + kWorker, + }; + WorkerContext(std::shared_ptr app, std::shared_ptr worker); virtual ~WorkerContext(); @@ -38,11 +38,11 @@ class WorkerContext final : public Event { void Stop(); void Join(); bool IsRuning() { return runing_.load(); } - pthread_t GetPosixThreadId() { return th_.native_handle(); } + std::thread::id GetThreadId() { return th_.get_id(); } /// event 相关函数 - int GetFd() const override; - EventType GetType() override; + ev_handle_t GetHandle() const override; + Event::Type GetType() override; Mailbox* GetMailbox(); @@ -60,10 +60,10 @@ class WorkerContext final : public Event { void Cache(std::list>* msg_list); /// 线程交互控制flag函数 - void SetCtrlOwnerFlag(WorkerCtrlOwner owner) { + void SetCtrlOwnerFlag(CtrlOwner owner) { ctrl_owner_ = owner; } - WorkerCtrlOwner GetOwner() const { + CtrlOwner GetOwner() const { return ctrl_owner_; } void SetWaitMsgQueueFlag(bool in_wait_msg_queue) { @@ -81,7 +81,7 @@ class WorkerContext final : public Event { /// state flag std::atomic_bool runing_; - WorkerCtrlOwner ctrl_owner_{ WorkerCtrlOwner::kWorker }; + CtrlOwner ctrl_owner_{ CtrlOwner::kWorker }; bool in_msg_wait_queue_{ false }; /// worker diff --git a/myframe/worker_context_manager.cpp b/myframe/worker_context_manager.cpp index c7e6b7d..43473f4 100644 --- a/myframe/worker_context_manager.cpp +++ b/myframe/worker_context_manager.cpp @@ -55,7 +55,7 @@ std::shared_ptr WorkerContextManager::Get( bool WorkerContextManager::Add(std::shared_ptr worker_ctx) { auto worker = worker_ctx->GetWorker(); - int handle = worker_ctx->GetFd(); + ev_handle_t handle = worker_ctx->GetHandle(); std::unique_lock lk(rw_); if (worker_ctxs_.find(handle) != worker_ctxs_.end()) { LOG(ERROR) << *worker_ctx << " reg handle " << handle @@ -70,7 +70,7 @@ bool WorkerContextManager::Add(std::shared_ptr worker_ctx) { void WorkerContextManager::Del(std::shared_ptr worker_ctx) { auto worker = worker_ctx->GetWorker(); - int handle = worker_ctx->GetFd(); + ev_handle_t handle = worker_ctx->GetHandle(); std::unique_lock lk(rw_); if (worker_ctxs_.find(handle) == worker_ctxs_.end()) { return; @@ -123,7 +123,7 @@ std::vector WorkerContextManager::GetAllUserWorkerAddr() { std::vector res; std::shared_lock lk(rw_); for (auto p : worker_ctxs_) { - if (p.second->GetType() == EventType::kWorkerUser + if (p.second->GetType() == Event::Type::kWorkerUser && p.second->GetWorker()->GetTypeName() != "node") { res.push_back(p.second->GetWorker()->GetWorkerName()); } @@ -137,7 +137,7 @@ void WorkerContextManager::StopAllWorker() { // 目前仅支持使用channel通信的worker停止退出 // 不使用的可以调用Stop函数退出(目前暂无需求) // p.second->Stop(); - p.second->GetCmdChannel()->SendToOwner(Cmd::kQuit); + p.second->GetCmdChannel()->SendToOwner(CmdChannel::Cmd::kQuit); } } @@ -152,7 +152,7 @@ void WorkerContextManager::WaitAllWorkerQuit() { void WorkerContextManager::PushWaitWorker( std::shared_ptr worker) { - worker->SetCtrlOwnerFlag(WorkerCtrlOwner::kMain); + worker->SetCtrlOwnerFlag(WorkerContext::CtrlOwner::kMain); } void WorkerContextManager::WeakupWorker() { @@ -164,16 +164,16 @@ void WorkerContextManager::WeakupWorker() { it = weakup_workers_ctx_.erase(it); continue; } - if (worker_ctx->GetOwner() == WorkerCtrlOwner::kWorker) { + if (worker_ctx->GetOwner() == WorkerContext::CtrlOwner::kWorker) { ++it; continue; } worker_ctx->GetMailbox()->Recv(worker_ctx->GetCache()); it = weakup_workers_ctx_.erase(it); - worker_ctx->SetCtrlOwnerFlag(WorkerCtrlOwner::kWorker); + worker_ctx->SetCtrlOwnerFlag(WorkerContext::CtrlOwner::kWorker); worker_ctx->SetWaitMsgQueueFlag(false); DLOG(INFO) << "notify " << *worker_ctx << " process msg"; - worker_ctx->GetCmdChannel()->SendToOwner(Cmd::kRunWithMsg); + worker_ctx->GetCmdChannel()->SendToOwner(CmdChannel::Cmd::kRunWithMsg); } } @@ -187,8 +187,8 @@ void WorkerContextManager::DispatchWorkerMsg(std::shared_ptr msg) { auto worker_ctx = Get(worker_name); auto worker = worker_ctx->GetWorker(); auto worker_type = worker->GetType(); - if (worker_type == EventType::kWorkerTimer || - worker_type == EventType::kWorkerCommon) { + if (worker_type == Event::Type::kWorkerTimer || + worker_type == Event::Type::kWorkerCommon) { LOG(WARNING) << worker_name << " unsupport recv msg, drop it"; return; } diff --git a/myframe/worker_timer.h b/myframe/worker_timer.h index 739d54c..b3a91e8 100644 --- a/myframe/worker_timer.h +++ b/myframe/worker_timer.h @@ -88,8 +88,8 @@ class WorkerTimer final : public Worker { void Init() override; void Run() override; void Exit() override; - EventType GetType() override { - return EventType::kWorkerTimer; + Event::Type GetType() override { + return Event::Type::kWorkerTimer; } private: From 68025d6cba6448b6ba96441fd9bc32f2744c1dbb Mon Sep 17 00:00:00 2001 From: likepeng01 Date: Fri, 21 Jul 2023 16:53:57 +0800 Subject: [PATCH 13/17] abstract epoll --- myframe/CMakeLists.txt | 1 + myframe/app.cpp | 112 +++++---------------------------- myframe/app.h | 15 ++--- myframe/event_conn_manager.cpp | 7 ++- myframe/poller.cpp | 101 +++++++++++++++++++++++++++++ myframe/poller.h | 39 ++++++++++++ 6 files changed, 167 insertions(+), 108 deletions(-) create mode 100644 myframe/poller.cpp create mode 100644 myframe/poller.h diff --git a/myframe/CMakeLists.txt b/myframe/CMakeLists.txt index 47b12e9..aecfc05 100644 --- a/myframe/CMakeLists.txt +++ b/myframe/CMakeLists.txt @@ -17,6 +17,7 @@ file(GLOB header_files actor.h event.h worker.h + mod_manager.h app.h ) install(FILES diff --git a/myframe/app.cpp b/myframe/app.cpp index d4aa81b..fc0b587 100644 --- a/myframe/app.cpp +++ b/myframe/app.cpp @@ -7,12 +7,6 @@ Author: likepeng #include "myframe/app.h" -#include -#include -#include - -#include - #include #include "myframe/common.h" @@ -28,6 +22,7 @@ Author: likepeng #include "myframe/worker_timer.h" #include "myframe/worker_context_manager.h" #include "myframe/mod_manager.h" +#include "myframe/poller.h" namespace myframe { @@ -48,7 +43,7 @@ std::shared_ptr App::GetTimerWorker() { } App::App() - : epoll_fd_(-1) + : poller_(new Poller()) , mods_(new ModManager()) , actor_ctx_mgr_(new ActorContextManager()) , ev_conn_mgr_(new EventConnManager()) @@ -56,10 +51,6 @@ App::App() {} App::~App() { - if (epoll_fd_ != -1) { - close(epoll_fd_); - epoll_fd_ = -1; - } LOG(INFO) << "app deconstruct"; } @@ -71,16 +62,11 @@ bool App::Init( if (!quit_.load()) { return true; } - epoll_fd_ = epoll_create(1024); - if (-1 == epoll_fd_) { - LOG(ERROR) << strerror(errno); - return false; - } - LOG(INFO) << "Create epoll fd " << epoll_fd_; bool ret = true; lib_dir_ = lib_dir; warning_msg_size_.store(warning_msg_size); + ret &= poller_->Init(); ret &= worker_ctx_mgr_->Init(warning_msg_size); ret &= ev_conn_mgr_->Init(shared_from_this(), event_conn_size); ret &= StartCommonWorker(thread_pool_size); @@ -302,7 +288,7 @@ bool App::AddWorker( if (!worker_ctx_mgr_->Add(worker_ctx)) { return false; } - if (!AddEvent(worker_ctx)) { + if (!poller_->Add(worker_ctx)) { return false; } worker_ctx->Start(); @@ -365,37 +351,6 @@ bool App::CreateActorContext( return true; } -bool App::AddEvent(std::shared_ptr ev) { - struct epoll_event event; - event.data.fd = ev->GetHandle(); - event.events = ToEpollType(ev->ListenIOType()); - int res = 0; - // 如果该事件已经注册,就修改事件类型 - res = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, ev->GetHandle(), &event); - if (-1 == res) { - // 没有注册就添加至epoll - res = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, ev->GetHandle(), &event); - if (-1 == res) { - LOG(ERROR) << "epoll " << strerror(errno); - return false; - } - } else { - LOG(WARNING) - << " has already reg ev " << ev->GetHandle() << ": " - << strerror(errno); - return false; - } - return true; -} - -bool App::DelEvent(std::shared_ptr ev) { - if (-1 == epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, ev->GetHandle(), NULL)) { - LOG(ERROR) << "del event " << ev->GetHandle() << ": " << strerror(errno); - return false; - } - return true; -} - bool App::StartCommonWorker(int worker_count) { bool ret = false; for (int i = 0; i < worker_count; ++i) { @@ -424,28 +379,6 @@ bool App::StartTimerWorker() { return true; } -Event::IOType App::ToEventIOType(int ev) { - switch (ev) { - case EPOLLIN: - return Event::IOType::kIn; - case EPOLLOUT: - return Event::IOType::kOut; - default: - return Event::IOType::kNone; - } -} - -int App::ToEpollType(const Event::IOType& type) { - switch (type) { - case Event::IOType::kIn: - return EPOLLIN; - case Event::IOType::kOut: - return EPOLLOUT; - default: - return EPOLLERR; - } -} - void App::DispatchMsg(std::list>* msg_list) { LOG_IF(WARNING, msg_list->size() > warning_msg_size_.load()) @@ -613,7 +546,7 @@ void App::ProcessTimerEvent(std::shared_ptr worker_ctx) { case CmdChannel::Cmd::kQuit: // quit LOG(INFO) << *worker_ctx << " quit, delete from main"; - DelEvent(worker_ctx); + poller_->Del(worker_ctx); worker_ctx_mgr_->Del(worker_ctx); break; default: @@ -641,7 +574,7 @@ void App::ProcessUserEvent(std::shared_ptr worker_ctx) { break; case CmdChannel::Cmd::kQuit: // quit LOG(INFO) << *worker_ctx << " quit, delete from main"; - DelEvent(worker_ctx); + poller_->Del(worker_ctx); worker_ctx_mgr_->Del(worker_ctx); break; default: @@ -678,7 +611,7 @@ void App::ProcessWorkerEvent(std::shared_ptr worker_ctx) { LOG(INFO) << *worker_ctx << " quit, delete from main"; - DelEvent(worker_ctx); + poller_->Del(worker_ctx); worker_ctx_mgr_->Del(worker_ctx); // FIXME: 应该将worker加入删除队列,等worker运行结束后再从队列删除 // 否则会造成删除智能指针后,worker还没结束运行造成coredump @@ -708,19 +641,19 @@ void App::ProcessEventConn(std::shared_ptr ev) { } } -void App::ProcessEvent(struct epoll_event* evs, int ev_count) { - DLOG_IF(INFO, ev_count > 0) << "get " << ev_count << " event"; - for (int i = 0; i < ev_count; ++i) { +void App::ProcessEvent(const std::vector& evs) { + DLOG_IF(INFO, evs.size() > 0) << "get " << evs.size() << " event"; + for (size_t i = 0; i < evs.size(); ++i) { std::shared_ptr ev_obj = nullptr; - ev_obj = worker_ctx_mgr_->Get(evs[i].data.fd); + ev_obj = worker_ctx_mgr_->Get(evs[i]); if (ev_obj == nullptr) { - ev_obj = ev_conn_mgr_->Get(evs[i].data.fd); + ev_obj = ev_conn_mgr_->Get(evs[i]); if (ev_obj == nullptr) { - LOG(ERROR) << "can't find ev obj, handle " << evs[i].data.fd; + LOG(ERROR) << "can't find ev obj, handle " << evs[i]; continue; } } - ev_obj->RetListenIOType(ToEventIOType(evs[i].events)); + ev_obj->RetListenIOType(Event::IOType::kIn); switch (ev_obj->GetType()) { case Event::Type::kWorkerCommon: ProcessWorkerEvent(std::dynamic_pointer_cast(ev_obj)); @@ -742,31 +675,20 @@ void App::ProcessEvent(struct epoll_event* evs, int ev_count) { } int App::Exec() { - int ev_count = 0; - int max_ev_count = 64; int time_wait_ms = 1000; - struct epoll_event* evs = nullptr; - auto void_evs = malloc(sizeof(struct epoll_event) * max_ev_count); - evs = reinterpret_cast(void_evs); + std::vector evs; while (worker_ctx_mgr_->WorkerSize()) { /// 检查空闲线程队列是否有空闲线程,如果有就找到一个有消息的actor处理 CheckStopWorkers(); /// 等待事件 - ev_count = epoll_wait(epoll_fd_, evs, max_ev_count, time_wait_ms); - if (0 > ev_count) { - LOG(ERROR) << "epoll wait error: " << strerror(errno); - continue; - } + poller_->Wait(&evs, time_wait_ms); /// 处理事件 - ProcessEvent(evs, ev_count); + ProcessEvent(evs); } // quit App worker_ctx_mgr_->WaitAllWorkerQuit(); - free(evs); - close(epoll_fd_); - epoll_fd_ = -1; quit_.store(true); LOG(INFO) << "app exit exec"; return 0; diff --git a/myframe/app.h b/myframe/app.h index 06ea7a9..27e1799 100644 --- a/myframe/app.h +++ b/myframe/app.h @@ -18,11 +18,10 @@ Author: likepeng #include "myframe/macros.h" #include "myframe/event.h" -struct epoll_event; - namespace myframe { class Msg; +class Poller; class Actor; class ActorContext; class ActorContextManager; @@ -38,6 +37,7 @@ class ModManager; class App final : public std::enable_shared_from_this { friend class Actor; friend class ActorContext; + friend class EventConnManager; public: App(); @@ -82,9 +82,6 @@ class App final : public std::enable_shared_from_this { std::unique_ptr& GetModManager() { return mods_; } - bool AddEvent(std::shared_ptr ev); - bool DelEvent(std::shared_ptr ev); - int Exec(); void Quit(); @@ -119,11 +116,9 @@ class App final : public std::enable_shared_from_this { void CheckStopWorkers(); /// 分发事件 - Event::IOType ToEventIOType(int ev); - int ToEpollType(const Event::IOType& type); void DispatchMsg(std::list>* msg_list); void DispatchMsg(std::shared_ptr context); - void ProcessEvent(struct epoll_event* evs, int ev_count); + void ProcessEvent(const std::vector& evs); void ProcessWorkerEvent(std::shared_ptr); void ProcessTimerEvent(std::shared_ptr); void ProcessUserEvent(std::shared_ptr); @@ -138,8 +133,8 @@ class App final : public std::enable_shared_from_this { std::atomic_bool quit_{true}; std::mutex dispatch_mtx_; std::mutex local_mtx_; - /// epoll文件描述符 - int epoll_fd_; + /// poller + std::unique_ptr poller_; /// 模块管理对象 std::unique_ptr mods_; /// 句柄管理对象 diff --git a/myframe/event_conn_manager.cpp b/myframe/event_conn_manager.cpp index dde4f8d..c5d1ac6 100644 --- a/myframe/event_conn_manager.cpp +++ b/myframe/event_conn_manager.cpp @@ -10,6 +10,7 @@ Author: likepeng #include #include "myframe/app.h" +#include "myframe/poller.h" #include "myframe/event_conn.h" namespace myframe { @@ -24,7 +25,7 @@ EventConnManager::~EventConnManager() { auto app = app_.lock(); if (app != nullptr) { for (auto p : run_conn_) { - app->DelEvent(p.second); + app->poller_->Del(p.second); } } run_conn_.clear(); @@ -82,7 +83,7 @@ std::shared_ptr EventConnManager::Get() { run_conn_[addr] = conn; run_conn_map_[conn->GetHandle()] = addr; // add to epoll - app->AddEvent(conn); + app->poller_->Add(conn); return conn; } @@ -94,7 +95,7 @@ void EventConnManager::Release(std::shared_ptr ev) { return; } // delete from epoll - app->DelEvent(ev); + app->poller_->Del(ev); // remove from run_conn const auto& name = ev->GetMailbox()->Addr(); run_conn_.erase(name); diff --git a/myframe/poller.cpp b/myframe/poller.cpp new file mode 100644 index 0000000..bdf555e --- /dev/null +++ b/myframe/poller.cpp @@ -0,0 +1,101 @@ +/**************************************************************************** +Copyright (c) 2018, likepeng +All rights reserved. + +Author: likepeng +****************************************************************************/ + +#include "myframe/poller.h" + +#include +#include + +#include + +namespace myframe { + +Poller::~Poller() { + if (poll_fd_ != -1) { + close(poll_fd_); + poll_fd_ = -1; + } + if (evs_ != nullptr) { + free(evs_); + evs_ = nullptr; + } + init_.store(false); +} + +bool Poller::Init() { + if (init_.load()) { + return true; + } + poll_fd_ = epoll_create(1024); + if (-1 == poll_fd_) { + LOG(ERROR) << "poller create() failed, " << strerror(errno); + return false; + } + LOG(INFO) << "Create epoll fd " << poll_fd_; + auto void_evs = malloc(sizeof(struct epoll_event) * max_ev_count_); + evs_ = reinterpret_cast(void_evs); + init_.store(true); + return true; +} + +bool Poller::Add(const std::shared_ptr& ev) const { + if (!init_.load()) { + return false; + } + struct epoll_event event; + event.data.fd = ev->GetHandle(); + event.events = EPOLLIN; + int res = 0; + // 如果该事件已经注册,就修改事件类型 + res = epoll_ctl(poll_fd_, EPOLL_CTL_MOD, ev->GetHandle(), &event); + if (-1 == res) { + // 没有注册就添加至epoll + res = epoll_ctl(poll_fd_, EPOLL_CTL_ADD, ev->GetHandle(), &event); + if (-1 == res) { + LOG(ERROR) << "epoll_ctl error, " << strerror(errno); + return false; + } + } else { + LOG(WARNING) + << " has already reg ev " << ev->GetHandle() << ": " + << strerror(errno); + return false; + } + return true; +} + +bool Poller::Del(const std::shared_ptr& ev) const { + if (!init_.load()) { + return false; + } + if (-1 == epoll_ctl(poll_fd_, EPOLL_CTL_DEL, ev->GetHandle(), NULL)) { + LOG(ERROR) << "del event " << ev->GetHandle() << ": " << strerror(errno); + return false; + } + return true; +} + +int Poller::Wait(std::vector* evs, int timeout_ms) { + if (!init_.load()) { + return -1; + } + evs->clear(); + int ev_count = epoll_wait(poll_fd_, + evs_, + static_cast(max_ev_count_), + timeout_ms); + if (0 > ev_count) { + LOG(ERROR) << "epoll wait error: " << strerror(errno); + return -1; + } + for (int i = 0; i < ev_count; ++i) { + evs->push_back(evs_[i].data.fd); + } + return ev_count; +} + +} // namespace myframe diff --git a/myframe/poller.h b/myframe/poller.h new file mode 100644 index 0000000..d16dca6 --- /dev/null +++ b/myframe/poller.h @@ -0,0 +1,39 @@ +/**************************************************************************** +Copyright (c) 2018, likepeng +All rights reserved. + +Author: likepeng +****************************************************************************/ + +#pragma once +#include +#include +#include + +#include "myframe/macros.h" +#include "myframe/event.h" + +struct epoll_event; + +namespace myframe { + +class Poller final { + public: + explicit Poller() = default; + ~Poller(); + + bool Init(); + bool Add(const std::shared_ptr&) const; + bool Del(const std::shared_ptr&) const; + int Wait(std::vector* evs, int timeout_ms = 100); + + private: + std::atomic_bool init_{false}; + int poll_fd_{-1}; + size_t max_ev_count_{64}; + struct epoll_event* evs_{nullptr}; + + DISALLOW_COPY_AND_ASSIGN(Poller) +}; + +} // namespace myframe From bd77c94b5a2502ac95a5dfc893f31496d6f321d1 Mon Sep 17 00:00:00 2001 From: likepeng01 Date: Fri, 21 Jul 2023 17:22:54 +0800 Subject: [PATCH 14/17] only listen IN ioevent --- myframe/app.cpp | 1 - myframe/event.h | 14 +------------- myframe/poller.cpp | 4 ++++ 3 files changed, 5 insertions(+), 14 deletions(-) diff --git a/myframe/app.cpp b/myframe/app.cpp index fc0b587..7e57f16 100644 --- a/myframe/app.cpp +++ b/myframe/app.cpp @@ -653,7 +653,6 @@ void App::ProcessEvent(const std::vector& evs) { continue; } } - ev_obj->RetListenIOType(Event::IOType::kIn); switch (ev_obj->GetType()) { case Event::Type::kWorkerCommon: ProcessWorkerEvent(std::dynamic_pointer_cast(ev_obj)); diff --git a/myframe/event.h b/myframe/event.h index a2b0efa..2621b2b 100644 --- a/myframe/event.h +++ b/myframe/event.h @@ -13,12 +13,6 @@ typedef int ev_handle_t; class Event : public std::enable_shared_from_this { public: - enum class IOType : int { - kNone, - kIn, - kOut, - }; - enum class Type : int { kWorkerCommon, kWorkerTimer, @@ -32,14 +26,8 @@ class Event : public std::enable_shared_from_this { /* 事件类型 */ virtual Type GetType() { return Type::kWorkerUser; } - /* 获得当前事件的文件描述符 */ + /* 事件句柄 */ virtual ev_handle_t GetHandle() const = 0; - - /* 监听的是文件描述符的写事件还是读事件 */ - virtual IOType ListenIOType() { return IOType::kIn; } - - /* 返回的监听事件类型 */ - virtual void RetListenIOType(const IOType&) {} }; } // namespace myframe diff --git a/myframe/poller.cpp b/myframe/poller.cpp index bdf555e..9145957 100644 --- a/myframe/poller.cpp +++ b/myframe/poller.cpp @@ -93,6 +93,10 @@ int Poller::Wait(std::vector* evs, int timeout_ms) { return -1; } for (int i = 0; i < ev_count; ++i) { + if (evs_[i].events != EPOLLIN) { + LOG(WARNING) << "epoll event " << evs_[i].events << " continue"; + continue; + } evs->push_back(evs_[i].data.fd); } return ev_count; From 59a0557c49a19d06aa362a53bfd0ffbed10588a7 Mon Sep 17 00:00:00 2001 From: likepeng01 Date: Fri, 21 Jul 2023 18:19:03 +0800 Subject: [PATCH 15/17] all use ev_handle_t --- myframe/event_conn_manager.cpp | 2 +- myframe/event_conn_manager.h | 5 +++-- myframe/worker_context_manager.cpp | 6 +++--- myframe/worker_context_manager.h | 7 ++++--- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/myframe/event_conn_manager.cpp b/myframe/event_conn_manager.cpp index c5d1ac6..a75fbfa 100644 --- a/myframe/event_conn_manager.cpp +++ b/myframe/event_conn_manager.cpp @@ -50,7 +50,7 @@ void EventConnManager::AddEventConn() { conn_sz_++; } -std::shared_ptr EventConnManager::Get(int handle) { +std::shared_ptr EventConnManager::Get(ev_handle_t handle) { std::lock_guard g(mtx_); if (run_conn_map_.find(handle) == run_conn_map_.end()) { DLOG(WARNING) << "can't find event conn, handle " << handle; diff --git a/myframe/event_conn_manager.h b/myframe/event_conn_manager.h index 4187bb9..82b395e 100644 --- a/myframe/event_conn_manager.h +++ b/myframe/event_conn_manager.h @@ -12,6 +12,7 @@ Author: likepeng #include #include "myframe/macros.h" +#include "myframe/event.h" namespace myframe { @@ -29,7 +30,7 @@ class EventConnManager final { std::shared_ptr Get(); - std::shared_ptr Get(int handle); + std::shared_ptr Get(ev_handle_t); void Release(std::shared_ptr); @@ -39,7 +40,7 @@ class EventConnManager final { int conn_sz_{0}; std::mutex mtx_; - std::unordered_map run_conn_map_; + std::unordered_map run_conn_map_; std::unordered_map> run_conn_; std::list> idle_conn_; diff --git a/myframe/worker_context_manager.cpp b/myframe/worker_context_manager.cpp index 43473f4..e8f44c1 100644 --- a/myframe/worker_context_manager.cpp +++ b/myframe/worker_context_manager.cpp @@ -31,7 +31,7 @@ bool WorkerContextManager::Init(int warning_msg_size) { int WorkerContextManager::WorkerSize() { return cur_worker_count_.load(); } -std::shared_ptr WorkerContextManager::Get(int handle) { +std::shared_ptr WorkerContextManager::Get(ev_handle_t handle) { std::shared_lock lk(rw_); if (worker_ctxs_.find(handle) == worker_ctxs_.end()) { DLOG(WARNING) << "can't find worker, handle " << handle; @@ -55,7 +55,7 @@ std::shared_ptr WorkerContextManager::Get( bool WorkerContextManager::Add(std::shared_ptr worker_ctx) { auto worker = worker_ctx->GetWorker(); - ev_handle_t handle = worker_ctx->GetHandle(); + auto handle = worker_ctx->GetHandle(); std::unique_lock lk(rw_); if (worker_ctxs_.find(handle) != worker_ctxs_.end()) { LOG(ERROR) << *worker_ctx << " reg handle " << handle @@ -70,7 +70,7 @@ bool WorkerContextManager::Add(std::shared_ptr worker_ctx) { void WorkerContextManager::Del(std::shared_ptr worker_ctx) { auto worker = worker_ctx->GetWorker(); - ev_handle_t handle = worker_ctx->GetHandle(); + auto handle = worker_ctx->GetHandle(); std::unique_lock lk(rw_); if (worker_ctxs_.find(handle) == worker_ctxs_.end()) { return; diff --git a/myframe/worker_context_manager.h b/myframe/worker_context_manager.h index 66361b3..37fbc6a 100644 --- a/myframe/worker_context_manager.h +++ b/myframe/worker_context_manager.h @@ -16,6 +16,7 @@ Author: likepeng #include #include "myframe/macros.h" +#include "myframe/event.h" namespace myframe { @@ -30,7 +31,7 @@ class WorkerContextManager final { int WorkerSize(); - std::shared_ptr Get(int fd); + std::shared_ptr Get(ev_handle_t); std::shared_ptr Get(const std::string&); bool Add(std::shared_ptr worker); void Del(std::shared_ptr worker); @@ -66,9 +67,9 @@ class WorkerContextManager final { /// 停止的线程列表 std::list> stoped_workers_ctx_; /// name/handle 映射表 - std::unordered_map name_handle_map_; + std::unordered_map name_handle_map_; /// handle/worker 映射表 - std::unordered_map> worker_ctxs_; + std::unordered_map> worker_ctxs_; DISALLOW_COPY_AND_ASSIGN(WorkerContextManager) }; From 6ae5996a91780fb4d6159be6ac0213c32ec86590 Mon Sep 17 00:00:00 2001 From: likepeng01 Date: Mon, 24 Jul 2023 01:33:33 +0800 Subject: [PATCH 16/17] All events are managed by the event manager --- myframe/app.cpp | 43 +++++++++------- myframe/app.h | 9 ++-- myframe/event.h | 8 ++- myframe/event_conn.cpp | 8 ++- myframe/event_conn.h | 3 +- myframe/event_conn_manager.cpp | 73 ++++++--------------------- myframe/event_conn_manager.h | 20 +++----- myframe/event_manager.cpp | 80 ++++++++++++++++++++++++++++++ myframe/event_manager.h | 66 ++++++++++++++++++++++++ myframe/mod_manager.cpp | 4 +- myframe/poller.cpp | 2 +- myframe/worker_context.cpp | 6 ++- myframe/worker_context.h | 3 +- myframe/worker_context_manager.cpp | 79 ++++++++++------------------- myframe/worker_context_manager.h | 12 ++--- 15 files changed, 251 insertions(+), 165 deletions(-) create mode 100644 myframe/event_manager.cpp create mode 100644 myframe/event_manager.h diff --git a/myframe/app.cpp b/myframe/app.cpp index 7e57f16..c732a74 100644 --- a/myframe/app.cpp +++ b/myframe/app.cpp @@ -15,6 +15,7 @@ Author: likepeng #include "myframe/actor.h" #include "myframe/actor_context.h" #include "myframe/actor_context_manager.h" +#include "myframe/event_manager.h" #include "myframe/event_conn.h" #include "myframe/event_conn_manager.h" #include "myframe/worker_context.h" @@ -32,7 +33,7 @@ std::shared_ptr App::GetTimerWorker() { return nullptr; } std::string worker_timer_name = "worker.timer.#1"; - auto w = worker_ctx_mgr_->Get(worker_timer_name); + auto w = ev_mgr_->Get(worker_timer_name); if (w == nullptr) { LOG(ERROR) << "can't find " << worker_timer_name; @@ -46,8 +47,9 @@ App::App() : poller_(new Poller()) , mods_(new ModManager()) , actor_ctx_mgr_(new ActorContextManager()) - , ev_conn_mgr_(new EventConnManager()) - , worker_ctx_mgr_(new WorkerContextManager()) + , ev_mgr_(new EventManager()) + , ev_conn_mgr_(new EventConnManager(ev_mgr_)) + , worker_ctx_mgr_(new WorkerContextManager(ev_mgr_)) {} App::~App() { @@ -68,7 +70,7 @@ bool App::Init( warning_msg_size_.store(warning_msg_size); ret &= poller_->Init(); ret &= worker_ctx_mgr_->Init(warning_msg_size); - ret &= ev_conn_mgr_->Init(shared_from_this(), event_conn_size); + ret &= ev_conn_mgr_->Init(event_conn_size); ret &= StartCommonWorker(thread_pool_size); ret &= StartTimerWorker(); @@ -298,8 +300,14 @@ bool App::AddWorker( int App::Send( const std::string& dst, std::shared_ptr msg) { - auto conn = ev_conn_mgr_->Get(); + auto conn = ev_conn_mgr_->Alloc(); + if (conn == nullptr) { + LOG(ERROR) << "alloc conn event failed"; + return -1; + } + poller_->Add(conn); auto ret = conn->Send(dst, msg); + poller_->Del(conn); ev_conn_mgr_->Release(conn); return ret; } @@ -307,8 +315,14 @@ int App::Send( const std::shared_ptr App::SendRequest( const std::string& name, std::shared_ptr msg) { - auto conn = ev_conn_mgr_->Get(); + auto conn = ev_conn_mgr_->Alloc(); + if (conn == nullptr) { + LOG(ERROR) << "alloc conn event failed"; + return nullptr; + } + poller_->Add(conn); auto resp = conn->SendRequest(name, msg); + poller_->Del(conn); ev_conn_mgr_->Release(conn); return resp; } @@ -412,7 +426,7 @@ void App::DispatchMsg(std::list>* msg_list) { continue; } if (name_list[0] == "worker" - && worker_ctx_mgr_->HasWorker(msg->GetDst())) { + && ev_mgr_->Has(msg->GetDst())) { // dispatch to user worker worker_ctx_mgr_->DispatchWorkerMsg(msg); } else if (name_list[0] == "actor" @@ -421,7 +435,8 @@ void App::DispatchMsg(std::list>* msg_list) { actor_ctx_mgr_->DispatchMsg(msg); } else if (name_list[0] == "event") { if (name_list[1] == "conn") { - ev_conn_mgr_->Notify(msg->GetDst(), msg); + auto handle = ev_mgr_->ToHandle(msg->GetDst()); + ev_conn_mgr_->Notify(handle, msg); } else { LOG(ERROR) << "Unknown msg " << *msg; } @@ -590,8 +605,6 @@ void App::ProcessWorkerEvent(std::shared_ptr worker_ctx) { DLOG_IF(INFO, worker->GetActorContext() != nullptr) << *worker_ctx << " dispatch " << worker->GetActorContext()->GetActor()->GetActorName() << " msg..."; - LOG_IF(WARNING, worker->GetActorContext() == nullptr) - << *worker_ctx << " no context"; DispatchMsg(worker->GetActorContext()); CmdChannel::Cmd cmd; @@ -644,14 +657,10 @@ void App::ProcessEventConn(std::shared_ptr ev) { void App::ProcessEvent(const std::vector& evs) { DLOG_IF(INFO, evs.size() > 0) << "get " << evs.size() << " event"; for (size_t i = 0; i < evs.size(); ++i) { - std::shared_ptr ev_obj = nullptr; - ev_obj = worker_ctx_mgr_->Get(evs[i]); + auto ev_obj = ev_mgr_->Get(evs[i]); if (ev_obj == nullptr) { - ev_obj = ev_conn_mgr_->Get(evs[i]); - if (ev_obj == nullptr) { - LOG(ERROR) << "can't find ev obj, handle " << evs[i]; - continue; - } + LOG(ERROR) << "can't find ev obj, handle " << evs[i]; + continue; } switch (ev_obj->GetType()) { case Event::Type::kWorkerCommon: diff --git a/myframe/app.h b/myframe/app.h index 27e1799..33be462 100644 --- a/myframe/app.h +++ b/myframe/app.h @@ -26,6 +26,7 @@ class Actor; class ActorContext; class ActorContextManager; class Event; +class EventManager; class EventConn; class EventConnManager; class Worker; @@ -36,8 +37,6 @@ class WorkerContextManager; class ModManager; class App final : public std::enable_shared_from_this { friend class Actor; - friend class ActorContext; - friend class EventConnManager; public: App(); @@ -76,10 +75,6 @@ class App final : public std::enable_shared_from_this { const std::string& name, std::shared_ptr msg); - std::unique_ptr& GetActorContextManager() { - return actor_ctx_mgr_; - } - std::unique_ptr& GetModManager() { return mods_; } int Exec(); @@ -139,6 +134,8 @@ class App final : public std::enable_shared_from_this { std::unique_ptr mods_; /// 句柄管理对象 std::unique_ptr actor_ctx_mgr_; + /// 事件管理对象 + std::shared_ptr ev_mgr_; /// 与框架通信管理对象 std::unique_ptr ev_conn_mgr_; /// 线程管理对象 diff --git a/myframe/event.h b/myframe/event.h index 2621b2b..ef7c21c 100644 --- a/myframe/event.h +++ b/myframe/event.h @@ -6,6 +6,7 @@ Author: likepeng ****************************************************************************/ #pragma once #include +#include namespace myframe { @@ -24,10 +25,15 @@ class Event : public std::enable_shared_from_this { virtual ~Event() {} /* 事件类型 */ - virtual Type GetType() { return Type::kWorkerUser; } + virtual Type GetType() const { return Type::kWorkerUser; } /* 事件句柄 */ virtual ev_handle_t GetHandle() const = 0; + + /* 事件名称 */ + virtual std::string GetName() const = 0; + + static const ev_handle_t DEFAULT_EV_HANDLE{-1}; }; } // namespace myframe diff --git a/myframe/event_conn.cpp b/myframe/event_conn.cpp index 0bae2a4..a59cc67 100644 --- a/myframe/event_conn.cpp +++ b/myframe/event_conn.cpp @@ -17,7 +17,13 @@ ev_handle_t EventConn::GetHandle() const { return cmd_channel_.GetMainHandle(); } -Event::Type EventConn::GetType() { return Event::Type::kEventConn; } +Event::Type EventConn::GetType() const { + return Event::Type::kEventConn; +} + +std::string EventConn::GetName() const { + return mailbox_.Addr(); +} Mailbox* EventConn::GetMailbox() { return &mailbox_; diff --git a/myframe/event_conn.h b/myframe/event_conn.h index cd3553e..c108771 100644 --- a/myframe/event_conn.h +++ b/myframe/event_conn.h @@ -30,7 +30,8 @@ class EventConn final : public Event { EventConn() = default; ev_handle_t GetHandle() const override; - Event::Type GetType() override; + Event::Type GetType() const override; + std::string GetName() const override; EventConn::Type GetConnType() { return conn_type_; } diff --git a/myframe/event_conn_manager.cpp b/myframe/event_conn_manager.cpp index a75fbfa..633d96c 100644 --- a/myframe/event_conn_manager.cpp +++ b/myframe/event_conn_manager.cpp @@ -9,32 +9,21 @@ Author: likepeng #include -#include "myframe/app.h" -#include "myframe/poller.h" #include "myframe/event_conn.h" +#include "myframe/event_manager.h" namespace myframe { -EventConnManager::EventConnManager() { +EventConnManager::EventConnManager(std::shared_ptr ev_mgr) + : ev_mgr_(ev_mgr) { LOG(INFO) << "EventConnManager create"; } EventConnManager::~EventConnManager() { LOG(INFO) << "EventConnManager deconstruct"; - std::lock_guard g(mtx_); - auto app = app_.lock(); - if (app != nullptr) { - for (auto p : run_conn_) { - app->poller_->Del(p.second); - } - } - run_conn_.clear(); - run_conn_map_.clear(); - idle_conn_.clear(); } -bool EventConnManager::Init(std::shared_ptr app, int sz) { - app_ = app; +bool EventConnManager::Init(int sz) { for (int i = 0; i < sz; ++i) { std::lock_guard g(mtx_); AddEventConn(); @@ -50,72 +39,38 @@ void EventConnManager::AddEventConn() { conn_sz_++; } -std::shared_ptr EventConnManager::Get(ev_handle_t handle) { - std::lock_guard g(mtx_); - if (run_conn_map_.find(handle) == run_conn_map_.end()) { - DLOG(WARNING) << "can't find event conn, handle " << handle; - return nullptr; - } - auto name = run_conn_map_[handle]; - if (run_conn_.find(name) == run_conn_.end()) { - DLOG(WARNING) << "can't find event conn, name " << name; - return nullptr; - } - return run_conn_[name]; -} - -std::shared_ptr EventConnManager::Get() { +std::shared_ptr EventConnManager::Alloc() { std::lock_guard g(mtx_); // check has event conn if (idle_conn_.empty()) { AddEventConn(); } - auto app = app_.lock(); - if (app == nullptr) { - LOG(ERROR) << "app is nullptr"; - return nullptr; - } // remove from idle_conn auto conn = idle_conn_.front(); idle_conn_.pop_front(); // add to run_conn - const auto& addr = conn->GetMailbox()->Addr(); - run_conn_[addr] = conn; - run_conn_map_[conn->GetHandle()] = addr; - // add to epoll - app->poller_->Add(conn); + if (!ev_mgr_->Add(conn)) { + return nullptr; + } return conn; } void EventConnManager::Release(std::shared_ptr ev) { - std::lock_guard g(mtx_); - auto app = app_.lock(); - if (app == nullptr) { - LOG(ERROR) << "app is nullptr"; - return; - } - // delete from epoll - app->poller_->Del(ev); // remove from run_conn - const auto& name = ev->GetMailbox()->Addr(); - run_conn_.erase(name); - run_conn_map_.erase(ev->GetHandle()); + ev_mgr_->Del(ev); // add to idle_conn + std::lock_guard g(mtx_); idle_conn_.emplace_back(ev); } // call by main frame void EventConnManager::Notify( - const std::string& name, + ev_handle_t h, std::shared_ptr msg) { std::shared_ptr ev = nullptr; - { - std::lock_guard g(mtx_); - if (run_conn_.find(name) == run_conn_.end()) { - LOG(WARNING) << "can't find " << name; - return; - } - ev = run_conn_[name]; + ev = ev_mgr_->Get(h); + if (ev == nullptr) { + return; } if (ev->GetConnType() == EventConn::Type::kSend) { return; diff --git a/myframe/event_conn_manager.h b/myframe/event_conn_manager.h index 82b395e..e8be907 100644 --- a/myframe/event_conn_manager.h +++ b/myframe/event_conn_manager.h @@ -16,35 +16,29 @@ Author: likepeng namespace myframe { -class App; class Msg; +class EventManager; class EventConn; class EventConnManager final { - friend class App; - public: - EventConnManager(); + EventConnManager(std::shared_ptr); virtual ~EventConnManager(); - bool Init(std::shared_ptr app, int sz = 2); - - std::shared_ptr Get(); + bool Init(int sz = 2); - std::shared_ptr Get(ev_handle_t); + std::shared_ptr Alloc(); void Release(std::shared_ptr); + void Notify(ev_handle_t, std::shared_ptr msg); + private: void AddEventConn(); - void Notify(const std::string& name, std::shared_ptr msg); int conn_sz_{0}; std::mutex mtx_; - std::unordered_map run_conn_map_; - std::unordered_map> run_conn_; std::list> idle_conn_; - - std::weak_ptr app_; + std::shared_ptr ev_mgr_; DISALLOW_COPY_AND_ASSIGN(EventConnManager) }; diff --git a/myframe/event_manager.cpp b/myframe/event_manager.cpp new file mode 100644 index 0000000..63b2fa3 --- /dev/null +++ b/myframe/event_manager.cpp @@ -0,0 +1,80 @@ +/**************************************************************************** +Copyright (c) 2018, likepeng +All rights reserved. + +Author: likepeng +****************************************************************************/ + +#include "myframe/event_manager.h" + +#include + +#include +#include + +namespace myframe { + +EventManager::EventManager() { + LOG(INFO) << "EventManager create"; +} + +EventManager::~EventManager() { + LOG(INFO) << "EventManager deconstruct"; + std::unique_lock lk(rw_); + name_handle_map_.clear(); + evs_.clear(); +} + +ev_handle_t EventManager::ToHandle(const std::string& name) { + std::shared_lock lk(rw_); + if (name_handle_map_.find(name) == name_handle_map_.end()) { + return Event::DEFAULT_EV_HANDLE; + } + return name_handle_map_[name]; +} + +bool EventManager::Has(const std::string& name) { + std::shared_lock lk(rw_); + return name_handle_map_.find(name) != name_handle_map_.end(); +} + +std::vector> EventManager::Get( + const std::vector& type_list) { + std::shared_lock lk(rw_); + std::vector> tmp_evs; + for (auto it = evs_.begin(); it != evs_.end(); ++it) { + for (size_t i = 0; i < type_list.size(); ++i) { + if (type_list[i] == it->second->GetType()) { + tmp_evs.push_back(it->second); + break; + } + } + } + return tmp_evs; +} + +bool EventManager::Add(std::shared_ptr ev) { + auto handle = ev->GetHandle(); + std::unique_lock lk(rw_); + if (evs_.find(handle) != evs_.end()) { + LOG(ERROR) << " add handle " << handle << " has exist"; + return false; + } + evs_[handle] = ev; + name_handle_map_[ev->GetName()] = handle; + return true; +} + +bool EventManager::Del(std::shared_ptr ev) { + auto handle = ev->GetHandle(); + std::unique_lock lk(rw_); + if (evs_.find(handle) == evs_.end()) { + LOG(ERROR) << " del handle " << handle << " has exist"; + return false; + } + evs_.erase(handle); + name_handle_map_.erase(ev->GetName()); + return true; +} + +} // namespace myframe diff --git a/myframe/event_manager.h b/myframe/event_manager.h new file mode 100644 index 0000000..00a8d2d --- /dev/null +++ b/myframe/event_manager.h @@ -0,0 +1,66 @@ +/**************************************************************************** +Copyright (c) 2018, likepeng +All rights reserved. + +Author: likepeng +****************************************************************************/ +#pragma once +#include +#include +#include +#include +#include + +#include "myframe/macros.h" +#include "myframe/event.h" + +namespace myframe { + +class EventConnManager; +class WorkerContextManager; +class EventManager final { + friend class EventConnManager; + friend class WorkerContextManager; + + public: + EventManager(); + virtual ~EventManager(); + + template + std::shared_ptr Get(ev_handle_t h) { + std::shared_lock lk(rw_); + if (evs_.find(h) == evs_.end()) { + return nullptr; + } + return std::dynamic_pointer_cast(evs_[h]); + } + + template + std::shared_ptr Get(const std::string& name) { + std::shared_lock lk(rw_); + if (name_handle_map_.find(name) == name_handle_map_.end()) { + return nullptr; + } + lk.unlock(); + return Get(name_handle_map_[name]); + } + + bool Has(const std::string& name); + + std::vector> Get( + const std::vector&); + + ev_handle_t ToHandle(const std::string&); + + private: + bool Add(std::shared_ptr); + bool Del(std::shared_ptr); + + std::shared_mutex rw_; + std::unordered_map name_handle_map_; + std::unordered_map> evs_; + + DISALLOW_COPY_AND_ASSIGN(EventManager) +}; + +} // namespace myframe diff --git a/myframe/mod_manager.cpp b/myframe/mod_manager.cpp index 9cf3319..901d6fa 100644 --- a/myframe/mod_manager.cpp +++ b/myframe/mod_manager.cpp @@ -28,8 +28,8 @@ bool ModManager::LoadMod(const std::string& dl_path) { auto dlname = GetLibName(dl_path); std::unique_lock lk(mods_rw_); if (mods_.find(dlname) != mods_.end()) { - DLOG(ERROR) << dlname << " has loaded"; - return false; + DLOG(INFO) << dlname << " has loaded"; + return true; } auto lib = std::make_shared(); if (!lib->Load(dl_path, SharedLibrary::Flags::kLocal)) { diff --git a/myframe/poller.cpp b/myframe/poller.cpp index 9145957..500307c 100644 --- a/myframe/poller.cpp +++ b/myframe/poller.cpp @@ -89,7 +89,7 @@ int Poller::Wait(std::vector* evs, int timeout_ms) { static_cast(max_ev_count_), timeout_ms); if (0 > ev_count) { - LOG(ERROR) << "epoll wait error: " << strerror(errno); + LOG(WARNING) << "epoll wait error: " << strerror(errno); return -1; } for (int i = 0; i < ev_count; ++i) { diff --git a/myframe/worker_context.cpp b/myframe/worker_context.cpp index f4fe925..5884829 100644 --- a/myframe/worker_context.cpp +++ b/myframe/worker_context.cpp @@ -33,10 +33,14 @@ ev_handle_t WorkerContext::GetHandle() const { return cmd_channel_.GetMainHandle(); } -Event::Type WorkerContext::GetType() { +Event::Type WorkerContext::GetType() const { return worker_->GetType(); } +std::string WorkerContext::GetName() const { + return worker_->GetWorkerName(); +} + void WorkerContext::Start() { if (runing_.load() == false) { runing_.store(true); diff --git a/myframe/worker_context.h b/myframe/worker_context.h index 4657a14..26cf928 100644 --- a/myframe/worker_context.h +++ b/myframe/worker_context.h @@ -42,7 +42,8 @@ class WorkerContext final : public Event { /// event 相关函数 ev_handle_t GetHandle() const override; - Event::Type GetType() override; + Event::Type GetType() const override; + std::string GetName() const override; Mailbox* GetMailbox(); diff --git a/myframe/worker_context_manager.cpp b/myframe/worker_context_manager.cpp index e8f44c1..e36bf7d 100644 --- a/myframe/worker_context_manager.cpp +++ b/myframe/worker_context_manager.cpp @@ -13,10 +13,13 @@ Author: likepeng #include "myframe/msg.h" #include "myframe/worker.h" #include "myframe/worker_context.h" +#include "myframe/event_manager.h" namespace myframe { -WorkerContextManager::WorkerContextManager() { +WorkerContextManager::WorkerContextManager( + std::shared_ptr ev_mgr) + : ev_mgr_(ev_mgr) { LOG(INFO) << "WorkerContextManager create"; } @@ -31,53 +34,20 @@ bool WorkerContextManager::Init(int warning_msg_size) { int WorkerContextManager::WorkerSize() { return cur_worker_count_.load(); } -std::shared_ptr WorkerContextManager::Get(ev_handle_t handle) { - std::shared_lock lk(rw_); - if (worker_ctxs_.find(handle) == worker_ctxs_.end()) { - DLOG(WARNING) << "can't find worker, handle " << handle; - return nullptr; - } - auto ret = worker_ctxs_[handle]; - return ret; -} - -std::shared_ptr WorkerContextManager::Get( - const std::string& name) { - std::shared_lock lk(rw_); - if (name_handle_map_.find(name) == name_handle_map_.end()) { - LOG(ERROR) << "can't find worker, name " << name; - return nullptr; - } - auto handle = name_handle_map_[name]; - auto ret = worker_ctxs_[handle]; - return ret; -} - bool WorkerContextManager::Add(std::shared_ptr worker_ctx) { - auto worker = worker_ctx->GetWorker(); - auto handle = worker_ctx->GetHandle(); - std::unique_lock lk(rw_); - if (worker_ctxs_.find(handle) != worker_ctxs_.end()) { - LOG(ERROR) << *worker_ctx << " reg handle " << handle - << " has exist"; + if (!ev_mgr_->Add(worker_ctx)) { return false; } - worker_ctxs_[handle] = worker_ctx; - name_handle_map_[worker->GetWorkerName()] = handle; cur_worker_count_.fetch_add(1); return true; } void WorkerContextManager::Del(std::shared_ptr worker_ctx) { - auto worker = worker_ctx->GetWorker(); - auto handle = worker_ctx->GetHandle(); - std::unique_lock lk(rw_); - if (worker_ctxs_.find(handle) == worker_ctxs_.end()) { + if (!ev_mgr_->Del(worker_ctx)) { return; } + std::unique_lock lk(rw_); stoped_workers_ctx_.push_back(worker_ctx); - worker_ctxs_.erase(worker_ctxs_.find(handle)); - name_handle_map_.erase(worker->GetWorkerName()); cur_worker_count_.fetch_sub(1); } @@ -112,32 +82,33 @@ void WorkerContextManager::PushBackIdleWorker( idle_workers_ctx_.emplace_back(worker); } -bool WorkerContextManager::HasWorker(const std::string& name) { - bool res = false; - std::shared_lock lk(rw_); - res = (name_handle_map_.find(name) != name_handle_map_.end()); - return res; -} - std::vector WorkerContextManager::GetAllUserWorkerAddr() { std::vector res; std::shared_lock lk(rw_); - for (auto p : worker_ctxs_) { - if (p.second->GetType() == Event::Type::kWorkerUser - && p.second->GetWorker()->GetTypeName() != "node") { - res.push_back(p.second->GetWorker()->GetWorkerName()); + auto worker_ctx_list = ev_mgr_->Get({Event::Type::kWorkerUser}); + for (auto p : worker_ctx_list) { + auto worker_ctx = std::dynamic_pointer_cast(p); + auto worker = worker_ctx->GetWorker(); + // 主要服务与node类型的worker + // 所以返回的地址不包含node + if (worker->GetTypeName() != "node") { + res.push_back(worker->GetWorkerName()); } } return res; } void WorkerContextManager::StopAllWorker() { - std::shared_lock lk(rw_); - for (auto p : worker_ctxs_) { + auto worker_ctx_list = ev_mgr_->Get({ + Event::Type::kWorkerUser, + Event::Type::kWorkerCommon, + Event::Type::kWorkerTimer}); + for (auto p : worker_ctx_list) { + auto worker_ctx = std::dynamic_pointer_cast(p); // 目前仅支持使用channel通信的worker停止退出 // 不使用的可以调用Stop函数退出(目前暂无需求) - // p.second->Stop(); - p.second->GetCmdChannel()->SendToOwner(CmdChannel::Cmd::kQuit); + // worker_ctx->Stop(); + worker_ctx->GetCmdChannel()->SendToOwner(CmdChannel::Cmd::kQuit); } } @@ -179,12 +150,12 @@ void WorkerContextManager::WeakupWorker() { void WorkerContextManager::DispatchWorkerMsg(std::shared_ptr msg) { std::string worker_name = msg->GetDst(); - if (name_handle_map_.find(worker_name) == name_handle_map_.end()) { + if (!ev_mgr_->Has(worker_name)) { LOG(ERROR) << "can't find worker " << worker_name << ", drop msg: from " << msg->GetSrc() << " to " << msg->GetDst(); return; } - auto worker_ctx = Get(worker_name); + auto worker_ctx = ev_mgr_->Get(worker_name); auto worker = worker_ctx->GetWorker(); auto worker_type = worker->GetType(); if (worker_type == Event::Type::kWorkerTimer || diff --git a/myframe/worker_context_manager.h b/myframe/worker_context_manager.h index 37fbc6a..9f0d524 100644 --- a/myframe/worker_context_manager.h +++ b/myframe/worker_context_manager.h @@ -21,18 +21,17 @@ Author: likepeng namespace myframe { class Msg; +class EventManager; class WorkerContext; class WorkerContextManager final { public: - WorkerContextManager(); + WorkerContextManager(std::shared_ptr); virtual ~WorkerContextManager(); bool Init(int warning_msg_size = 10); int WorkerSize(); - std::shared_ptr Get(ev_handle_t); - std::shared_ptr Get(const std::string&); bool Add(std::shared_ptr worker); void Del(std::shared_ptr worker); @@ -48,7 +47,6 @@ class WorkerContextManager final { void DispatchWorkerMsg(std::shared_ptr msg); std::vector GetAllUserWorkerAddr(); - bool HasWorker(const std::string& name); // 停止工作线程 void StopAllWorker(); @@ -66,10 +64,8 @@ class WorkerContextManager final { std::list> weakup_workers_ctx_; /// 停止的线程列表 std::list> stoped_workers_ctx_; - /// name/handle 映射表 - std::unordered_map name_handle_map_; - /// handle/worker 映射表 - std::unordered_map> worker_ctxs_; + /// 事件管理对象 + std::shared_ptr ev_mgr_; DISALLOW_COPY_AND_ASSIGN(WorkerContextManager) }; From 3a3b3dbe6630107bddf387d128f6f37c7d780bbe Mon Sep 17 00:00:00 2001 From: likepeng01 Date: Mon, 24 Jul 2023 01:43:23 +0800 Subject: [PATCH 17/17] fix compile error --- myframe/event_manager.h | 1 + 1 file changed, 1 insertion(+) diff --git a/myframe/event_manager.h b/myframe/event_manager.h index 00a8d2d..4b97d0c 100644 --- a/myframe/event_manager.h +++ b/myframe/event_manager.h @@ -7,6 +7,7 @@ Author: likepeng #pragma once #include #include +#include #include #include #include