Rtos API example

Committer:
marcozecchini
Date:
Sat Feb 23 12:13:36 2019 +0000
Revision:
0:9fca2b23d0ba
final commit

Who changed what in which revision?

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