1 /*
2  *  Copyright (c) 2017, The OpenThread Authors.
3  *  All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions are met:
7  *  1. Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  *  2. Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *  3. Neither the name of the copyright holder nor the
13  *     names of its contributors may be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  *  POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /**
30  * @file
31  *   This file includes definitions for locator class for OpenThread objects.
32  */
33 
34 #ifndef LOCATOR_HPP_
35 #define LOCATOR_HPP_
36 
37 #include "openthread-core-config.h"
38 
39 #include <openthread/platform/toolchain.h>
40 
41 #include <stdint.h>
42 
43 namespace ot {
44 
45 class Instance;
46 
47 #if !OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
48 extern uint64_t gInstanceRaw[];
49 #endif
50 
51 /**
52  * @addtogroup core-locator
53  *
54  * @brief
55  *   This module includes definitions for OpenThread instance locator.
56  *
57  * @{
58  *
59  */
60 
61 /**
62  * Implements `Get<Type>()` method for different `Type` objects belonging to the OpenThread
63  * instance.
64  *
65  * Users of this class MUST follow CRTP-style inheritance, i.e., the class `Class` itself should publicly inherit
66  * from `GetProvider<Class>`.
67  *
68  * @tparam InstanceGetProvider   The template sub-lass used in CRTP style inheritance.
69  *                               `InstanceGetProvider` MUST provide a method with the following signature:
70  *                               `Instance &GetInstance(void) const`
71  *
72  */
73 template <class InstanceGetProvider> class GetProvider
74 {
75 public:
76     /**
77      * Returns a reference to a given `Type` object belonging to the OpenThread instance.
78      *
79      * For example, `Get<MeshForwarder>()` returns a reference to the `MeshForwarder` object of the instance.
80      *
81      * Note that any `Type` for which the `Get<Type>` is defined MUST be uniquely accessible from the OpenThread
82      * `Instance` through the member variable property hierarchy.
83      *
84      * @returns A reference to the `Type` object of the instance.
85      *
86      */
87     template <typename Type> inline Type &Get(void) const; // Implemented in `locator_getters.hpp`.
88 
89 protected:
90     GetProvider(void) = default;
91 };
92 
93 /**
94  * Implements a locator for an OpenThread Instance object.
95  *
96  * The `InstanceLocator` is used as base class of almost all other OpenThread classes. It provides a way for an object
97  * to get to its owning/parent OpenThread `Instance` and also any other `Type` within the `Instance` member variable
98  * property hierarchy (using `Get<Type>()` method).
99  *
100  * If multiple-instance feature is supported, the owning/parent OpenThread `Instance` is tracked as a reference. In the
101  * single-instance case, this class becomes an empty base class.
102  *
103  */
104 class InstanceLocator : public GetProvider<InstanceLocator>
105 {
106     friend class InstanceLocatorInit;
107 
108 public:
109     /**
110      * Returns a reference to the parent OpenThread Instance.
111      *
112      * @returns A reference to the parent otInstance.
113      *
114      */
115 #if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
GetInstance(void) const116     Instance &GetInstance(void) const { return *mInstance; }
117 #else
118     Instance &GetInstance(void) const { return *reinterpret_cast<Instance *>(&gInstanceRaw); }
119 #endif
120 
121 protected:
122     /**
123      * Initializes the object.
124      *
125      * @param[in]  aInstance  A reference to the OpenThread Instance.
126      *
127      */
InstanceLocator(Instance & aInstance)128     explicit InstanceLocator(Instance &aInstance)
129 #if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
130         : mInstance(&aInstance)
131 #endif
132     {
133         OT_UNUSED_VARIABLE(aInstance);
134     }
135 
136 private:
137     InstanceLocator(void) = default;
138 
139 #if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
140     Instance *mInstance;
141 #endif
142 };
143 
144 /**
145  * Implements a locator for an OpenThread Instance object.
146  *
147  * The `InstanceLocatorInit` is similar to `InstanceLocator` but provides a default constructor (instead of a
148  * parameterized one) and allows an inheriting class to initialize the object (set the OpenThread Instance) post
149  * constructor call using the `Init()` method. This class is intended for types that require a default constructor and
150  * cannot use a parameterized one. (e.g., `Neighbor`/`Child`/`Router` classes which are used as a C array element type
151  * in`ChildTable`/`RouterTable`).
152  *
153  * The inheriting class from `InstanceLocatorInit` should ensure that object is properly initialized after the object
154  * is created and more importantly that it is re-initialized when/if it is cleared or reset.
155  *
156  */
157 class InstanceLocatorInit : public InstanceLocator
158 {
159 protected:
160     /**
161      * This is the default constructor for the `InstanceLocatorInit` object.
162      *
163      */
InstanceLocatorInit(void)164     InstanceLocatorInit(void)
165         : InstanceLocator()
166     {
167     }
168 
169     /**
170      * This method (re)initializes the object and sets the OpenThread Instance.
171      *
172      * @param[in] aInstance  A reference to the OpenThread Instance.
173      */
Init(Instance & aInstance)174     void Init(Instance &aInstance)
175     {
176 #if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE
177         mInstance = &aInstance;
178 #endif
179         OT_UNUSED_VARIABLE(aInstance);
180     }
181 };
182 
183 /**
184  * @}
185  *
186  */
187 
188 } // namespace ot
189 
190 #endif // LOCATOR_HPP_
191