test

Dependencies:   mbed Watchdog

Dependents:   STM32-MC_node

Committer:
ommpy
Date:
Mon Jul 06 17:18:59 2020 +0530
Revision:
0:d383e2dee0f7
first commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ommpy 0:d383e2dee0f7 1 /* Copyright (c) 2017 ARM Limited
ommpy 0:d383e2dee0f7 2 * SPDX-License-Identifier: Apache-2.0
ommpy 0:d383e2dee0f7 3 *
ommpy 0:d383e2dee0f7 4 * Licensed under the Apache License, Version 2.0 (the "License");
ommpy 0:d383e2dee0f7 5 * you may not use this file except in compliance with the License.
ommpy 0:d383e2dee0f7 6 * You may obtain a copy of the License at
ommpy 0:d383e2dee0f7 7 *
ommpy 0:d383e2dee0f7 8 * http://www.apache.org/licenses/LICENSE-2.0
ommpy 0:d383e2dee0f7 9 *
ommpy 0:d383e2dee0f7 10 * Unless required by applicable law or agreed to in writing, software
ommpy 0:d383e2dee0f7 11 * distributed under the License is distributed on an "AS IS" BASIS,
ommpy 0:d383e2dee0f7 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
ommpy 0:d383e2dee0f7 13 * See the License for the specific language governing permissions and
ommpy 0:d383e2dee0f7 14 * limitations under the License.
ommpy 0:d383e2dee0f7 15 */
ommpy 0:d383e2dee0f7 16
ommpy 0:d383e2dee0f7 17 #ifndef MBED_NONCOPYABLE_H_
ommpy 0:d383e2dee0f7 18 #define MBED_NONCOPYABLE_H_
ommpy 0:d383e2dee0f7 19
ommpy 0:d383e2dee0f7 20 #if (!defined(MBED_DEBUG) && (MBED_CONF_PLATFORM_FORCE_NON_COPYABLE_ERROR == 0))
ommpy 0:d383e2dee0f7 21 #include "mbed_toolchain.h"
ommpy 0:d383e2dee0f7 22 #include "mbed_debug.h"
ommpy 0:d383e2dee0f7 23 #endif
ommpy 0:d383e2dee0f7 24
ommpy 0:d383e2dee0f7 25 namespace mbed {
ommpy 0:d383e2dee0f7 26
ommpy 0:d383e2dee0f7 27 /** \addtogroup platform */
ommpy 0:d383e2dee0f7 28 /** @{*/
ommpy 0:d383e2dee0f7 29 /**
ommpy 0:d383e2dee0f7 30 * \defgroup platform_NonCopyable NonCopyable class
ommpy 0:d383e2dee0f7 31 * @{
ommpy 0:d383e2dee0f7 32 */
ommpy 0:d383e2dee0f7 33
ommpy 0:d383e2dee0f7 34 /**
ommpy 0:d383e2dee0f7 35 * Prevents generation of copy constructor and copy assignment operator in
ommpy 0:d383e2dee0f7 36 * derived classes.
ommpy 0:d383e2dee0f7 37 *
ommpy 0:d383e2dee0f7 38 * @par Usage
ommpy 0:d383e2dee0f7 39 *
ommpy 0:d383e2dee0f7 40 * To prevent generation of copy constructor and copy assignment operator,
ommpy 0:d383e2dee0f7 41 * inherit privately from the NonCopyable class.
ommpy 0:d383e2dee0f7 42 *
ommpy 0:d383e2dee0f7 43 * @code
ommpy 0:d383e2dee0f7 44 * class Resource : NonCopyable<Resource> { };
ommpy 0:d383e2dee0f7 45 *
ommpy 0:d383e2dee0f7 46 * Resource r;
ommpy 0:d383e2dee0f7 47 * // generates compile time error:
ommpy 0:d383e2dee0f7 48 * Resource r2 = r;
ommpy 0:d383e2dee0f7 49 * @endcode
ommpy 0:d383e2dee0f7 50 *
ommpy 0:d383e2dee0f7 51 * @par Background information
ommpy 0:d383e2dee0f7 52 *
ommpy 0:d383e2dee0f7 53 * Instances of polymorphic classes are not meant to be copied. The
ommpy 0:d383e2dee0f7 54 * C++ standards generate a default copy constructor and copy assignment
ommpy 0:d383e2dee0f7 55 * function if these functions have not been defined in the class.
ommpy 0:d383e2dee0f7 56 *
ommpy 0:d383e2dee0f7 57 * Consider the following example:
ommpy 0:d383e2dee0f7 58 *
ommpy 0:d383e2dee0f7 59 * @code
ommpy 0:d383e2dee0f7 60 * // base class representing a connection
ommpy 0:d383e2dee0f7 61 * struct Connection {
ommpy 0:d383e2dee0f7 62 * Connection();
ommpy 0:d383e2dee0f7 63 * virtual ~Connection();
ommpy 0:d383e2dee0f7 64 * virtual void open() = 0;
ommpy 0:d383e2dee0f7 65 * }
ommpy 0:d383e2dee0f7 66 *
ommpy 0:d383e2dee0f7 67 * class SerialConnection : public Connection {
ommpy 0:d383e2dee0f7 68 * public:
ommpy 0:d383e2dee0f7 69 * SerialConnection(Serial*);
ommpy 0:d383e2dee0f7 70 *
ommpy 0:d383e2dee0f7 71 * private:
ommpy 0:d383e2dee0f7 72 * Serial* _serial;
ommpy 0:d383e2dee0f7 73 * };
ommpy 0:d383e2dee0f7 74 *
ommpy 0:d383e2dee0f7 75 * Connection& get_connection() {
ommpy 0:d383e2dee0f7 76 * static SerialConnection serial_connection;
ommpy 0:d383e2dee0f7 77 * return serial_connection;
ommpy 0:d383e2dee0f7 78 * }
ommpy 0:d383e2dee0f7 79 *
ommpy 0:d383e2dee0f7 80 * Connection connection = get_connection();
ommpy 0:d383e2dee0f7 81 * @endcode
ommpy 0:d383e2dee0f7 82 *
ommpy 0:d383e2dee0f7 83 * There is a subtle bug in this code, the function get_connection returns a
ommpy 0:d383e2dee0f7 84 * reference to a Connection which is captured by value instead of reference.
ommpy 0:d383e2dee0f7 85 *
ommpy 0:d383e2dee0f7 86 * When `get_connection` returns a reference to serial_connection it is copied into
ommpy 0:d383e2dee0f7 87 * the local variable connection. The vtable and others members defined in Connection
ommpy 0:d383e2dee0f7 88 * are copied, but members defined in SerialConnection are left apart. This can cause
ommpy 0:d383e2dee0f7 89 * severe crashes or bugs if the virtual functions captured use members not present
ommpy 0:d383e2dee0f7 90 * in the base declaration.
ommpy 0:d383e2dee0f7 91 *
ommpy 0:d383e2dee0f7 92 * To solve that problem, the copy constructor and assignment operator have to
ommpy 0:d383e2dee0f7 93 * be declared (but don't need to be defined) in the private section of the
ommpy 0:d383e2dee0f7 94 * Connection class:
ommpy 0:d383e2dee0f7 95 *
ommpy 0:d383e2dee0f7 96 * @code
ommpy 0:d383e2dee0f7 97 * struct Connection {
ommpy 0:d383e2dee0f7 98 * private:
ommpy 0:d383e2dee0f7 99 * Connection(const Connection&);
ommpy 0:d383e2dee0f7 100 * Connection& operator=(const Connection&);
ommpy 0:d383e2dee0f7 101 * }
ommpy 0:d383e2dee0f7 102 * @endcode
ommpy 0:d383e2dee0f7 103 *
ommpy 0:d383e2dee0f7 104 * Although manually declaring private copy constructor and assignment functions
ommpy 0:d383e2dee0f7 105 * works, it is not ideal. These declarations are usually easy to forget,
ommpy 0:d383e2dee0f7 106 * not immediately visible, and may be obscure to uninformed programmers.
ommpy 0:d383e2dee0f7 107 *
ommpy 0:d383e2dee0f7 108 * Using the NonCopyable class reduces the boilerplate required and expresses
ommpy 0:d383e2dee0f7 109 * the intent because class inheritance appears right after the class name
ommpy 0:d383e2dee0f7 110 * declaration.
ommpy 0:d383e2dee0f7 111 *
ommpy 0:d383e2dee0f7 112 * @code
ommpy 0:d383e2dee0f7 113 * struct Connection : private NonCopyable<Connection> {
ommpy 0:d383e2dee0f7 114 * // regular declarations
ommpy 0:d383e2dee0f7 115 * }
ommpy 0:d383e2dee0f7 116 * @endcode
ommpy 0:d383e2dee0f7 117 *
ommpy 0:d383e2dee0f7 118 *
ommpy 0:d383e2dee0f7 119 * @par Implementation details
ommpy 0:d383e2dee0f7 120 *
ommpy 0:d383e2dee0f7 121 * Using a template type prevents cases where the empty base optimization cannot
ommpy 0:d383e2dee0f7 122 * be applied and therefore ensures that the cost of the NonCopyable semantic
ommpy 0:d383e2dee0f7 123 * sugar is null.
ommpy 0:d383e2dee0f7 124 *
ommpy 0:d383e2dee0f7 125 * As an example, the empty base optimization is prohibited if one of the empty
ommpy 0:d383e2dee0f7 126 * base classes is also a base type of the first nonstatic data member:
ommpy 0:d383e2dee0f7 127 *
ommpy 0:d383e2dee0f7 128 * @code
ommpy 0:d383e2dee0f7 129 * struct A { };
ommpy 0:d383e2dee0f7 130 * struct B : A {
ommpy 0:d383e2dee0f7 131 * int foo;
ommpy 0:d383e2dee0f7 132 * };
ommpy 0:d383e2dee0f7 133 * // thanks to empty base optimization, sizeof(B) == sizeof(int)
ommpy 0:d383e2dee0f7 134 *
ommpy 0:d383e2dee0f7 135 * struct C : A {
ommpy 0:d383e2dee0f7 136 * B b;
ommpy 0:d383e2dee0f7 137 * };
ommpy 0:d383e2dee0f7 138 *
ommpy 0:d383e2dee0f7 139 * // empty base optimization cannot be applied here because A from C and A from
ommpy 0:d383e2dee0f7 140 * // B have a different address. In that case, with the alignment
ommpy 0:d383e2dee0f7 141 * // sizeof(C) == 2* sizeof(int)
ommpy 0:d383e2dee0f7 142 * @endcode
ommpy 0:d383e2dee0f7 143 *
ommpy 0:d383e2dee0f7 144 * The solution to that problem is to templatize the empty class to make it
ommpy 0:d383e2dee0f7 145 * unique to the type it is applied to:
ommpy 0:d383e2dee0f7 146 *
ommpy 0:d383e2dee0f7 147 * @code
ommpy 0:d383e2dee0f7 148 * template<typename T>
ommpy 0:d383e2dee0f7 149 * struct A<T> { };
ommpy 0:d383e2dee0f7 150 * struct B : A<B> {
ommpy 0:d383e2dee0f7 151 * int foo;
ommpy 0:d383e2dee0f7 152 * };
ommpy 0:d383e2dee0f7 153 * struct C : A<C> {
ommpy 0:d383e2dee0f7 154 * B b;
ommpy 0:d383e2dee0f7 155 * };
ommpy 0:d383e2dee0f7 156 *
ommpy 0:d383e2dee0f7 157 * // empty base optimization can be applied B and C does not refer to the same
ommpy 0:d383e2dee0f7 158 * // kind of A. sizeof(C) == sizeof(B) == sizeof(int).
ommpy 0:d383e2dee0f7 159 * @endcode
ommpy 0:d383e2dee0f7 160 *
ommpy 0:d383e2dee0f7 161 * @tparam T The type that should be made noncopyable.
ommpy 0:d383e2dee0f7 162 *
ommpy 0:d383e2dee0f7 163 * @note Compile time errors are disabled if you use the develop or release profile.
ommpy 0:d383e2dee0f7 164 * To override this behavior and force compile time errors in all profiles,
ommpy 0:d383e2dee0f7 165 * set the configuration parameter "platform.force-non-copyable-error" to true.
ommpy 0:d383e2dee0f7 166 */
ommpy 0:d383e2dee0f7 167 template<typename T>
ommpy 0:d383e2dee0f7 168 class NonCopyable {
ommpy 0:d383e2dee0f7 169 #ifndef DOXYGEN_ONLY
ommpy 0:d383e2dee0f7 170 protected:
ommpy 0:d383e2dee0f7 171 /**
ommpy 0:d383e2dee0f7 172 * Disallow construction of NonCopyable objects from outside of its hierarchy.
ommpy 0:d383e2dee0f7 173 */
ommpy 0:d383e2dee0f7 174 NonCopyable() { }
ommpy 0:d383e2dee0f7 175 /**
ommpy 0:d383e2dee0f7 176 * Disallow destruction of NonCopyable objects from outside of its hierarchy.
ommpy 0:d383e2dee0f7 177 */
ommpy 0:d383e2dee0f7 178 ~NonCopyable() { }
ommpy 0:d383e2dee0f7 179
ommpy 0:d383e2dee0f7 180 #if (!defined(MBED_DEBUG) && (MBED_CONF_PLATFORM_FORCE_NON_COPYABLE_ERROR == 0))
ommpy 0:d383e2dee0f7 181 /**
ommpy 0:d383e2dee0f7 182 * NonCopyable copy constructor.
ommpy 0:d383e2dee0f7 183 *
ommpy 0:d383e2dee0f7 184 * A compile time warning is issued when this function is used, and a runtime
ommpy 0:d383e2dee0f7 185 * warning is printed when the copy construction of the noncopyable happens.
ommpy 0:d383e2dee0f7 186 *
ommpy 0:d383e2dee0f7 187 * If you see this warning, your code is probably doing something unspecified.
ommpy 0:d383e2dee0f7 188 * Copying of noncopyable resources can lead to resource leak and random error.
ommpy 0:d383e2dee0f7 189 */
ommpy 0:d383e2dee0f7 190 MBED_DEPRECATED("Invalid copy construction of a NonCopyable resource.")
ommpy 0:d383e2dee0f7 191 NonCopyable(const NonCopyable &)
ommpy 0:d383e2dee0f7 192 {
ommpy 0:d383e2dee0f7 193 debug("Invalid copy construction of a NonCopyable resource: %s\r\n", MBED_PRETTY_FUNCTION);
ommpy 0:d383e2dee0f7 194 }
ommpy 0:d383e2dee0f7 195
ommpy 0:d383e2dee0f7 196 /**
ommpy 0:d383e2dee0f7 197 * NonCopyable copy assignment operator.
ommpy 0:d383e2dee0f7 198 *
ommpy 0:d383e2dee0f7 199 * A compile time warning is issued when this function is used, and a runtime
ommpy 0:d383e2dee0f7 200 * warning is printed when the copy construction of the noncopyable happens.
ommpy 0:d383e2dee0f7 201 *
ommpy 0:d383e2dee0f7 202 * If you see this warning, your code is probably doing something unspecified.
ommpy 0:d383e2dee0f7 203 * Copying of noncopyable resources can lead to resource leak and random error.
ommpy 0:d383e2dee0f7 204 */
ommpy 0:d383e2dee0f7 205 MBED_DEPRECATED("Invalid copy assignment of a NonCopyable resource.")
ommpy 0:d383e2dee0f7 206 NonCopyable &operator=(const NonCopyable &)
ommpy 0:d383e2dee0f7 207 {
ommpy 0:d383e2dee0f7 208 debug("Invalid copy assignment of a NonCopyable resource: %s\r\n", MBED_PRETTY_FUNCTION);
ommpy 0:d383e2dee0f7 209 return *this;
ommpy 0:d383e2dee0f7 210 }
ommpy 0:d383e2dee0f7 211
ommpy 0:d383e2dee0f7 212 #else
ommpy 0:d383e2dee0f7 213 private:
ommpy 0:d383e2dee0f7 214 /**
ommpy 0:d383e2dee0f7 215 * Declare copy constructor as private. Any attempt to copy construct
ommpy 0:d383e2dee0f7 216 * a NonCopyable will fail at compile time.
ommpy 0:d383e2dee0f7 217 */
ommpy 0:d383e2dee0f7 218 NonCopyable(const NonCopyable &);
ommpy 0:d383e2dee0f7 219
ommpy 0:d383e2dee0f7 220 /**
ommpy 0:d383e2dee0f7 221 * Declare copy assignment operator as private. Any attempt to copy assign
ommpy 0:d383e2dee0f7 222 * a NonCopyable will fail at compile time.
ommpy 0:d383e2dee0f7 223 */
ommpy 0:d383e2dee0f7 224 NonCopyable &operator=(const NonCopyable &);
ommpy 0:d383e2dee0f7 225 #endif
ommpy 0:d383e2dee0f7 226 #endif
ommpy 0:d383e2dee0f7 227 };
ommpy 0:d383e2dee0f7 228
ommpy 0:d383e2dee0f7 229 /**@}*/
ommpy 0:d383e2dee0f7 230
ommpy 0:d383e2dee0f7 231 /**@}*/
ommpy 0:d383e2dee0f7 232
ommpy 0:d383e2dee0f7 233 } // namespace mbed
ommpy 0:d383e2dee0f7 234
ommpy 0:d383e2dee0f7 235 #endif /* MBED_NONCOPYABLE_H_ */