Marco Zecchini
/
Example_RTOS
Rtos API example
Embed:
(wiki syntax)
Show/hide line numbers
NonCopyable.h
00001 /* Copyright (c) 2017 ARM Limited 00002 * 00003 * Licensed under the Apache License, Version 2.0 (the "License"); 00004 * you may not use this file except in compliance with the License. 00005 * You may obtain a copy of the License at 00006 * 00007 * http://www.apache.org/licenses/LICENSE-2.0 00008 * 00009 * Unless required by applicable law or agreed to in writing, software 00010 * distributed under the License is distributed on an "AS IS" BASIS, 00011 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00012 * See the License for the specific language governing permissions and 00013 * limitations under the License. 00014 */ 00015 00016 #ifndef MBED_NONCOPYABLE_H_ 00017 #define MBED_NONCOPYABLE_H_ 00018 00019 #if (!defined(MBED_DEBUG) && (MBED_CONF_PLATFORM_FORCE_NON_COPYABLE_ERROR == 0)) 00020 #include "mbed_toolchain.h" 00021 #include "mbed_debug.h" 00022 #endif 00023 00024 namespace mbed { 00025 00026 /** 00027 * Inheriting from this class autogeneration of copy construction and copy 00028 * assignement operations. 00029 * 00030 * Classes which are not value type should inherit privately from this class 00031 * to avoid generation of invalid copy constructor or copy assignement operator 00032 * which can lead to unoticeable programming errors. 00033 * 00034 * As an example consider the following signature: 00035 * 00036 * @code 00037 * class Resource; 00038 * 00039 * class Foo { 00040 * public: 00041 * Foo() : _resource(new Resource()) { } 00042 * ~Foo() { delete _resource; } 00043 * private: 00044 * Resource* _resource; 00045 * } 00046 * 00047 * Foo get_foo(); 00048 * 00049 * Foo foo = get_foo(); 00050 * @endcode 00051 * 00052 * There is a bug in this function, it returns a temporary value which will be 00053 * byte copied into foo then destroyed. Unfortunately, internaly the Foo class 00054 * manage a pointer to a Resource object. This pointer will be released when the 00055 * temporary is destroyed and foo will manage a pointer to an already released 00056 * Resource. 00057 * 00058 * Two issues has to be fixed in the example above: 00059 * - Function signature has to be changed to reflect the fact that Foo 00060 * instances cannot be copied. In that case accessor should return a 00061 * reference to give access to objects already existing and managed. 00062 * Generator on the other hand should return a pointer to the created object. 00063 * 00064 * @code 00065 * // return a reference to an already managed Foo instance 00066 * Foo& get_foo(); 00067 * Foo& foo = get_foo(); 00068 * 00069 * // create a new Foo instance 00070 * Foo* make_foo(); 00071 * Foo* m = make_foo(); 00072 * @endcode 00073 * 00074 * - Copy constructor and copy assignement operator has to be made private 00075 * in the Foo class. It prevents unwanted copy of Foo objects. This can be 00076 * done by declaring copy constructor and copy assignement in the private 00077 * section of the Foo class. 00078 * 00079 * @code 00080 * class Foo { 00081 * public: 00082 * Foo() : _resource(new Resource()) { } 00083 * ~Foo() { delete _resource; } 00084 * private: 00085 * // disallow copy operations 00086 * Foo(const Foo&); 00087 * Foo& operator=(const Foo&); 00088 * // data members 00089 * Resource* _resource; 00090 * } 00091 * @endcode 00092 * 00093 * Another solution is to inherit privately from the NonCopyable class. 00094 * It reduces the boiler plate needed to avoid copy operations but more 00095 * importantly it clarifies the programer intent and the object semantic. 00096 * 00097 * class Foo : private NonCopyable<Foo> { 00098 * public: 00099 * Foo() : _resource(new Resource()) { } 00100 * ~Foo() { delete _resource; } 00101 * private: 00102 * Resource* _resource; 00103 * } 00104 * 00105 * @tparam T The type that should be made non copyable. It prevent cases where 00106 * the empty base optimization cannot be applied and therefore ensure that the 00107 * cost of this semantic sugar is null. 00108 * 00109 * As an example, the empty base optimization is prohibited if one of the empty 00110 * base class is also a base type of the first non static data member: 00111 * 00112 * @code 00113 * struct A { }; 00114 * struct B : A { 00115 * int foo; 00116 * }; 00117 * // thanks to empty base optimization, sizeof(B) == sizeof(int) 00118 * 00119 * struct C : A { 00120 * B b; 00121 * }; 00122 * 00123 * // empty base optimization cannot be applied here because A from C and A from 00124 * // B shall have a different address. In that case, with the alignement 00125 * // sizeof(C) == 2* sizeof(int) 00126 * @endcode 00127 * 00128 * The solution to that problem is to templatize the empty class to makes it 00129 * unique to the type it is applied to: 00130 * 00131 * @code 00132 * template<typename T> 00133 * struct A<T> { }; 00134 * struct B : A<B> { 00135 * int foo; 00136 * }; 00137 * struct C : A<C> { 00138 * B b; 00139 * }; 00140 * 00141 * // empty base optimization can be applied B and C does not refer to the same 00142 * // kind of A. sizeof(C) == sizeof(B) == sizeof(int). 00143 * @endcode 00144 * 00145 * @note Compile time errors are disabled if the develop or the release profile 00146 * is used. To override this behavior and force compile time errors in all profile 00147 * set the configuration parameter "platform.force-non-copyable-error" to true. 00148 */ 00149 template<typename T> 00150 class NonCopyable { 00151 protected: 00152 /** 00153 * Disalow construction of NonCopyable objects from outside of its hierarchy. 00154 */ 00155 NonCopyable() { } 00156 /** 00157 * Disalow destruction of NonCopyable objects from outside of its hierarchy. 00158 */ 00159 ~NonCopyable() { } 00160 00161 #if (!defined(MBED_DEBUG) && (MBED_CONF_PLATFORM_FORCE_NON_COPYABLE_ERROR == 0)) 00162 /** 00163 * NonCopyable copy constructor. 00164 * 00165 * A compile time warning is issued when this function is used and a runtime 00166 * warning is printed when the copy construction of the non copyable happens. 00167 * 00168 * If you see this warning, your code is probably doing something unspecified. 00169 * Copy of non copyable resources can lead to resource leak and random error. 00170 */ 00171 MBED_DEPRECATED("Invalid copy construction of a NonCopyable resource.") 00172 NonCopyable(const NonCopyable&) 00173 { 00174 debug("Invalid copy construction of a NonCopyable resource: %s\r\n", MBED_PRETTY_FUNCTION); 00175 } 00176 00177 /** 00178 * NonCopyable copy assignment operator. 00179 * 00180 * A compile time warning is issued when this function is used and a runtime 00181 * warning is printed when the copy construction of the non copyable happens. 00182 * 00183 * If you see this warning, your code is probably doing something unspecified. 00184 * Copy of non copyable resources can lead to resource leak and random error. 00185 */ 00186 MBED_DEPRECATED("Invalid copy assignment of a NonCopyable resource.") 00187 NonCopyable& operator=(const NonCopyable&) 00188 { 00189 debug("Invalid copy assignment of a NonCopyable resource: %s\r\n", MBED_PRETTY_FUNCTION); 00190 return *this; 00191 } 00192 00193 #else 00194 private: 00195 /** 00196 * Declare copy constructor as private, any attempt to copy construct 00197 * a NonCopyable will fail at compile time. 00198 */ 00199 NonCopyable(const NonCopyable&); 00200 00201 /** 00202 * Declare copy assignement operator as private, any attempt to copy assign 00203 * a NonCopyable will fail at compile time. 00204 */ 00205 NonCopyable& operator=(const NonCopyable&); 00206 #endif 00207 }; 00208 00209 } // namespace mbed 00210 00211 #endif /* MBED_NONCOPYABLE_H_ */
Generated on Sun Jul 17 2022 08:25:28 by 1.7.2