| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // ====================================================================== | ||
| 2 | // \title Os/MutexInterface.hpp | ||
| 3 | // \brief Os::MutexHandle, Os::MutexInterface, and Os::ScopeLock definitions | ||
| 4 | // ====================================================================== | ||
| 5 | #ifndef OS_MUTEXINTERFACE_HPP_ | ||
| 6 | #define OS_MUTEXINTERFACE_HPP_ | ||
| 7 | |||
| 8 | #include <Fw/FPrimeBasicTypes.hpp> | ||
| 9 | #include <Fw/Types/Assert.hpp> | ||
| 10 | #include <Os/Os.hpp> | ||
| 11 | #include "config/OsSelection.hpp" // defines Os::Mutex alias and OS_MUTEX_HEADER consumed by Os/Mutex.hpp; do not remove | ||
| 12 | |||
| 13 | namespace Os { | ||
| 14 | |||
| 15 | struct MutexHandle {}; | ||
| 16 | |||
| 17 | class MutexInterface { | ||
| 18 | public: | ||
| 19 | enum Status { | ||
| 20 | OP_OK, //!< Operation was successful | ||
| 21 | ERROR_BUSY, //!< Mutex is busy | ||
| 22 | ERROR_DEADLOCK, //!< Deadlock condition detected | ||
| 23 | NOT_SUPPORTED, //!< Mutex does not support operation | ||
| 24 | ERROR_OTHER //!< All other errors | ||
| 25 | }; | ||
| 26 | |||
| 27 | //! \brief default constructor | ||
| 28 | 20120 | MutexInterface() = default; | |
| 29 | |||
| 30 | //! \brief default virtual destructor | ||
| 31 | 40240 | virtual ~MutexInterface() = default; | |
| 32 | |||
| 33 | //! \brief copy constructor is forbidden | ||
| 34 | MutexInterface(const MutexInterface& other) = delete; | ||
| 35 | |||
| 36 | //! \brief copy constructor is forbidden | ||
| 37 | MutexInterface(const MutexInterface* other) = delete; | ||
| 38 | |||
| 39 | //! \brief assignment operator is forbidden | ||
| 40 | MutexInterface& operator=(const MutexInterface& other) = delete; | ||
| 41 | |||
| 42 | //! \brief return the underlying mutex handle (implementation specific) | ||
| 43 | //! \return internal mutex handle representation | ||
| 44 | virtual MutexHandle* getHandle() = 0; | ||
| 45 | |||
| 46 | //! \brief provide a pointer to a Mutex delegate object | ||
| 47 | static MutexInterface* getDelegate(MutexHandleStorage& aligned_new_memory); | ||
| 48 | |||
| 49 | // ------------------------------------------------------------------ | ||
| 50 | // Mutex operations to be implemented by an OSAL implementation | ||
| 51 | // ------------------------------------------------------------------ | ||
| 52 | |||
| 53 | virtual Status take() = 0; //!< lock the mutex return status | ||
| 54 | virtual Status release() = 0; //!< unlock the mutex return status | ||
| 55 | |||
| 56 | // ------------------------------------------------------------------ | ||
| 57 | // Common (non-virtual) functions built on top of take()/release(). | ||
| 58 | // Defined inline on the interface (per fprime#5249) so they are available | ||
| 59 | // regardless of which implementation Os::Mutex is configured to be, and so | ||
| 60 | // that under compile-time selection the call site can devirtualize take()/ | ||
| 61 | // release() and inline the whole acquisition without relying on LTO. | ||
| 62 | // ------------------------------------------------------------------ | ||
| 63 | |||
| 64 | //! \brief lock the mutex and assert success | ||
| 65 | 13165422 | void lock() { | |
| 66 | 13165422 | const Status status = this->take(); | |
| 67 | 13471201 | FW_ASSERT(status == Status::OP_OK, | |
| 68 | static_cast<FwAssertArgType>(reinterpret_cast<PlatformPointerCastType>(this)), status); | ||
| 69 | 13471201 | } | |
| 70 | |||
| 71 | //! \brief unlock the mutex and assert success | ||
| 72 | 14747858 | void unLock() { | |
| 73 | 14747858 | const Status status = this->release(); | |
| 74 | 12960915 | FW_ASSERT(status == Status::OP_OK, | |
| 75 | static_cast<FwAssertArgType>(reinterpret_cast<PlatformPointerCastType>(this)), status); | ||
| 76 | 12960915 | } | |
| 77 | |||
| 78 | //! \brief alias for unLock to meet BasicLockable requirements | ||
| 79 | 12598589 | void unlock() { this->unLock(); } | |
| 80 | }; | ||
| 81 | |||
| 82 | //! \brief locks a mutex within the current scope | ||
| 83 | //! | ||
| 84 | //! The scope lock will lock the associated mutex immediately and will ensure the mutex is unlock when the scope lock | ||
| 85 | //! is destroyed. | ||
| 86 | //! | ||
| 87 | //! \warning it is unadvisable to dynamically allocate ScopeLock as this violates the implied usage. | ||
| 88 | class ScopeLock { | ||
| 89 | public: | ||
| 90 | //! \brief construct the scope lock | ||
| 91 | //! | ||
| 92 | //! Will lock the supplied mutex and will unlock the mutex when this object goes out of scope. | ||
| 93 | //! \param mutex | ||
| 94 | 862568 | explicit ScopeLock(MutexInterface& mutex) : m_mutex(mutex) { this->m_mutex.lock(); } | |
| 95 | |||
| 96 | //!\brief unlock the scoped mutex | ||
| 97 | 862568 | ~ScopeLock() { this->m_mutex.unLock(); } | |
| 98 | |||
| 99 | //! \brief copy constructor is forbidden | ||
| 100 | ScopeLock(const ScopeLock& other) = delete; | ||
| 101 | |||
| 102 | //! \brief copy constructor is forbidden | ||
| 103 | ScopeLock(const ScopeLock* other) = delete; | ||
| 104 | |||
| 105 | //! \brief assignment operator is forbidden | ||
| 106 | ScopeLock& operator=(const ScopeLock& other) = delete; | ||
| 107 | |||
| 108 | private: | ||
| 109 | MutexInterface& m_mutex; //!< Stores the mutex reference | ||
| 110 | }; | ||
| 111 | |||
| 112 | } // namespace Os | ||
| 113 | |||
| 114 | #endif // OS_MUTEXINTERFACE_HPP_ | ||
| 115 |