From 7a2d2966d53b45c541da2f75d8eebee9598f8d4c Mon Sep 17 00:00:00 2001 From: =?utf8?q?=EB=B0=95=EC=A2=85=ED=98=84/=EB=8F=99=EC=9E=91=EC=A0=9C?= =?utf8?q?=EC=96=B4Lab=28SR=29/Staff=20Engineer/=EC=82=BC=EC=84=B1?= =?utf8?q?=EC=A0=84=EC=9E=90?= Date: Tue, 14 Aug 2018 16:43:01 +0900 Subject: [PATCH] [coco] Introduce PtrSlot (#969) This commit introduces PtrSlot which allows us to insert a hook on pointer updates. Signed-off-by: Jonghyun Park --- contrib/coco/core/include/coco/ADT/PtrSlot.h | 86 ++++++++++++++++++++++++++++ contrib/coco/core/src/ADT/PtrSlot.test.cpp | 65 +++++++++++++++++++++ 2 files changed, 151 insertions(+) create mode 100644 contrib/coco/core/include/coco/ADT/PtrSlot.h create mode 100644 contrib/coco/core/src/ADT/PtrSlot.test.cpp diff --git a/contrib/coco/core/include/coco/ADT/PtrSlot.h b/contrib/coco/core/include/coco/ADT/PtrSlot.h new file mode 100644 index 0000000..8797196 --- /dev/null +++ b/contrib/coco/core/include/coco/ADT/PtrSlot.h @@ -0,0 +1,86 @@ +#ifndef __COCO_ADT_PTR_SLOT_H__ +#define __COCO_ADT_PTR_SLOT_H__ + +#include +#include + +#include +#include + +namespace coco +{ + +template class PtrSlot +{ +public: + struct Hook + { + virtual ~Hook() = default; + + virtual void onTake(T *value) = 0; + virtual void onRelease(T *value) = 0; + }; + +public: + PtrSlot() : _value{nullptr} + { + // DO NOTHING + } + +public: + virtual ~PtrSlot() { value(nullptr); } + +public: + T *value(void) const { return _value; } + +public: + void value(T *value) + { + if (_value) + { + notifyRelease(_value); + _value = nullptr; + } + + assert(_value == nullptr); + + if (value) + { + _value = value; + notifyTake(_value); + } + + assert(_value == value); + } + +protected: + void insert(std::unique_ptr &&hook) { _hooks.emplace_back(std::move(hook)); } + +private: + void notifyTake(T *value) const + { + for (const auto &hook : _hooks) + { + hook->onTake(value); + } + } + +private: + void notifyRelease(T *value) const + { + for (const auto &hook : _hooks) + { + hook->onRelease(value); + } + } + +private: + T *_value; + +private: + std::vector> _hooks; +}; + +} // namespace coco + +#endif // __COCO_ADT_PTR_SLOT_H__ diff --git a/contrib/coco/core/src/ADT/PtrSlot.test.cpp b/contrib/coco/core/src/ADT/PtrSlot.test.cpp new file mode 100644 index 0000000..42f02ef --- /dev/null +++ b/contrib/coco/core/src/ADT/PtrSlot.test.cpp @@ -0,0 +1,65 @@ +#include "coco/ADT/PtrSlot.h" + +#include + +#include + +namespace +{ +struct Entity +{ + Entity() = default; +}; + +struct EntitySlot final : public coco::PtrSlot +{ +private: + class Hook final : public coco::PtrSlot::Hook + { + public: + Hook(std::set *bounded) : _bounded{bounded} + { + // DO NOTING + } + + public: + void onTake(Entity *node) { _bounded->insert(node); } + void onRelease(Entity *node) { _bounded->erase(node); } + + private: + std::set *_bounded; + }; + +public: + EntitySlot(std::set *bounded) { insert(nncc::foundation::make_unique(bounded)); } +}; +} // namespace + +TEST(ADT_PTR_SLOT, usecase) +{ + std::set bounded; + + EntitySlot slot{&bounded}; + + ASSERT_EQ(slot.value(), nullptr); + + Entity e_0; + Entity e_1; + + slot.value(&e_0); + + ASSERT_EQ(slot.value(), &e_0); + ASSERT_EQ(bounded.size(), 1); + ASSERT_EQ(bounded.count(&e_0), 1); + + slot.value(&e_1); + + ASSERT_EQ(slot.value(), &e_1); + ASSERT_EQ(bounded.size(), 1); + ASSERT_EQ(bounded.count(&e_1), 1); + + slot.value(nullptr); + + ASSERT_EQ(slot.value(), nullptr); + ASSERT_EQ(bounded.size(), 0); +} -- 2.7.4