init

Dependencies:   mbed

Committer:
Nathan Yonkee
Date:
Fri Mar 02 07:16:49 2018 -0700
Revision:
10:46a4cf51ee38
Parent:
9:d58e77ebd769
remove mbed-os

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Nathan Yonkee 9:d58e77ebd769 1 /* Copyright (c) 2017 ARM Limited
Nathan Yonkee 9:d58e77ebd769 2 *
Nathan Yonkee 9:d58e77ebd769 3 * Licensed under the Apache License, Version 2.0 (the "License");
Nathan Yonkee 9:d58e77ebd769 4 * you may not use this file except in compliance with the License.
Nathan Yonkee 9:d58e77ebd769 5 * You may obtain a copy of the License at
Nathan Yonkee 9:d58e77ebd769 6 *
Nathan Yonkee 9:d58e77ebd769 7 * http://www.apache.org/licenses/LICENSE-2.0
Nathan Yonkee 9:d58e77ebd769 8 *
Nathan Yonkee 9:d58e77ebd769 9 * Unless required by applicable law or agreed to in writing, software
Nathan Yonkee 9:d58e77ebd769 10 * distributed under the License is distributed on an "AS IS" BASIS,
Nathan Yonkee 9:d58e77ebd769 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Nathan Yonkee 9:d58e77ebd769 12 * See the License for the specific language governing permissions and
Nathan Yonkee 9:d58e77ebd769 13 * limitations under the License.
Nathan Yonkee 9:d58e77ebd769 14 */
Nathan Yonkee 9:d58e77ebd769 15
Nathan Yonkee 9:d58e77ebd769 16 #ifndef MBED_NONCOPYABLE_H_
Nathan Yonkee 9:d58e77ebd769 17 #define MBED_NONCOPYABLE_H_
Nathan Yonkee 9:d58e77ebd769 18
Nathan Yonkee 9:d58e77ebd769 19 #if (!defined(MBED_DEBUG) && (MBED_CONF_PLATFORM_FORCE_NON_COPYABLE_ERROR == 0))
Nathan Yonkee 9:d58e77ebd769 20 #include "mbed_toolchain.h"
Nathan Yonkee 9:d58e77ebd769 21 #include "mbed_debug.h"
Nathan Yonkee 9:d58e77ebd769 22 #endif
Nathan Yonkee 9:d58e77ebd769 23
Nathan Yonkee 9:d58e77ebd769 24 namespace mbed {
Nathan Yonkee 9:d58e77ebd769 25
Nathan Yonkee 9:d58e77ebd769 26 /**
Nathan Yonkee 9:d58e77ebd769 27 * Inheriting from this class autogeneration of copy construction and copy
Nathan Yonkee 9:d58e77ebd769 28 * assignement operations.
Nathan Yonkee 9:d58e77ebd769 29 *
Nathan Yonkee 9:d58e77ebd769 30 * Classes which are not value type should inherit privately from this class
Nathan Yonkee 9:d58e77ebd769 31 * to avoid generation of invalid copy constructor or copy assignement operator
Nathan Yonkee 9:d58e77ebd769 32 * which can lead to unoticeable programming errors.
Nathan Yonkee 9:d58e77ebd769 33 *
Nathan Yonkee 9:d58e77ebd769 34 * As an example consider the following signature:
Nathan Yonkee 9:d58e77ebd769 35 *
Nathan Yonkee 9:d58e77ebd769 36 * @code
Nathan Yonkee 9:d58e77ebd769 37 * class Resource;
Nathan Yonkee 9:d58e77ebd769 38 *
Nathan Yonkee 9:d58e77ebd769 39 * class Foo {
Nathan Yonkee 9:d58e77ebd769 40 * public:
Nathan Yonkee 9:d58e77ebd769 41 * Foo() : _resource(new Resource()) { }
Nathan Yonkee 9:d58e77ebd769 42 * ~Foo() { delete _resource; }
Nathan Yonkee 9:d58e77ebd769 43 * private:
Nathan Yonkee 9:d58e77ebd769 44 * Resource* _resource;
Nathan Yonkee 9:d58e77ebd769 45 * }
Nathan Yonkee 9:d58e77ebd769 46 *
Nathan Yonkee 9:d58e77ebd769 47 * Foo get_foo();
Nathan Yonkee 9:d58e77ebd769 48 *
Nathan Yonkee 9:d58e77ebd769 49 * Foo foo = get_foo();
Nathan Yonkee 9:d58e77ebd769 50 * @endcode
Nathan Yonkee 9:d58e77ebd769 51 *
Nathan Yonkee 9:d58e77ebd769 52 * There is a bug in this function, it returns a temporary value which will be
Nathan Yonkee 9:d58e77ebd769 53 * byte copied into foo then destroyed. Unfortunately, internaly the Foo class
Nathan Yonkee 9:d58e77ebd769 54 * manage a pointer to a Resource object. This pointer will be released when the
Nathan Yonkee 9:d58e77ebd769 55 * temporary is destroyed and foo will manage a pointer to an already released
Nathan Yonkee 9:d58e77ebd769 56 * Resource.
Nathan Yonkee 9:d58e77ebd769 57 *
Nathan Yonkee 9:d58e77ebd769 58 * Two issues has to be fixed in the example above:
Nathan Yonkee 9:d58e77ebd769 59 * - Function signature has to be changed to reflect the fact that Foo
Nathan Yonkee 9:d58e77ebd769 60 * instances cannot be copied. In that case accessor should return a
Nathan Yonkee 9:d58e77ebd769 61 * reference to give access to objects already existing and managed.
Nathan Yonkee 9:d58e77ebd769 62 * Generator on the other hand should return a pointer to the created object.
Nathan Yonkee 9:d58e77ebd769 63 *
Nathan Yonkee 9:d58e77ebd769 64 * @code
Nathan Yonkee 9:d58e77ebd769 65 * // return a reference to an already managed Foo instance
Nathan Yonkee 9:d58e77ebd769 66 * Foo& get_foo();
Nathan Yonkee 9:d58e77ebd769 67 * Foo& foo = get_foo();
Nathan Yonkee 9:d58e77ebd769 68 *
Nathan Yonkee 9:d58e77ebd769 69 * // create a new Foo instance
Nathan Yonkee 9:d58e77ebd769 70 * Foo* make_foo();
Nathan Yonkee 9:d58e77ebd769 71 * Foo* m = make_foo();
Nathan Yonkee 9:d58e77ebd769 72 * @endcode
Nathan Yonkee 9:d58e77ebd769 73 *
Nathan Yonkee 9:d58e77ebd769 74 * - Copy constructor and copy assignement operator has to be made private
Nathan Yonkee 9:d58e77ebd769 75 * in the Foo class. It prevents unwanted copy of Foo objects. This can be
Nathan Yonkee 9:d58e77ebd769 76 * done by declaring copy constructor and copy assignement in the private
Nathan Yonkee 9:d58e77ebd769 77 * section of the Foo class.
Nathan Yonkee 9:d58e77ebd769 78 *
Nathan Yonkee 9:d58e77ebd769 79 * @code
Nathan Yonkee 9:d58e77ebd769 80 * class Foo {
Nathan Yonkee 9:d58e77ebd769 81 * public:
Nathan Yonkee 9:d58e77ebd769 82 * Foo() : _resource(new Resource()) { }
Nathan Yonkee 9:d58e77ebd769 83 * ~Foo() { delete _resource; }
Nathan Yonkee 9:d58e77ebd769 84 * private:
Nathan Yonkee 9:d58e77ebd769 85 * // disallow copy operations
Nathan Yonkee 9:d58e77ebd769 86 * Foo(const Foo&);
Nathan Yonkee 9:d58e77ebd769 87 * Foo& operator=(const Foo&);
Nathan Yonkee 9:d58e77ebd769 88 * // data members
Nathan Yonkee 9:d58e77ebd769 89 * Resource* _resource;
Nathan Yonkee 9:d58e77ebd769 90 * }
Nathan Yonkee 9:d58e77ebd769 91 * @endcode
Nathan Yonkee 9:d58e77ebd769 92 *
Nathan Yonkee 9:d58e77ebd769 93 * Another solution is to inherit privately from the NonCopyable class.
Nathan Yonkee 9:d58e77ebd769 94 * It reduces the boiler plate needed to avoid copy operations but more
Nathan Yonkee 9:d58e77ebd769 95 * importantly it clarifies the programer intent and the object semantic.
Nathan Yonkee 9:d58e77ebd769 96 *
Nathan Yonkee 9:d58e77ebd769 97 * class Foo : private NonCopyable<Foo> {
Nathan Yonkee 9:d58e77ebd769 98 * public:
Nathan Yonkee 9:d58e77ebd769 99 * Foo() : _resource(new Resource()) { }
Nathan Yonkee 9:d58e77ebd769 100 * ~Foo() { delete _resource; }
Nathan Yonkee 9:d58e77ebd769 101 * private:
Nathan Yonkee 9:d58e77ebd769 102 * Resource* _resource;
Nathan Yonkee 9:d58e77ebd769 103 * }
Nathan Yonkee 9:d58e77ebd769 104 *
Nathan Yonkee 9:d58e77ebd769 105 * @tparam T The type that should be made non copyable. It prevent cases where
Nathan Yonkee 9:d58e77ebd769 106 * the empty base optimization cannot be applied and therefore ensure that the
Nathan Yonkee 9:d58e77ebd769 107 * cost of this semantic sugar is null.
Nathan Yonkee 9:d58e77ebd769 108 *
Nathan Yonkee 9:d58e77ebd769 109 * As an example, the empty base optimization is prohibited if one of the empty
Nathan Yonkee 9:d58e77ebd769 110 * base class is also a base type of the first non static data member:
Nathan Yonkee 9:d58e77ebd769 111 *
Nathan Yonkee 9:d58e77ebd769 112 * @code
Nathan Yonkee 9:d58e77ebd769 113 * struct A { };
Nathan Yonkee 9:d58e77ebd769 114 * struct B : A {
Nathan Yonkee 9:d58e77ebd769 115 * int foo;
Nathan Yonkee 9:d58e77ebd769 116 * };
Nathan Yonkee 9:d58e77ebd769 117 * // thanks to empty base optimization, sizeof(B) == sizeof(int)
Nathan Yonkee 9:d58e77ebd769 118 *
Nathan Yonkee 9:d58e77ebd769 119 * struct C : A {
Nathan Yonkee 9:d58e77ebd769 120 * B b;
Nathan Yonkee 9:d58e77ebd769 121 * };
Nathan Yonkee 9:d58e77ebd769 122 *
Nathan Yonkee 9:d58e77ebd769 123 * // empty base optimization cannot be applied here because A from C and A from
Nathan Yonkee 9:d58e77ebd769 124 * // B shall have a different address. In that case, with the alignement
Nathan Yonkee 9:d58e77ebd769 125 * // sizeof(C) == 2* sizeof(int)
Nathan Yonkee 9:d58e77ebd769 126 * @endcode
Nathan Yonkee 9:d58e77ebd769 127 *
Nathan Yonkee 9:d58e77ebd769 128 * The solution to that problem is to templatize the empty class to makes it
Nathan Yonkee 9:d58e77ebd769 129 * unique to the type it is applied to:
Nathan Yonkee 9:d58e77ebd769 130 *
Nathan Yonkee 9:d58e77ebd769 131 * @code
Nathan Yonkee 9:d58e77ebd769 132 * template<typename T>
Nathan Yonkee 9:d58e77ebd769 133 * struct A<T> { };
Nathan Yonkee 9:d58e77ebd769 134 * struct B : A<B> {
Nathan Yonkee 9:d58e77ebd769 135 * int foo;
Nathan Yonkee 9:d58e77ebd769 136 * };
Nathan Yonkee 9:d58e77ebd769 137 * struct C : A<C> {
Nathan Yonkee 9:d58e77ebd769 138 * B b;
Nathan Yonkee 9:d58e77ebd769 139 * };
Nathan Yonkee 9:d58e77ebd769 140 *
Nathan Yonkee 9:d58e77ebd769 141 * // empty base optimization can be applied B and C does not refer to the same
Nathan Yonkee 9:d58e77ebd769 142 * // kind of A. sizeof(C) == sizeof(B) == sizeof(int).
Nathan Yonkee 9:d58e77ebd769 143 * @endcode
Nathan Yonkee 9:d58e77ebd769 144 *
Nathan Yonkee 9:d58e77ebd769 145 * @note Compile time errors are disabled if the develop or the release profile
Nathan Yonkee 9:d58e77ebd769 146 * is used. To override this behavior and force compile time errors in all profile
Nathan Yonkee 9:d58e77ebd769 147 * set the configuration parameter "platform.force-non-copyable-error" to true.
Nathan Yonkee 9:d58e77ebd769 148 */
Nathan Yonkee 9:d58e77ebd769 149 template<typename T>
Nathan Yonkee 9:d58e77ebd769 150 class NonCopyable {
Nathan Yonkee 9:d58e77ebd769 151 protected:
Nathan Yonkee 9:d58e77ebd769 152 /**
Nathan Yonkee 9:d58e77ebd769 153 * Disalow construction of NonCopyable objects from outside of its hierarchy.
Nathan Yonkee 9:d58e77ebd769 154 */
Nathan Yonkee 9:d58e77ebd769 155 NonCopyable() { }
Nathan Yonkee 9:d58e77ebd769 156 /**
Nathan Yonkee 9:d58e77ebd769 157 * Disalow destruction of NonCopyable objects from outside of its hierarchy.
Nathan Yonkee 9:d58e77ebd769 158 */
Nathan Yonkee 9:d58e77ebd769 159 ~NonCopyable() { }
Nathan Yonkee 9:d58e77ebd769 160
Nathan Yonkee 9:d58e77ebd769 161 #if (!defined(MBED_DEBUG) && (MBED_CONF_PLATFORM_FORCE_NON_COPYABLE_ERROR == 0))
Nathan Yonkee 9:d58e77ebd769 162 /**
Nathan Yonkee 9:d58e77ebd769 163 * NonCopyable copy constructor.
Nathan Yonkee 9:d58e77ebd769 164 *
Nathan Yonkee 9:d58e77ebd769 165 * A compile time warning is issued when this function is used and a runtime
Nathan Yonkee 9:d58e77ebd769 166 * warning is printed when the copy construction of the non copyable happens.
Nathan Yonkee 9:d58e77ebd769 167 *
Nathan Yonkee 9:d58e77ebd769 168 * If you see this warning, your code is probably doing something unspecified.
Nathan Yonkee 9:d58e77ebd769 169 * Copy of non copyable resources can lead to resource leak and random error.
Nathan Yonkee 9:d58e77ebd769 170 */
Nathan Yonkee 9:d58e77ebd769 171 MBED_DEPRECATED("Invalid copy construction of a NonCopyable resource.")
Nathan Yonkee 9:d58e77ebd769 172 NonCopyable(const NonCopyable&)
Nathan Yonkee 9:d58e77ebd769 173 {
Nathan Yonkee 9:d58e77ebd769 174 debug("Invalid copy construction of a NonCopyable resource: %s\r\n", MBED_PRETTY_FUNCTION);
Nathan Yonkee 9:d58e77ebd769 175 }
Nathan Yonkee 9:d58e77ebd769 176
Nathan Yonkee 9:d58e77ebd769 177 /**
Nathan Yonkee 9:d58e77ebd769 178 * NonCopyable copy assignment operator.
Nathan Yonkee 9:d58e77ebd769 179 *
Nathan Yonkee 9:d58e77ebd769 180 * A compile time warning is issued when this function is used and a runtime
Nathan Yonkee 9:d58e77ebd769 181 * warning is printed when the copy construction of the non copyable happens.
Nathan Yonkee 9:d58e77ebd769 182 *
Nathan Yonkee 9:d58e77ebd769 183 * If you see this warning, your code is probably doing something unspecified.
Nathan Yonkee 9:d58e77ebd769 184 * Copy of non copyable resources can lead to resource leak and random error.
Nathan Yonkee 9:d58e77ebd769 185 */
Nathan Yonkee 9:d58e77ebd769 186 MBED_DEPRECATED("Invalid copy assignment of a NonCopyable resource.")
Nathan Yonkee 9:d58e77ebd769 187 NonCopyable& operator=(const NonCopyable&)
Nathan Yonkee 9:d58e77ebd769 188 {
Nathan Yonkee 9:d58e77ebd769 189 debug("Invalid copy assignment of a NonCopyable resource: %s\r\n", MBED_PRETTY_FUNCTION);
Nathan Yonkee 9:d58e77ebd769 190 return *this;
Nathan Yonkee 9:d58e77ebd769 191 }
Nathan Yonkee 9:d58e77ebd769 192
Nathan Yonkee 9:d58e77ebd769 193 #else
Nathan Yonkee 9:d58e77ebd769 194 private:
Nathan Yonkee 9:d58e77ebd769 195 /**
Nathan Yonkee 9:d58e77ebd769 196 * Declare copy constructor as private, any attempt to copy construct
Nathan Yonkee 9:d58e77ebd769 197 * a NonCopyable will fail at compile time.
Nathan Yonkee 9:d58e77ebd769 198 */
Nathan Yonkee 9:d58e77ebd769 199 NonCopyable(const NonCopyable&);
Nathan Yonkee 9:d58e77ebd769 200
Nathan Yonkee 9:d58e77ebd769 201 /**
Nathan Yonkee 9:d58e77ebd769 202 * Declare copy assignement operator as private, any attempt to copy assign
Nathan Yonkee 9:d58e77ebd769 203 * a NonCopyable will fail at compile time.
Nathan Yonkee 9:d58e77ebd769 204 */
Nathan Yonkee 9:d58e77ebd769 205 NonCopyable& operator=(const NonCopyable&);
Nathan Yonkee 9:d58e77ebd769 206 #endif
Nathan Yonkee 9:d58e77ebd769 207 };
Nathan Yonkee 9:d58e77ebd769 208
Nathan Yonkee 9:d58e77ebd769 209 } // namespace mbed
Nathan Yonkee 9:d58e77ebd769 210
Nathan Yonkee 9:d58e77ebd769 211 #endif /* MBED_NONCOPYABLE_H_ */