Skip to content

Commit

Permalink
SafeWeak: so broadcast SafePtr to dom lib
Browse files Browse the repository at this point in the history
  • Loading branch information
fchn289 committed Feb 13, 2025
1 parent 4385a18 commit 8a85e47
Show file tree
Hide file tree
Showing 21 changed files with 215 additions and 123 deletions.
23 changes: 13 additions & 10 deletions src/domino/DataDomino.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
#pragma once

#include "DataStore.hpp"
#include "SafePtr.hpp"
#include "UniLog.hpp"
#include "UniPtr.hpp"

namespace rlib
{
Expand All @@ -24,42 +24,43 @@ class DataDomino : public aDominoType
{
// -------------------------------------------------------------------------------------------
// Extend Tile record:
// - data: now Tile can store any type of data besides state, optional
// - data: now Tile can store any type of data besides state
// - data is optional of Tile
// -------------------------------------------------------------------------------------------

public:
explicit DataDomino(const LogName& aUniLogName = ULN_DEFAULT) : aDominoType(aUniLogName) {}

// -------------------------------------------------------------------------------------------
// - for read/write data
// - if aEvName/data invalid, return null
// - if aEvName invalid, return null
// - not template<aDataType> so can virtual for WrDatDom
// . & let DataDomino has little idea of read-write ctrl, simpler
virtual SafePtr<void> getData(const Domino::EvName&) const;
virtual S_PTR<void> getData(const Domino::EvName&) const;

// -------------------------------------------------------------------------------------------
// - replace old data by new=aData if old != new
// - for aDataType w/o default constructor!!!
virtual void replaceData(const Domino::EvName&, SafePtr<void> = nullptr);
virtual void replaceData(const Domino::EvName&, S_PTR<void> = nullptr);

protected:
void rmEv_(const Domino::Event& aValidEv) override;

private:
// -------------------------------------------------------------------------------------------
DataStore<Domino::Event> ev_data_S_; // [event]=SafePtr<void>
DataStore<Domino::Event> ev_data_S_; // [event]=S_PTR<void>
};

// ***********************************************************************************************
template<typename aDominoType>
SafePtr<void> DataDomino<aDominoType>::getData(const Domino::EvName& aEvName) const
S_PTR<void> DataDomino<aDominoType>::getData(const Domino::EvName& aEvName) const
{
return ev_data_S_.get<void>(this->getEventBy(aEvName));
}

// ***********************************************************************************************
template<typename aDominoType>
void DataDomino<aDominoType>::replaceData(const Domino::EvName& aEvName, SafePtr<void> aData)
void DataDomino<aDominoType>::replaceData(const Domino::EvName& aEvName, S_PTR<void> aData)
{
ev_data_S_.replace(this->newEvent(aEvName), aData);
}
Expand All @@ -78,17 +79,18 @@ void DataDomino<aDominoType>::rmEv_(const Domino::Event& aValidEv)
// - getValue() is NOT mem-safe when aEvName not found
// . so getData() instead of getValue
// - this getData() cast type so convenient
// . SafePtr's cast is safe, while shared_ptr is NOT
template<typename aDataDominoType, typename aDataType>
auto getData(aDataDominoType& aDom, const Domino::EvName& aEvName)
{
return staticPtrCast<aDataType>(aDom.getData(aEvName));
return STATIC_PTR_CAST<aDataType>(aDom.getData(aEvName));
}

// ***********************************************************************************************
template<typename aDataDominoType, typename aDataType>
void setValue(aDataDominoType& aDom, const Domino::EvName& aEvName, const aDataType& aData)
{
aDom.replaceData(aEvName, make_safe<aDataType>(aData));
aDom.replaceData(aEvName, MAKE_PTR<aDataType>(aData));
}
} // namespace
// ***********************************************************************************************
Expand All @@ -107,4 +109,5 @@ void setValue(aDataDominoType& aDom, const Domino::EvName& aEvName, const aDataT
// 2022-12-30 CSZ - rm data
// 2024-02-12 CSZ 4)use SafePtr (mem-safe); shared_ptr is not mem-safe
// 2024-06-08 CSZ 5)use DataStore instead of map
// 2025-02-13 CSZ - support both SafePtr & shared_ptr
// ***********************************************************************************************
3 changes: 2 additions & 1 deletion src/domino/FreeHdlrDomino.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ void FreeHdlrDomino<aDominoType>::triggerHdlr_(const SharedMsgCB& aValidHdlr, co
return; // otherwise crash
auto hdlr = weakHdlr.lock(); // get
this->rmOneHdlrOK_(aValidEv, hdlr); // safer to rm first to avoid hdlr does sth strange
(*hdlr)(); // call; setHdlr() forbid cb==null
(*(hdlr.get()))(); // call; setHdlr() forbid cb==null
},
this->getPriority(aValidEv)
);
Expand All @@ -122,4 +122,5 @@ void FreeHdlrDomino<aDominoType>::triggerHdlr_(const SharedMsgCB& aValidHdlr, co
// 2022-03-27 CSZ - if ut case can test base class, never specify derive
// 2022-08-18 CSZ - replace CppLog by UniLog
// 2022-12-04 CSZ - simple & natural
// 2025-02-13 CSZ - support both SafePtr & shared_ptr
// ***********************************************************************************************
18 changes: 8 additions & 10 deletions src/domino/HdlrDomino.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,17 @@
//
// - class safe: yes
// . no duty to hdlr itself's any unsafe behavior
// . why shared_ptr rather than SafePtr to store hdlr?
// . HdlrDomino ensures safely usage of shared_ptr
// . principle: safe class can base on unsafe materials
// . mem safe: yes SafePtr, no shared_ptr
// ***********************************************************************************************
#pragma once

#include <functional>
#include <memory>
#include <unordered_map>

#include "MsgSelf.hpp"
#include "ObjAnywhere.hpp"
#include "SafePtr.hpp"
#include "UniLog.hpp"
#include "UniPtr.hpp"

namespace rlib
{
Expand All @@ -43,7 +40,7 @@ class HdlrDomino : public aDominoType
{
public:
explicit HdlrDomino(const LogName& aUniLogName = ULN_DEFAULT) : aDominoType(aUniLogName) {}
bool setMsgSelfOK(const SafePtr<MsgSelf>& aMsgSelf); // replace default
bool setMsgSelfOK(const S_PTR<MsgSelf>& aMsgSelf); // replace default; safe: yes SafePtr, no shared_ptr

Domino::Event setHdlr(const Domino::EvName&, const MsgCB& aHdlr);
bool rmOneHdlrOK(const Domino::EvName&); // rm by EvName
Expand Down Expand Up @@ -71,7 +68,7 @@ class HdlrDomino : public aDominoType
private:
std::unordered_map<Domino::Event, SharedMsgCB> ev_hdlr_S_;
protected:
SafePtr<MsgSelf> msgSelf_ = ObjAnywhere::getObj<MsgSelf>();
S_PTR<MsgSelf> msgSelf_ = ObjAnywhere::getObj<MsgSelf>();
public:
using aDominoType::oneLog;
};
Expand Down Expand Up @@ -167,7 +164,7 @@ Domino::Event HdlrDomino<aDominoType>::setHdlr(const Domino::EvName& aEvName, co
}

// set
auto newHdlr = std::make_shared<MsgCB>(aHdlr);
auto newHdlr = MAKE_PTR<MsgCB>(aHdlr);
ev_hdlr_S_.emplace(newEv, newHdlr);
HID("(HdlrDom) Succeed for EvName=" << aEvName);

Expand All @@ -182,7 +179,7 @@ Domino::Event HdlrDomino<aDominoType>::setHdlr(const Domino::EvName& aEvName, co

// ***********************************************************************************************
template<class aDominoType>
bool HdlrDomino<aDominoType>::setMsgSelfOK(const SafePtr<MsgSelf>& aMsgSelf)
bool HdlrDomino<aDominoType>::setMsgSelfOK(const S_PTR<MsgSelf>& aMsgSelf)
{
// validate
const auto nMsgUnhandled = msgSelf_ ? msgSelf_->nMsg() : 0; // HdlrDomino ensure msgSelf_ always NOT null
Expand Down Expand Up @@ -211,7 +208,7 @@ void HdlrDomino<aDominoType>::triggerHdlr_(const SharedMsgCB& aValidHdlr, const
[weakMsgCB = WeakMsgCB(aValidHdlr)]() mutable // WeakMsgCB is to support rm hdlr
{
if (! weakMsgCB.expired())
(*weakMsgCB.lock())(); // setHdlr() forbid cb==null
(*(weakMsgCB.lock().get()))(); // setHdlr() forbid cb==null
},
getPriority(aValidEv)
);
Expand All @@ -231,4 +228,5 @@ void HdlrDomino<aDominoType>::triggerHdlr_(const SharedMsgCB& aValidHdlr, const
// 2023-01-23 CSZ - rename pureRmHdlrOK to rmOneHdlrOK
// 2023-05-24 CSZ - support force call hdlr
// 2024-03-10 CSZ - enhance safe eg setMsgSelf()
// 2025-02-13 CSZ - support both SafePtr & shared_ptr
// ***********************************************************************************************
3 changes: 2 additions & 1 deletion src/domino/MultiHdlrDomino.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ Domino::Event MultiHdlrDomino<aDominoType>::multiHdlrOnSameEv(const Domino::EvNa
}

// set hdlr
auto&& newHdlr = std::make_shared<MsgCB>(aHdlr);
auto&& newHdlr = MAKE_PTR<MsgCB>(aHdlr);
auto&& ev = this->getEventBy(aEvName);
auto&& ev_hdlrs = ev_hdlrs_S_.find(ev);
if (ev_hdlrs == ev_hdlrs_S_.end())
Expand Down Expand Up @@ -207,4 +207,5 @@ bool MultiHdlrDomino<aDominoType>::rmOneHdlrOK_(const Domino::Event& aValidEv, c
// 2022-08-18 CSZ - replace CppLog by UniLog
// 2023-05-25 CSZ - support force call hdlr
// 2023-05-29 CSZ - rmAllHdlr
// 2025-02-13 CSZ - support both SafePtr & shared_ptr
// ***********************************************************************************************
25 changes: 13 additions & 12 deletions src/domino/WbasicDatDom.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@

#include <vector>

#include "SafePtr.hpp"
#include "UniLog.hpp"
#include "UniPtr.hpp"

namespace rlib
{
Expand All @@ -28,11 +28,11 @@ class WbasicDatDom : public aDominoType
bool isWrCtrl(const Domino::EvName&) const;
bool wrCtrlOk(const Domino::EvName&, const bool aNewState = true);

SafePtr<void> getData(const Domino::EvName&) const override;
SafePtr<void> wbasic_getData(const Domino::EvName&) const;
S_PTR<void> getData(const Domino::EvName&) const override;
S_PTR<void> wbasic_getData(const Domino::EvName&) const;

void replaceData(const Domino::EvName&, SafePtr<void> aData = nullptr) override;
void wbasic_replaceData(const Domino::EvName&, SafePtr<void> aData = nullptr);
void replaceData(const Domino::EvName&, S_PTR<void> aData = nullptr) override;
void wbasic_replaceData(const Domino::EvName&, S_PTR<void> aData = nullptr);

protected:
void rmEv_(const Domino::Event& aValidEv) override;
Expand All @@ -50,7 +50,7 @@ class WbasicDatDom : public aDominoType

// ***********************************************************************************************
template<typename aDominoType>
SafePtr<void> WbasicDatDom<aDominoType>::getData(const Domino::EvName& aEvName) const
S_PTR<void> WbasicDatDom<aDominoType>::getData(const Domino::EvName& aEvName) const
{
if (not isWrCtrl(aEvName))
return aDominoType::getData(aEvName);
Expand All @@ -69,7 +69,7 @@ bool WbasicDatDom<aDominoType>::isWrCtrl(const Domino::EvName& aEvName) const

// ***********************************************************************************************
template<typename aDominoType>
void WbasicDatDom<aDominoType>::replaceData(const Domino::EvName& aEvName, SafePtr<void> aData)
void WbasicDatDom<aDominoType>::replaceData(const Domino::EvName& aEvName, S_PTR<void> aData)
{
if (isWrCtrl(aEvName))
WRN("(WbasicDatDom) Failed!!! EvName=" << aEvName << " is not write-protect so unavailable via this func!!!")
Expand All @@ -88,7 +88,7 @@ void WbasicDatDom<aDominoType>::rmEv_(const Domino::Event& aValidEv)

// ***********************************************************************************************
template<typename aDominoType>
SafePtr<void> WbasicDatDom<aDominoType>::wbasic_getData(const Domino::EvName& aEvName) const
S_PTR<void> WbasicDatDom<aDominoType>::wbasic_getData(const Domino::EvName& aEvName) const
{
if (isWrCtrl(aEvName))
return aDominoType::getData(aEvName);
Expand All @@ -99,7 +99,7 @@ SafePtr<void> WbasicDatDom<aDominoType>::wbasic_getData(const Domino::EvName& aE

// ***********************************************************************************************
template<typename aDominoType>
void WbasicDatDom<aDominoType>::wbasic_replaceData(const Domino::EvName& aEvName, SafePtr<void> aData)
void WbasicDatDom<aDominoType>::wbasic_replaceData(const Domino::EvName& aEvName, S_PTR<void> aData)
{
if (isWrCtrl(aEvName))
aDominoType::replaceData(aEvName, aData);
Expand Down Expand Up @@ -134,16 +134,16 @@ bool WbasicDatDom<aDominoType>::wrCtrlOk(const Domino::EvName& aEvName, const bo
// . so getData() instead of getValue()
// - this func cast type so more convenient than WbasicDatDom's
template<typename aDataDominoType, typename aDataType>
SafePtr<aDataType> wbasic_getData(aDataDominoType& aDom, const Domino::EvName& aEvName)
S_PTR<aDataType> wbasic_getData(aDataDominoType& aDom, const Domino::EvName& aEvName)
{
return staticPtrCast<aDataType>(aDom.wbasic_getData(aEvName));
return STATIC_PTR_CAST<aDataType>(aDom.wbasic_getData(aEvName)); // mem safe: yes SafePtr, no shared_ptr
}

// ***********************************************************************************************
template<typename aDataDominoType, typename aDataType>
void wbasic_setValue(aDataDominoType& aDom, const Domino::EvName& aEvName, const aDataType& aData)
{
aDom.wbasic_replaceData(aEvName, make_safe<aDataType>(aData));
aDom.wbasic_replaceData(aEvName, MAKE_PTR<aDataType>(aData));
}

} // namespace
Expand All @@ -168,4 +168,5 @@ void wbasic_setValue(aDataDominoType& aDom, const Domino::EvName& aEvName, const
// 2022-12-03 CSZ - simple & natural
// 2022-12-31 CSZ - rm data
// 2024-02-12 CSZ 2)use SafePtr (mem-safe); shared_ptr is not mem-safe
// 2025-02-13 CSZ - support both SafePtr & shared_ptr
// ***********************************************************************************************
10 changes: 6 additions & 4 deletions src/msg_self/MsgSelf.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,9 @@
//
// - class safe: yes
// . not responsible for MsgCB itself's any unsafe behavior
// . why shared_ptr rather than SafePtr to store MsgCB?
// . MsgSelf ensures safely usage of shared_ptr
// . shared_ptr is safe since internal use only (pub-interface is MsgCB&)
// . principle: safe class can base on unsafe materials
// . SafePtr is just to test SafeWeak in real world
// . not support callback after ~MsgSelf() since all msg discarded when ~MsgSelf()
// . UtInitObjAnywhere gives example how to provide a common callback for main()
// ***********************************************************************************************
Expand Down Expand Up @@ -64,8 +65,8 @@ enum EMsgPriority : unsigned char
// - MsgCB can try-catch all exception
// - exception is bug to be fixed than pretected
using MsgCB = std::function<void()>;
using WeakMsgCB = std::weak_ptr<MsgCB>;
using SharedMsgCB = std::shared_ptr<MsgCB>;
using WeakMsgCB = W_PTR<MsgCB>;
using SharedMsgCB = S_PTR<MsgCB>;

// ***********************************************************************************************
class MsgSelf : public UniLog
Expand Down Expand Up @@ -109,4 +110,5 @@ class MsgSelf : public UniLog
// 2022-12-31 CSZ - not support MsgCB=nullptr
// 2023-07-13 CSZ - copilot compare
// 2023-10-27 CSZ - replace pingMainFN_() by mt_pingMainTH()
// 2025-02-13 CSZ - support both SafePtr & shared_ptr
// ***********************************************************************************************
22 changes: 11 additions & 11 deletions src/obj_anywhere/DataStore.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,16 @@
// . store data of any type: eg for ObjAnywhere
// * store multi-copy of data of the same type: eg for DataDomino
// . fetch data by unique key(eg string)
// . ensure mem safe of stored data by SafePtr
//
// - MT safe: NO
// - mem safe: yes
// - mem safe: yes if SafePtr
// ***********************************************************************************************
#pragma once

#include <unordered_map>

#include "SafePtr.hpp" // can't UniPtr.hpp since ut(=req) build-err
#include "UniLog.hpp"
#include "UniPtr.hpp"

namespace rlib
{
Expand All @@ -29,26 +28,26 @@ class DataStore
public:
// @brief: get a data
// @ret: ok or nullptr
template<typename aDataT> SafePtr<aDataT> get(const aDataKey& aKey) const;
template<typename aDataT> S_PTR<aDataT> get(const aDataKey& aKey) const;

// @brief: store a new data (ie not replace but add new or rm old by aData=nullptr)
// @ret: store ok/nok
bool emplaceOK(const aDataKey& aKey, SafePtr<void> aData);
bool emplaceOK(const aDataKey& aKey, S_PTR<void> aData);

// @brief: store a data (add new, replace old, or rm old by aData=nullptr)
void replace(const aDataKey& aKey, SafePtr<void> aData);
void replace(const aDataKey& aKey, S_PTR<void> aData);

size_t nData() const { return key_data_S_.size(); }
~DataStore() { HID("(DataStore) discard nData=" << nData()); } // debug

private:
// -------------------------------------------------------------------------------------------
std::unordered_map<aDataKey, SafePtr<void>> key_data_S_;
std::unordered_map<aDataKey, S_PTR<void>> key_data_S_;
};

// ***********************************************************************************************
template<typename aDataKey>
bool DataStore<aDataKey>::emplaceOK(const aDataKey& aKey, SafePtr<void> aData)
bool DataStore<aDataKey>::emplaceOK(const aDataKey& aKey, S_PTR<void> aData)
{
if (! aData)
{
Expand All @@ -72,20 +71,20 @@ bool DataStore<aDataKey>::emplaceOK(const aDataKey& aKey, SafePtr<void> aData)
// ***********************************************************************************************
template<typename aDataKey>
template<typename aDataT>
SafePtr<aDataT> DataStore<aDataKey>::get(const aDataKey& aKey) const
S_PTR<aDataT> DataStore<aDataKey>::get(const aDataKey& aKey) const
{
auto&& key_data = key_data_S_.find(aKey);
if (key_data == key_data_S_.end())
{
HID("(DataStore) can't find key=" << aKey);
return nullptr;
}
return dynPtrCast<aDataT>(key_data->second);
return STATIC_PTR_CAST<aDataT>(key_data->second); // mem safe: yes SafePtr, no shared_ptr
}

// ***********************************************************************************************
template<typename aDataKey>
void DataStore<aDataKey>::replace(const aDataKey& aKey, SafePtr<void> aData)
void DataStore<aDataKey>::replace(const aDataKey& aKey, S_PTR<void> aData)
{
if (! aData)
{
Expand All @@ -101,4 +100,5 @@ void DataStore<aDataKey>::replace(const aDataKey& aKey, SafePtr<void> aData)
// YYYY-MM-DD Who v)Modification Description
// .......... ......... .......................................................................
// 2024-06-05 CSZ 1)create
// 2025-02-13 CSZ - support both SafePtr & shared_ptr
// ***********************************************************************************************
1 change: 0 additions & 1 deletion src/obj_anywhere/ObjAnywhere.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
* Licensed under the BSD 3 Clause license
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <memory>
#include "ObjAnywhere.hpp"

using namespace std;
Expand Down
Loading

0 comments on commit 8a85e47

Please sign in to comment.