// **CAUTION** Child SHOULD inherit DLinkedList<Child, Parent>::Node
template <typename Child, typename Parent> struct DLinkedList
{
+ // @brief A hook for Child-Join event
+ static void joined(Parent *, Child *);
+ // @brief A hook for Child-Leave event
+ static void leaving(Parent *, Child *);
+
class Head
{
public:
// Update parent-child relation
child->parent(_parent);
+
+ // Notify Child-Joining event
+ joined(_parent, child);
}
public:
assert(child->parent() == _parent);
assert(!empty());
+ // Notify Child-Leaving event
+ leaving(_parent, child);
+
if (child == _head)
{
_head = child->next();
class Parent
{
public:
- Parent() : _list{this}
+ friend void coco::DLinkedList<Child, Parent>::joined(Parent *, Child *);
+ friend void coco::DLinkedList<Child, Parent>::leaving(Parent *, Child *);
+
+public:
+ Parent() : _list{this}, _count{0}
{
// DO NOTHING
}
public:
ChildList *children(void) { return &_list; }
+ uint32_t count(void) const { return _count; }
private:
ChildList _list;
+ uint32_t _count;
};
class Child final : public coco::DLinkedList<Child, Parent>::Node
namespace coco
{
+template <> void DLinkedList<Child, Parent>::joined(Parent *p, Child *) { p->_count += 1; }
+template <> void DLinkedList<Child, Parent>::leaving(Parent *p, Child *) { p->_count -= 1; }
+
template <> ChildList *DLinkedList<Child, Parent>::head(Parent *p) { return p->children(); }
} // namespace coco
} // namespace
+TEST_F(DLinkedListTest, append)
+{
+ auto parent = create<::Parent>();
+ auto child = create<::Child>();
+
+ parent->children()->append(child);
+
+ ASSERT_EQ(child->parent(), parent);
+ ASSERT_EQ(child->prev(), nullptr);
+ ASSERT_EQ(child->next(), nullptr);
+
+ ASSERT_EQ(parent->children()->head(), child);
+ ASSERT_EQ(parent->children()->tail(), child);
+ ASSERT_EQ(parent->count(), 1);
+}
+
TEST_F(DLinkedListTest, insert_two_elements)
{
auto parent = create<::Parent>();
namespace coco
{
+template <> void DLinkedList<Block, Module>::joined(Module *, Block *)
+{
+ // TODO Implement this
+}
+
+template <> void DLinkedList<Block, Module>::leaving(Module *, Block *)
+{
+ // TODO Implement this
+}
+
template <> BlockList *DLinkedList<Block, Module>::head(Module *m) { return m->block(); }
} // namespace coco
namespace coco
{
+template <> void DLinkedList<Instr, Block>::joined(Block *, Instr *)
+{
+ // TODO Implement this
+}
+
+template <> void DLinkedList<Instr, Block>::leaving(Block *, Instr *)
+{
+ // TODO Implement this
+}
+
template <> InstrList *DLinkedList<Instr, Block>::head(Block *b) { return b->instr(); }
} // namespace coco