From 120e4c319b7fc1dd9bfb4dacd455770b8068bb67 Mon Sep 17 00:00:00 2001 From: fchn289 Date: Sat, 5 Oct 2024 18:52:58 +0800 Subject: [PATCH] MtQ: integrate with dom --- src/thread/MtInQueue.cpp | 25 ++++++++++++-- src/thread/MtInQueue.hpp | 13 ++++--- ut/thread/MtInQueueTest.cpp | 69 +++++++++++++++++++++++++++++++------ 3 files changed, 91 insertions(+), 16 deletions(-) diff --git a/src/thread/MtInQueue.cpp b/src/thread/MtInQueue.cpp index 7d16077..0f7c76e 100644 --- a/src/thread/MtInQueue.cpp +++ b/src/thread/MtInQueue.cpp @@ -19,7 +19,7 @@ MtInQueue::~MtInQueue() { const auto nEle = mt_size(true); if (nEle) - WRN("discard nEle=" << nEle); // main thread can WRN() + WRN("(MtQ) discard nEle=" << nEle); // main thread can WRN() } // *********************************************************************************************** @@ -44,6 +44,13 @@ deque::iterator MtInQueue::begin_() return cache_.begin(); } +// *********************************************************************************************** +void MtInQueue::clearHdlrPool() +{ + tid_hdlr_S_.clear(); + setHdlrOK(); +} + // *********************************************************************************************** size_t MtInQueue::handleCacheEle_() { @@ -56,7 +63,7 @@ size_t MtInQueue::handleCacheEle_() auto&& id_hdlr = tid_hdlr_S_.find(ele_tid.second); if (id_hdlr == tid_hdlr_S_.end()) { - WRN("(MtQ) discard 1 ele(tid=" << ele_tid.second.name() << ") since no handler.") + defaultHdlr_(ele_tid); continue; } id_hdlr->second(ele_tid.first); @@ -122,6 +129,20 @@ ELE_TID MtInQueue::pop() return ele_tid; } +// *********************************************************************************************** +bool MtInQueue::setHdlrOK(const DftHdlr& aHdlr) +{ + if (aHdlr) + { + defaultHdlr_ = aHdlr; + return true; + } + else + { + WRN("(MtQ) why set null hdlr?"); + return false; + } +} // *********************************************************************************************** MtInQueue& mt_getQ() diff --git a/src/thread/MtInQueue.hpp b/src/thread/MtInQueue.hpp index bc2d933..7588658 100644 --- a/src/thread/MtInQueue.hpp +++ b/src/thread/MtInQueue.hpp @@ -39,12 +39,14 @@ namespace rlib // - ele & its type_index(==/!= ok, but type_info* & hash_code nok) // - shared_ptr is safe to cast void since type_index (but not safe as SafePtr's create) using ELE_TID = std::pair; -using EleHdlr = std::function; // NO exception allowed +using EleHdlr = std::function; // NO exception allowed +using DftHdlr = std::function; // NO exception allowed // *********************************************************************************************** class MtInQueue { public: + MtInQueue() { setHdlrOK(); } ~MtInQueue(); // aEle may not mt-safe, so here mv @@ -60,9 +62,10 @@ class MtInQueue // shall be called in main thread ONLY!!! template bool setHdlrOK(const EleHdlr&); + bool setHdlrOK(const DftHdlr& aHdlr = [](ELE_TID&){ WRN("(MtQ) discard 1 ele since no handler"); }); size_t handleAllEle(); auto nHdlr() const { return tid_hdlr_S_.size(); } - void clearHdlrPool() { tid_hdlr_S_.clear(); } + void clearHdlrPool(); private: std::deque::iterator begin_(); @@ -74,6 +77,7 @@ class MtInQueue std::mutex mutex_; std::unordered_map tid_hdlr_S_; + DftHdlr defaultHdlr_; // ------------------------------------------------------------------------------------------- #ifdef IN_GTEST @@ -135,14 +139,14 @@ bool MtInQueue::setHdlrOK(const EleHdlr& aHdlr) { if (! aHdlr) { - WRN("(MtInQueue) why set null hdlr?"); + WRN("(MtQ) why set null hdlr?"); return false; } auto&& tid = std::type_index(typeid(aEleType)); if (tid_hdlr_S_.find(tid) != tid_hdlr_S_.end()) { - ERR("(MtInQueue) failed!!! overwrite hdlr may unsafe existing data"); + ERR("(MtQ) failed!!! overwrite hdlr may unsafe existing data"); return false; } @@ -172,4 +176,5 @@ MtInQueue& mt_getQ(); // 2023-10-29 CSZ - integrate handler // 2024-02-15 CSZ 3)use SafePtr (mem-safe); shared_ptr is not mem-safe // 2024-03-10 CSZ - enhance safe of setHdlrOK() +// 2024-10-05 CSZ - integrate with domino // *********************************************************************************************** diff --git a/ut/thread/MtInQueueTest.cpp b/ut/thread/MtInQueueTest.cpp index 9244adc..dac3341 100644 --- a/ut/thread/MtInQueueTest.cpp +++ b/ut/thread/MtInQueueTest.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-3-Clause */ // *********************************************************************************************** +#include #include #include #include @@ -13,12 +14,19 @@ #include "MT_Semaphore.hpp" #include "UniLog.hpp" +#include "Domino.hpp" +#include "DataDomino.hpp" +#include "HdlrDomino.hpp" +using Dom = rlib::DataDomino>; +#define DAT_DOM (rlib::ObjAnywhere::getObj()) + #define IN_GTEST #include "MT_PingMainTH.hpp" -#include "MtInQueue.hpp" +#include "MtInQueueWithDom.hpp" #undef IN_GTEST using namespace std; +using namespace std::placeholders; using namespace testing; namespace rlib @@ -28,11 +36,14 @@ struct MtInQueueTest : public Test, public UniLog { MtInQueueTest() : UniLog(UnitTest::GetInstance()->current_test_info()->name()) - {} + { + ObjAnywhere::init(); + } ~MtInQueueTest() { mt_getQ().mt_clearElePool(); // not impact other testcase mt_getQ().clearHdlrPool(); // not impact other testcase + ObjAnywhere::deinit(); GTEST_LOG_FAIL } }; @@ -250,14 +261,6 @@ TEST_F(MtInQueueTest, GOLD_handle_bothCacheAndQueue_ifPossible_withoutBlocked) EXPECT_EQ(0u, mt_getQ().mt_size(true)) << "REQ: shall handle queue_ since unlocked"; EXPECT_EQ(2u, nCalled); } -TEST_F(MtInQueueTest, discard_noHdlrEle) -{ - mt_getQ().mt_push(MAKE_PTR(1)); - EXPECT_EQ(1u, mt_getQ().mt_size(true)); - - mt_getQ().handleAllEle(); - EXPECT_EQ(0u, mt_getQ().mt_size(true)) << "REQ: discard ele w/o hdlr - simple & no mem leak"; -} TEST_F(MtInQueueTest, handle_emptyQ) { EXPECT_EQ(0u, mt_getQ().mt_size(true)) << "REQ: can handle empty Q"; @@ -296,4 +299,50 @@ TEST_F(MtInQueueTest, handle_via_base) EXPECT_EQ(0u, mt_getQ().mt_size(true)) << "req: Base & Derive are handled correctly"; } +#define DEFAULT_HDLR +// *********************************************************************************************** +TEST_F(MtInQueueTest, noHdlrEle_default) +{ + mt_getQ().mt_push(MAKE_PTR(1)); + EXPECT_EQ(1u, mt_getQ().mt_size(true)); + + mt_getQ().handleAllEle(); + EXPECT_EQ(0u, mt_getQ().mt_size(true)) << "REQ: discard ele w/o hdlr - simple & no leak/crash"; +} +TEST_F(MtInQueueTest, noHdlrEle_setInvalidDefaultHdlr) +{ + EXPECT_FALSE(mt_getQ().setHdlrOK(nullptr)); + + mt_getQ().mt_push(MAKE_PTR(1)); + EXPECT_EQ(1u, mt_getQ().mt_size(true)); + mt_getQ().handleAllEle(); + EXPECT_EQ(0u, mt_getQ().mt_size(true)) << "REQ: discard ele w/o hdlr - simple & no leak/crash"; +} +TEST_F(MtInQueueTest, GOLD_noHdlrEle_setDefaultHdlr) +{ + // domino + auto msgSelf = make_safe(); + ObjAnywhere::emplaceObjOK(msgSelf); + ObjAnywhere::emplaceObjOK(make_safe()); + const auto en = string(EN_MTQ) + 'i'; + bool isCalled = false; + DAT_DOM->setHdlr(en, [&isCalled]{ isCalled = true; }); + + // MtQ: + EXPECT_TRUE(mt_getQ().setHdlrOK(bind(&defaultHdlr, _1))); + mt_getQ().mt_push(MAKE_PTR(1)); + mt_getQ().handleAllEle(); + EXPECT_EQ(1, *dynamic_pointer_cast(DAT_DOM->getData(en)).get()) + << "REQ: new MtQ default hdlr works"; + msgSelf->handleAllMsg(); + EXPECT_TRUE(isCalled) << "REQ: domino hdlr called"; + + mt_getQ().clearHdlrPool(); // reset default hdlr + isCalled = false; + mt_getQ().mt_push(MAKE_PTR(1)); + mt_getQ().handleAllEle(); + msgSelf->handleAllMsg(); + EXPECT_FALSE(isCalled) << "REQ: domino hdlr NOT called"; +} + } // namespace