Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: mbed_DS28EC20_GPIO
Function.hpp
00001 /******************************************************************************* 00002 * Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved. 00003 * 00004 * Permission is hereby granted, free of charge, to any person obtaining a 00005 * copy of this software and associated documentation files (the "Software"), 00006 * to deal in the Software without restriction, including without limitation 00007 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 00008 * and/or sell copies of the Software, and to permit persons to whom the 00009 * Software is furnished to do so, subject to the following conditions: 00010 * 00011 * The above copyright notice and this permission notice shall be included 00012 * in all copies or substantial portions of the Software. 00013 * 00014 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 00015 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 00016 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 00017 * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES 00018 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 00019 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 00020 * OTHER DEALINGS IN THE SOFTWARE. 00021 * 00022 * Except as contained in this notice, the name of Maxim Integrated 00023 * Products, Inc. shall not be used except as stated in the Maxim Integrated 00024 * Products, Inc. Branding Policy. 00025 * 00026 * The mere transfer of this software does not imply any licenses 00027 * of trade secrets, proprietary technology, copyrights, patents, 00028 * trademarks, maskwork rights, or any other form of intellectual 00029 * property whatsoever. Maxim Integrated Products, Inc. retains all 00030 * ownership rights. 00031 *******************************************************************************/ 00032 00033 #ifndef MaximInterface_Function 00034 #define MaximInterface_Function 00035 00036 #include <stddef.h> 00037 #include "SafeBool.hpp" 00038 #include "type_traits.hpp" 00039 00040 // Include for std::swap. 00041 #include <algorithm> 00042 #include <utility> 00043 00044 namespace MaximInterface { 00045 namespace detail { 00046 00047 // Provides char buffer storage for a given type. 00048 // Suitability of alignment for type should be verified with alignment_of. 00049 template <typename Type, size_t TypeSize> union TypeStorage { 00050 public: 00051 operator const Type *() const { return reinterpret_cast<const Type *>(data); } 00052 00053 operator Type *() { 00054 return const_cast<Type *>( 00055 static_cast<const Type *>(static_cast<const TypeStorage &>(*this))); 00056 } 00057 00058 const Type & operator*() const { return **this; } 00059 00060 Type & operator*() { 00061 return const_cast<Type &>( 00062 static_cast<const TypeStorage &>(*this).operator*()); 00063 } 00064 00065 const Type * operator->() const { return *this; } 00066 00067 Type * operator->() { 00068 return const_cast<Type *>( 00069 static_cast<const TypeStorage &>(*this).operator->()); 00070 } 00071 00072 private: 00073 char data[TypeSize]; 00074 long double aligner1; 00075 long int aligner2; 00076 void * aligner3; 00077 }; 00078 00079 // Computes the internal target size for TypeStorage based on a desired total 00080 // size. No internal storage will be allocated if the requested size is smaller 00081 // than the required data elements of TypeWrapper or if the requested size is 00082 // smaller than minimum size of TypeStorage. 00083 template <typename Target, size_t totalSize> class TypeWrapperTotalSize { 00084 private: 00085 typedef TypeStorage<Target, 1> MinSizeStorage; 00086 00087 static const size_t otherDataSize = sizeof(Target *); 00088 00089 // Round down to be a multiple of alignment_of<MinSizeTargetStorage>::value. 00090 static const size_t internalTargetRawSize = 00091 (totalSize - otherDataSize) / alignment_of<MinSizeStorage>::value * 00092 alignment_of<MinSizeStorage>::value; 00093 00094 public: 00095 // Use internal storage if internalTargetRawSize is valid and at least as 00096 // large as the minimum size of TypeStorage. 00097 static const size_t internalTargetSize = 00098 ((totalSize > otherDataSize) && 00099 (internalTargetRawSize >= sizeof(MinSizeStorage))) 00100 ? internalTargetRawSize 00101 : 0; 00102 }; 00103 00104 // Basic type erasure implementation with small object optimization. 00105 template <typename Target, template <typename> class TargetAdapter, 00106 size_t internalTargetSize = 00107 TypeWrapperTotalSize<Target, 32>::internalTargetSize> 00108 class TypeWrapper { 00109 private: 00110 typedef TypeStorage<Target, internalTargetSize> TargetStorage; 00111 00112 public: 00113 TypeWrapper() : currentTarget(NULL) {} 00114 00115 TypeWrapper(const TypeWrapper & other) { 00116 if (other.currentTarget == other.internalTarget) { 00117 other.currentTarget->clone(internalTarget); 00118 currentTarget = internalTarget; 00119 } else if (other.currentTarget) { 00120 currentTarget = other.currentTarget->clone(); 00121 } else { 00122 currentTarget = NULL; 00123 } 00124 } 00125 00126 template <typename Source> TypeWrapper(Source source) { 00127 if (sizeof(TargetAdapter<Source>) <= internalTargetSize && 00128 alignment_of<TargetAdapter<Source> >::value <= 00129 alignment_of<TargetStorage>::value) { 00130 new (internalTarget) TargetAdapter<Source>(source); 00131 currentTarget = internalTarget; 00132 } else { 00133 currentTarget = new TargetAdapter<Source>(source); 00134 } 00135 } 00136 00137 ~TypeWrapper() { 00138 if (currentTarget == internalTarget) { 00139 currentTarget->~Target(); 00140 } else { 00141 delete currentTarget; 00142 } 00143 } 00144 00145 const TypeWrapper & operator=(const TypeWrapper & rhs) { 00146 TypeWrapper(rhs).swap(*this); 00147 return *this; 00148 } 00149 00150 template <typename Source> const TypeWrapper & operator=(Source source) { 00151 TypeWrapper(source).swap(*this); 00152 return *this; 00153 } 00154 00155 void clear() { TypeWrapper().swap(*this); } 00156 00157 void swap(TypeWrapper & other) { 00158 if (this == &other) { 00159 return; 00160 } 00161 00162 if (currentTarget == internalTarget && 00163 other.currentTarget == other.internalTarget) { 00164 TargetStorage temp; 00165 currentTarget->clone(temp); 00166 currentTarget->~Target(); 00167 currentTarget = NULL; 00168 other.currentTarget->clone(internalTarget); 00169 other.currentTarget->~Target(); 00170 other.currentTarget = NULL; 00171 currentTarget = internalTarget; 00172 temp->clone(other.internalTarget); 00173 temp->~Target(); 00174 other.currentTarget = other.internalTarget; 00175 } else if (currentTarget == internalTarget) { 00176 currentTarget->clone(other.internalTarget); 00177 currentTarget->~Target(); 00178 currentTarget = other.currentTarget; 00179 other.currentTarget = other.internalTarget; 00180 } else if (other.currentTarget == other.internalTarget) { 00181 other.currentTarget->clone(internalTarget); 00182 other.currentTarget->~Target(); 00183 other.currentTarget = currentTarget; 00184 currentTarget = internalTarget; 00185 } else { 00186 using std::swap; 00187 swap(currentTarget, other.currentTarget); 00188 } 00189 } 00190 00191 const Target * target() const { return currentTarget; } 00192 00193 private: 00194 TargetStorage internalTarget; 00195 Target * currentTarget; 00196 }; 00197 00198 // TypeWrapper specialization with no internal storage space. 00199 template <typename Target, template <typename> class TargetAdapter> 00200 class TypeWrapper<Target, TargetAdapter, 0> { 00201 public: 00202 TypeWrapper() : currentTarget(NULL) {} 00203 00204 TypeWrapper(const TypeWrapper & other) { 00205 if (other.currentTarget) { 00206 currentTarget = other.currentTarget->clone(); 00207 } else { 00208 currentTarget = NULL; 00209 } 00210 } 00211 00212 template <typename Source> 00213 TypeWrapper(Source source) 00214 : currentTarget(new TargetAdapter<Source>(source)) {} 00215 00216 ~TypeWrapper() { delete currentTarget; } 00217 00218 const TypeWrapper & operator=(const TypeWrapper & rhs) { 00219 TypeWrapper(rhs).swap(*this); 00220 return *this; 00221 } 00222 00223 template <typename Source> const TypeWrapper & operator=(Source source) { 00224 TypeWrapper(source).swap(*this); 00225 return *this; 00226 } 00227 00228 void clear() { TypeWrapper().swap(*this); } 00229 00230 void swap(TypeWrapper & other) { 00231 using std::swap; 00232 swap(currentTarget, other.currentTarget); 00233 } 00234 00235 const Target * target() const { return currentTarget; } 00236 00237 private: 00238 Target * currentTarget; 00239 }; 00240 00241 } // namespace detail 00242 00243 // Function wrapper similar to std::function for 0-3 argument functions. 00244 template <typename> class Function; 00245 00246 // Function implementation for zero argument functions. 00247 template <typename ResultType> class Function<ResultType()> { 00248 public: 00249 typedef ResultType result_type; 00250 00251 Function(ResultType (*func)() = NULL) : callableWrapper() { 00252 if (func) { 00253 callableWrapper = func; 00254 } 00255 } 00256 00257 template <typename F> Function(F func) : callableWrapper(func) {} 00258 00259 const Function & operator=(ResultType (*func)()) { 00260 if (func) { 00261 callableWrapper = func; 00262 } else { 00263 callableWrapper.clear(); 00264 } 00265 return *this; 00266 } 00267 00268 template <typename F> const Function & operator=(F func) { 00269 callableWrapper = func; 00270 return *this; 00271 } 00272 00273 void swap(Function & other) { callableWrapper.swap(other.callableWrapper); } 00274 00275 operator SafeBool() const { 00276 return makeSafeBool(callableWrapper.target() != NULL); 00277 } 00278 00279 ResultType operator()() const { 00280 return callableWrapper.target() ? callableWrapper.target()->invoke() 00281 : ResultType(); 00282 } 00283 00284 private: 00285 class Callable { 00286 public: 00287 virtual ~Callable() {} 00288 virtual ResultType invoke() const = 0; 00289 virtual Callable * clone() const = 0; 00290 virtual void clone(void * buffer) const = 0; 00291 }; 00292 00293 template <typename F> class CallableAdapter : public Callable { 00294 public: 00295 CallableAdapter(F func) : func(func) {} 00296 00297 virtual ResultType invoke() const { return func(); } 00298 00299 virtual Callable * clone() const { return new CallableAdapter(*this); } 00300 00301 virtual void clone(void * buffer) const { 00302 new (buffer) CallableAdapter(*this); 00303 } 00304 00305 private: 00306 F func; 00307 }; 00308 00309 detail::TypeWrapper<Callable, CallableAdapter> callableWrapper; 00310 }; 00311 00312 template <typename ResultType> 00313 inline void swap(Function<ResultType()> & lhs, Function<ResultType()> & rhs) { 00314 lhs.swap(rhs); 00315 } 00316 00317 // Function implementation for one argument functions. 00318 template <typename ArgumentType, typename ResultType> 00319 class Function<ResultType(ArgumentType)> { 00320 public: 00321 typedef ArgumentType argument_type; 00322 typedef ResultType result_type; 00323 00324 Function(ResultType (*func)(ArgumentType) = NULL) : callableWrapper() { 00325 if (func) { 00326 callableWrapper = func; 00327 } 00328 } 00329 00330 template <typename F> Function(F func) : callableWrapper(func) {} 00331 00332 const Function & operator=(ResultType (*func)(ArgumentType)) { 00333 if (func) { 00334 callableWrapper = func; 00335 } else { 00336 callableWrapper.clear(); 00337 } 00338 return *this; 00339 } 00340 00341 template <typename F> const Function & operator=(F func) { 00342 callableWrapper = func; 00343 return *this; 00344 } 00345 00346 void swap(Function & other) { callableWrapper.swap(other.callableWrapper); } 00347 00348 operator SafeBool() const { 00349 return makeSafeBool(callableWrapper.target() != NULL); 00350 } 00351 00352 ResultType operator()(ArgumentType arg) const { 00353 return callableWrapper.target() ? callableWrapper.target()->invoke(arg) 00354 : ResultType(); 00355 } 00356 00357 private: 00358 class Callable { 00359 public: 00360 virtual ~Callable() {} 00361 virtual ResultType invoke(ArgumentType) const = 0; 00362 virtual Callable * clone() const = 0; 00363 virtual void clone(void * buffer) const = 0; 00364 }; 00365 00366 template <typename F> class CallableAdapter : public Callable { 00367 public: 00368 CallableAdapter(F func) : func(func) {} 00369 00370 virtual ResultType invoke(ArgumentType arg) const { return func(arg); } 00371 00372 virtual Callable * clone() const { return new CallableAdapter(*this); } 00373 00374 virtual void clone(void * buffer) const { 00375 new (buffer) CallableAdapter(*this); 00376 } 00377 00378 private: 00379 F func; 00380 }; 00381 00382 detail::TypeWrapper<Callable, CallableAdapter> callableWrapper; 00383 }; 00384 00385 template <typename ArgumentType, typename ResultType> 00386 inline void swap(Function<ResultType(ArgumentType)> & lhs, 00387 Function<ResultType(ArgumentType)> & rhs) { 00388 lhs.swap(rhs); 00389 } 00390 00391 // Function implementation for two argument functions. 00392 template <typename FirstArgumentType, typename SecondArgumentType, 00393 typename ResultType> 00394 class Function<ResultType(FirstArgumentType, SecondArgumentType)> { 00395 public: 00396 typedef FirstArgumentType first_argument_type; 00397 typedef SecondArgumentType second_argument_type; 00398 typedef ResultType result_type; 00399 00400 Function(ResultType (*func)(FirstArgumentType, SecondArgumentType) = NULL) 00401 : callableWrapper() { 00402 if (func) { 00403 callableWrapper = func; 00404 } 00405 } 00406 00407 template <typename F> Function(F func) : callableWrapper(func) {} 00408 00409 const Function & operator=(ResultType (*func)(FirstArgumentType, 00410 SecondArgumentType)) { 00411 if (func) { 00412 callableWrapper = func; 00413 } else { 00414 callableWrapper.clear(); 00415 } 00416 return *this; 00417 } 00418 00419 template <typename F> const Function & operator=(F func) { 00420 callableWrapper = func; 00421 return *this; 00422 } 00423 00424 void swap(Function & other) { callableWrapper.swap(other.callableWrapper); } 00425 00426 operator SafeBool() const { 00427 return makeSafeBool(callableWrapper.target() != NULL); 00428 } 00429 00430 ResultType operator()(FirstArgumentType arg1, SecondArgumentType arg2) const { 00431 return callableWrapper.target() 00432 ? callableWrapper.target()->invoke(arg1, arg2) 00433 : ResultType(); 00434 } 00435 00436 private: 00437 class Callable { 00438 public: 00439 virtual ~Callable() {} 00440 virtual ResultType invoke(FirstArgumentType, SecondArgumentType) const = 0; 00441 virtual Callable * clone() const = 0; 00442 virtual void clone(void * buffer) const = 0; 00443 }; 00444 00445 template <typename F> class CallableAdapter : public Callable { 00446 public: 00447 CallableAdapter(F func) : func(func) {} 00448 00449 virtual ResultType invoke(FirstArgumentType arg1, 00450 SecondArgumentType arg2) const { 00451 return func(arg1, arg2); 00452 } 00453 00454 virtual Callable * clone() const { return new CallableAdapter(*this); } 00455 00456 virtual void clone(void * buffer) const { 00457 new (buffer) CallableAdapter(*this); 00458 } 00459 00460 private: 00461 F func; 00462 }; 00463 00464 detail::TypeWrapper<Callable, CallableAdapter> callableWrapper; 00465 }; 00466 00467 template <typename FirstArgumentType, typename SecondArgumentType, 00468 typename ResultType> 00469 inline void 00470 swap(Function<ResultType(FirstArgumentType, SecondArgumentType)> & lhs, 00471 Function<ResultType(FirstArgumentType, SecondArgumentType)> & rhs) { 00472 lhs.swap(rhs); 00473 } 00474 00475 // Function implementation for three argument functions. 00476 template <typename FirstArgumentType, typename SecondArgumentType, 00477 typename ThirdArgumentType, typename ResultType> 00478 class Function<ResultType(FirstArgumentType, SecondArgumentType, 00479 ThirdArgumentType)> { 00480 public: 00481 typedef ResultType result_type; 00482 00483 Function(ResultType (*func)(FirstArgumentType, SecondArgumentType, 00484 ThirdArgumentType) = NULL) 00485 : callableWrapper() { 00486 if (func) { 00487 callableWrapper = func; 00488 } 00489 } 00490 00491 template <typename F> Function(F func) : callableWrapper(func) {} 00492 00493 const Function & operator=(ResultType (*func)(FirstArgumentType, 00494 SecondArgumentType, 00495 ThirdArgumentType)) { 00496 if (func) { 00497 callableWrapper = func; 00498 } else { 00499 callableWrapper.clear(); 00500 } 00501 return *this; 00502 } 00503 00504 template <typename F> const Function & operator=(F func) { 00505 callableWrapper = func; 00506 return *this; 00507 } 00508 00509 void swap(Function & other) { callableWrapper.swap(other.callableWrapper); } 00510 00511 operator SafeBool() const { 00512 return makeSafeBool(callableWrapper.target() != NULL); 00513 } 00514 00515 ResultType operator()(FirstArgumentType arg1, SecondArgumentType arg2, 00516 ThirdArgumentType arg3) const { 00517 return callableWrapper.target() 00518 ? callableWrapper.target()->invoke(arg1, arg2, arg3) 00519 : ResultType(); 00520 } 00521 00522 private: 00523 class Callable { 00524 public: 00525 virtual ~Callable() {} 00526 virtual ResultType invoke(FirstArgumentType, SecondArgumentType, 00527 ThirdArgumentType) const = 0; 00528 virtual Callable * clone() const = 0; 00529 virtual void clone(void * buffer) const = 0; 00530 }; 00531 00532 template <typename F> class CallableAdapter : public Callable { 00533 public: 00534 CallableAdapter(F func) : func(func) {} 00535 00536 virtual ResultType invoke(FirstArgumentType arg1, SecondArgumentType arg2, 00537 ThirdArgumentType arg3) const { 00538 return func(arg1, arg2, arg3); 00539 } 00540 00541 virtual Callable * clone() const { return new CallableAdapter(*this); } 00542 00543 virtual void clone(void * buffer) const { 00544 new (buffer) CallableAdapter(*this); 00545 } 00546 00547 private: 00548 F func; 00549 }; 00550 00551 detail::TypeWrapper<Callable, CallableAdapter> callableWrapper; 00552 }; 00553 00554 template <typename FirstArgumentType, typename SecondArgumentType, 00555 typename ThirdArgumentType, typename ResultType> 00556 inline void swap(Function<ResultType(FirstArgumentType, SecondArgumentType, 00557 ThirdArgumentType)> & lhs, 00558 Function<ResultType(FirstArgumentType, SecondArgumentType, 00559 ThirdArgumentType)> & rhs) { 00560 lhs.swap(rhs); 00561 } 00562 00563 } // namespace MaximInterface 00564 00565 #endif
Generated on Tue Jul 12 2022 23:29:45 by
1.7.2