Line data Source code
1 : /*
2 : *
3 : * Copyright (c) 2024 Project CHIP Authors
4 : * All rights reserved.
5 : *
6 : * Licensed under the Apache License, Version 2.0 (the "License");
7 : * you may not use this file except in compliance with the License.
8 : * You may obtain a copy of the License at
9 : *
10 : * http://www.apache.org/licenses/LICENSE-2.0
11 : *
12 : * Unless required by applicable law or agreed to in writing, software
13 : * distributed under the License is distributed on an "AS IS" BASIS,
14 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 : * See the License for the specific language governing permissions and
16 : * limitations under the License.
17 : */
18 : #pragma once
19 :
20 : #include <lib/support/CodeUtils.h>
21 :
22 : namespace chip {
23 :
24 : /// A template that is able to provide the global instance
25 : /// for some application-specific class
26 : ///
27 : /// It works specifically together with CheckedGlobalInstanceReference
28 : template <class T>
29 : struct GlobalInstanceProvider
30 : {
31 : static T * InstancePointer();
32 : };
33 :
34 : /// A class that looks like a smart pointer (overrides operator->)
35 : ///
36 : /// However internally it only checks that the provided value is a given
37 : /// Global instance.
38 : ///
39 : /// The global instance should be provided via GlobalInstanceProvider, for
40 : /// example
41 : ///
42 : /// namespace chip {
43 : /// template<>
44 : /// Foo *GlobalInstanceProvider<Foo>::InstancePointer() {
45 : /// return Foo::Instance();
46 : /// }
47 : /// } // namespace chip
48 : ///
49 : /// The CheckedGlobalInstanceReference will have minimal size (1 byte because
50 : /// comparing instance pointers has to work) and does not require alignment,
51 : /// as opposed to sizeof(void*) usage for SimpleInstanceReferences
52 : ///
53 : template <class T>
54 : class CheckedGlobalInstanceReference
55 : {
56 : public:
57 : CheckedGlobalInstanceReference() = default;
58 : CheckedGlobalInstanceReference(T * e) { VerifyOrDie(e == GlobalInstanceProvider<T>::InstancePointer()); }
59 : CheckedGlobalInstanceReference & operator=(T * value)
60 : {
61 : VerifyOrDie(value == GlobalInstanceProvider<T>::InstancePointer());
62 : return *this;
63 : }
64 :
65 : inline T * operator->() { return GlobalInstanceProvider<T>::InstancePointer(); }
66 : inline const T * operator->() const { return GlobalInstanceProvider<T>::InstancePointer(); }
67 : inline operator bool() const { return true; }
68 : };
69 :
70 : /// A class that acts as a wrapper to a pointer and provides
71 : /// operator-> overrides.
72 : ///
73 : /// It provides the same interface as CheckedGlobalInstanceReference
74 : /// however it does NOT use a global value.
75 : ///
76 : /// The intended usage of these pair of classes is to compile-time decide
77 : /// if global variables are to be used or if fully dynamic pointers are
78 : /// allowed.
79 : ///
80 : /// Example:
81 : /// #if USE_GLOBALS
82 : /// template<class T>
83 : /// using PointerContainer = chip::CheckedGlobalInstanceReference<T>;
84 : /// #else
85 : /// template<class T>
86 : /// using PointerContainer = chip::SimpleInstanceReference<T>;
87 : /// #endif
88 : template <class T>
89 : class SimpleInstanceReference
90 : {
91 : public:
92 236 : SimpleInstanceReference() = default;
93 5 : SimpleInstanceReference(T * e) : mValue(e) {}
94 429 : SimpleInstanceReference & operator=(T * value)
95 : {
96 429 : mValue = value;
97 429 : return *this;
98 : }
99 :
100 2494 : T * operator->() { return mValue; }
101 : const T * operator->() const { return mValue; }
102 2490 : inline operator bool() const { return mValue != nullptr; }
103 :
104 : private:
105 : T * mValue = nullptr;
106 : };
107 :
108 : } // namespace chip
|