Skip to content

Commit

Permalink
MtQ: integrate with dom
Browse files Browse the repository at this point in the history
  • Loading branch information
fchn289 committed Oct 5, 2024
1 parent 1e58dee commit 120e4c3
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 16 deletions.
25 changes: 23 additions & 2 deletions src/thread/MtInQueue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()
}

// ***********************************************************************************************
Expand All @@ -44,6 +44,13 @@ deque<ELE_TID>::iterator MtInQueue::begin_()
return cache_.begin();
}

// ***********************************************************************************************
void MtInQueue::clearHdlrPool()
{
tid_hdlr_S_.clear();
setHdlrOK();
}

// ***********************************************************************************************
size_t MtInQueue::handleCacheEle_()
{
Expand All @@ -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);
Expand Down Expand Up @@ -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()
Expand Down
13 changes: 9 additions & 4 deletions src/thread/MtInQueue.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<UniPtr, std::type_index>;
using EleHdlr = std::function<void(UniPtr)>; // NO exception allowed
using EleHdlr = std::function<void(UniPtr)>; // NO exception allowed
using DftHdlr = std::function<void(ELE_TID&)>; // NO exception allowed

// ***********************************************************************************************
class MtInQueue
{
public:
MtInQueue() { setHdlrOK(); }
~MtInQueue();

// aEle may not mt-safe, so here mv
Expand All @@ -60,9 +62,10 @@ class MtInQueue

// shall be called in main thread ONLY!!!
template<class aEleType> 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<ELE_TID>::iterator begin_();
Expand All @@ -74,6 +77,7 @@ class MtInQueue
std::mutex mutex_;

std::unordered_map<std::type_index, EleHdlr> tid_hdlr_S_;
DftHdlr defaultHdlr_;

// -------------------------------------------------------------------------------------------
#ifdef IN_GTEST
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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
// ***********************************************************************************************
69 changes: 59 additions & 10 deletions ut/thread/MtInQueueTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
// ***********************************************************************************************
#include <functional>
#include <future>
#include <gtest/gtest.h>
#include <queue>
Expand All @@ -13,12 +14,19 @@
#include "MT_Semaphore.hpp"
#include "UniLog.hpp"

#include "Domino.hpp"
#include "DataDomino.hpp"
#include "HdlrDomino.hpp"
using Dom = rlib::DataDomino<rlib::HdlrDomino<rlib::Domino>>;
#define DAT_DOM (rlib::ObjAnywhere::getObj<Dom>())

#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
Expand All @@ -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
}
};
Expand Down Expand Up @@ -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<int>(MAKE_PTR<int>(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";
Expand Down Expand Up @@ -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<int>(MAKE_PTR<int>(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<int>(MAKE_PTR<int>(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<MsgSelf>();
ObjAnywhere::emplaceObjOK(msgSelf);
ObjAnywhere::emplaceObjOK(make_safe<Dom>());
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<int>(MAKE_PTR<int>(1));
mt_getQ().handleAllEle();
EXPECT_EQ(1, *dynamic_pointer_cast<int>(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<int>(MAKE_PTR<int>(1));
mt_getQ().handleAllEle();
msgSelf->handleAllMsg();
EXPECT_FALSE(isCalled) << "REQ: domino hdlr NOT called";
}

} // namespace

0 comments on commit 120e4c3

Please sign in to comment.