| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // ====================================================================== | ||
| 2 | // \title Os/Delegate.hpp | ||
| 3 | // \brief helper functions to ease correct getDelegate implementations | ||
| 4 | // ====================================================================== | ||
| 5 | #include <new> | ||
| 6 | #include <type_traits> | ||
| 7 | #include "Fw/Types/Assert.hpp" | ||
| 8 | #include "Os/Os.hpp" | ||
| 9 | #ifndef OS_DELEGATE_HPP_ | ||
| 10 | #define OS_DELEGATE_HPP_ | ||
| 11 | namespace Os { | ||
| 12 | namespace Delegate { | ||
| 13 | |||
| 14 | //! \brief Make a delegate of type Interface using Implementation without copy-constructor support (generic function) | ||
| 15 | //! | ||
| 16 | //! This function is a generic implementation of the `getDelegate` functions provided for each function within Os. This | ||
| 17 | //! is templated over two types: Interface (e.g. TaskInterface) the interface the delegate supports, and Implementation | ||
| 18 | //! the implementation of the interface. This function takes care of the critical requirements of the getDelegate | ||
| 19 | //! function: | ||
| 20 | //! 1. Ensure Implementation is derived from Interface | ||
| 21 | //! 2. Ensure Implementation fits within FW_HANDLE_MAX_SIZE | ||
| 22 | //! 3. Ensure Implementation alignment fits within FW_HANDLE_ALIGNMENT | ||
| 23 | //! 4. Performs the correct placement new for normal constructors | ||
| 24 | //! 5. Ensure the returned pointer is not nullptr | ||
| 25 | //! | ||
| 26 | //! Implementors of a `getDelegate` function may use this function by calling it and returning the result. | ||
| 27 | //! | ||
| 28 | //! > Neither Interface nor Implementation is allowed to support copy-constructors | ||
| 29 | //! | ||
| 30 | //! Example: TaskInterface getDelegate (Without Copy-Constructor) | ||
| 31 | //! | ||
| 32 | //! ```c++ | ||
| 33 | //! #include "Os/Delegate.hpp" | ||
| 34 | //! | ||
| 35 | //! namespace Os { | ||
| 36 | //! TaskInterface* TaskInterface::getDelegate(HandleStorage& aligned_new_memory) { | ||
| 37 | //! return Os::Delegate::makeDelegate<TaskInterface, Os::Posix::Task::PosixTask>(aligned_new_memory); | ||
| 38 | //! } | ||
| 39 | //! } | ||
| 40 | //! ``` | ||
| 41 | //! \tparam Interface: interface the delegate supports (e.g. TaskInterface) | ||
| 42 | //! \tparam Implementation: implementation class of the delegate (e.g. PosixTask) | ||
| 43 | //! \param aligned_new_memory: memory to be filled via placement new call | ||
| 44 | //! \return pointer to implementation result of placement new | ||
| 45 | template <class Interface, class Implementation, class StorageType> | ||
| 46 | 30 | inline Interface* makeDelegate(StorageType& aligned_new_memory) { | |
| 47 | // Ensure prerequisites before performing placement new | ||
| 48 | static_assert(std::is_base_of<Interface, Implementation>::value, "Implementation must derive from Interface"); | ||
| 49 | static_assert(sizeof(Implementation) <= sizeof(StorageType), "Handle size not large enough"); | ||
| 50 | static_assert((FW_HANDLE_ALIGNMENT % alignof(Implementation)) == 0, "Handle alignment invalid"); | ||
| 51 | // Placement new the object and ensure non-null result | ||
| 52 |
1/3✓ Branch 3 taken 9 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
30 | Implementation* interface = new (aligned_new_memory) Implementation; |
| 53 | 30 | FW_ASSERT(interface != nullptr); | |
| 54 | 30 | return interface; | |
| 55 | } | ||
| 56 | |||
| 57 | //! \brief Make a delegate of type Interface using Implementation with copy-constructor support (generic function) | ||
| 58 | //! | ||
| 59 | //! This function is a generic implementation of the `getDelegate` functions provided for each function within Os. This | ||
| 60 | //! is templated over two types: Interface (e.g. TaskInterface) the interface the delegate supports, and Implementation | ||
| 61 | //! the implementation of the interface. This function takes care of the critical requirements of the getDelegate | ||
| 62 | //! function: | ||
| 63 | //! 1. Ensure Implementation is derived from Interface | ||
| 64 | //! 2. Ensure Implementation fits within FW_HANDLE_MAX_SIZE | ||
| 65 | //! 3. Ensure Implementation alignment fits within FW_HANDLE_ALIGNMENT | ||
| 66 | //! 4. Performs the correct placement new for normal and copy constructors | ||
| 67 | //! 5. Ensure the returned pointer is not nullptr | ||
| 68 | //! | ||
| 69 | //! Implementors of a `getDelegate` function may use this function by calling it and returning the result. | ||
| 70 | //! | ||
| 71 | //! Example: FileInterface getDelegate Supporting Copy-Constructor | ||
| 72 | //! | ||
| 73 | //! ```c++ | ||
| 74 | //! #include "Os/Delegate.hpp" | ||
| 75 | //! | ||
| 76 | //! namespace Os { | ||
| 77 | //! FileInterface* FileInterface::getDelegate(HandleStorage& aligned_new_memory, const FileInterface* to_copy) { | ||
| 78 | //! return Os::Delegate::makeDelegate<FileInterface, Os::Posix::File::PosixFile>(aligned_new_memory, to_copy); | ||
| 79 | //! } | ||
| 80 | //! } | ||
| 81 | //! ``` | ||
| 82 | //! \tparam Interface: interface the delegate supports (e.g. FileInterface) | ||
| 83 | //! \tparam Implementation: implementation class of the delegate (e.g. PosixFile) | ||
| 84 | //! \param aligned_new_memory: memory to be filled via placement new call | ||
| 85 | //! \return pointer to implementation result of placement new | ||
| 86 | //! \param to_copy: pointer to Interface to be copied by copy constructor | ||
| 87 | //! \return pointer to implementation result of placement new | ||
| 88 | template <class Interface, class Implementation, class StorageType> | ||
| 89 | 29 | inline Interface* makeDelegate(StorageType& aligned_new_memory, const Interface* to_copy) { | |
| 90 | 29 | const Implementation* copy_me = reinterpret_cast<const Implementation*>(to_copy); | |
| 91 | // Ensure prerequisites before performing placement new | ||
| 92 | static_assert(std::is_base_of<Interface, Implementation>::value, "Implementation must derive from Interface"); | ||
| 93 | static_assert(sizeof(Implementation) <= sizeof(aligned_new_memory), "Handle size not large enough"); | ||
| 94 | static_assert((FW_HANDLE_ALIGNMENT % alignof(Implementation)) == 0, "Handle alignment invalid"); | ||
| 95 | // Placement new the object and ensure non-null result | ||
| 96 | 29 | Implementation* interface = nullptr; | |
| 97 |
1/2✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
|
29 | if (to_copy == nullptr) { |
| 98 |
1/3✓ Branch 3 taken 6 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
29 | interface = new (aligned_new_memory) Implementation; |
| 99 | } else { | ||
| 100 | ✗ | interface = new (aligned_new_memory) Implementation(*copy_me); | |
| 101 | } | ||
| 102 | 29 | FW_ASSERT(interface != nullptr); | |
| 103 | 29 | return interface; | |
| 104 | } | ||
| 105 | } // namespace Delegate | ||
| 106 | } // namespace Os | ||
| 107 | #endif | ||
| 108 |