DetectorGraph  2.0
topicregistry-lite2.hpp
Go to the documentation of this file.
1 // Copyright 2017 Nest Labs, Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef DETECTORGRAPH_INCLUDE_TOPICREGISTRY_LITE2_HPP_
16 #define DETECTORGRAPH_INCLUDE_TOPICREGISTRY_LITE2_HPP_
17 
18 #include "topic.hpp"
19 #include "topicstate.hpp"
20 #include "dgassert.hpp"
21 #include "dgstdincludes.hpp"
22 
23 namespace DetectorGraph
24 {
25 /**
26  * @brief _Internal_ - A statically and automatically sized registry for Topics
27  *
28  * This TopicRegistry needs no explicit sizing, does not depend on RTTI nor STL
29  * and puts no requirements on TopicStates. It's downside is that its storage is
30  * static and thus behaves like a singleton - this means only one instance of
31  * TopicRegistry can be alive at any time.
32  *
33  * This implementation stores BaseTopic* on TTopicState-templated methods. The
34  * pointer can be set by calling ResolveOrRegister with a non-NULL argument and
35  * retrieved by calling the same method with a NULL argument.
36  *
37  * The type stored in the templated methods - RegistryNode - is a single node
38  * for a linked-list stack. Each node holds a BaseTopic* and a pointer to
39  * another RegistryNode. This allows TopicRegistry to perform cleanup of the
40  * static/singleton nodes per topic at the destructor.
41  */
42 class TopicRegistry
43 {
44  /**
45  * @brief _Internal_ - The node stored at each templated ResolveOrRegister
46  */
47  struct RegistryNode
48  {
49  RegistryNode()
50  : storedPtr(NULL), next(NULL)
51  {}
52  BaseTopic* storedPtr;
53  RegistryNode* next;
54  };
55 
56 public:
57  TopicRegistry() : mTopNode(NULL)
58  {
59  }
60 
62  {
63  Cleanup();
64  }
65 
66  /**
67  * @brief _Internal_ - Retrieves a Topic pointer for a given TopicState.
68  */
69  template<class TTopicState>
71  {
72 #if defined(BUILD_FEATURE_DETECTORGRAPH_CONFIG_STATIC_ASSERTS)
73  static_assert(std::is_base_of<TopicState, TTopicState>::value,
74  "Trying to Resolve non-Topic type.");
75 #endif
76  RegistryNode* nodePtr = ResolveOrRegister<TTopicState>(NULL);
77 
78  // Here one may feel tempted to check that there's a valid pointer
79  // for this type - but remember that in some versions of this graph
80  // a mechanism relies on this returning NULL to then create and
81  // register the missing topic.
82 
83  return static_cast<Topic<TTopicState>*>(nodePtr->storedPtr);
84  }
85 
86  /**
87  * @brief _Internal_ - Registers a Topic pointer for a given TopicState.
88  */
89  template<class TTopicState>
90  void Register(Topic<TTopicState>* topicPtr)
91  {
92 #if defined(BUILD_FEATURE_DETECTORGRAPH_CONFIG_STATIC_ASSERTS)
93  static_assert(std::is_base_of<TopicState, TTopicState>::value,
94  "Trying to Register non-Topic type.");
95 #endif
96  // Checks that this is the first registration for this type.
97  DG_ASSERT(ResolveOrRegister<TTopicState>(NULL)->storedPtr == NULL);
98 
99  RegistryNode* nodePtr = ResolveOrRegister<TTopicState>(topicPtr);
100  RegisterNode(nodePtr);
101  }
102 
103 private:
104  template<class TTopicState>
105  RegistryNode* ResolveOrRegister(Topic<TTopicState>* inTopicPtr)
106  {
107  static RegistryNode topicNode;
108  if (inTopicPtr)
109  {
110  topicNode.storedPtr = static_cast<BaseTopic*>(inTopicPtr);
111  }
112  return &topicNode;
113  }
114 
115  void RegisterNode(RegistryNode* node)
116  {
117  // adds to the end. If empty, next points to null.
118  node->next = mTopNode;
119  mTopNode = node;
120  }
121 
122  void Cleanup()
123  {
124  RegistryNode* node = mTopNode;
125  while (node)
126  {
127  RegistryNode* tmp = node->next;
128  node->storedPtr = NULL;
129  node->next = NULL;
130  node = tmp;
131  }
132  }
133 
134  RegistryNode* mTopNode;
135 };
136 
137 } // namespace DetectorGraph
138 
139 #endif // DETECTORGRAPH_INCLUDE_TOPICREGISTRY_LITE2_HPP_
Manage data and its handler.
Definition: topic.hpp:84
Topic< TTopicState > * Resolve()
Internal - Retrieves a Topic pointer for a given TopicState.
Provide interface for a topic.
Definition: topic.hpp:46
void Register(Topic< TTopicState > *topicPtr)
Internal - Registers a Topic pointer for a given TopicState.
#define DG_ASSERT(condition)
Definition: dgassert.hpp:20