GCC Code Coverage Report


Directory: ./
File: Os/Condition.hpp
Date: 2026-09-03 22:12:29
Exec Total Coverage
Lines: 2 2 100.0%
Functions: 2 2 100.0%
Branches: 0 0 -%

Line Branch Exec Source
1 // ======================================================================
2 // \title Os/Condition.hpp
3 // \brief common function definitions for Os::ConditionVariables
4 // ======================================================================
5 #include "Os/Mutex.hpp"
6 #include "Os/Os.hpp"
7
8 #ifndef OS_CONDITION_HPP_
9 #define OS_CONDITION_HPP_
10
11 namespace Os {
12
13 //! \brief Condition variable handle parent
14 class ConditionVariableHandle {};
15
16 //! \brief interface for condition variables
17 //!
18 //! Condition variables allow a program to block on a condition while atomically releasing an Os::Mutex and atomically
19 //! reacquiring the mutex once the condition has been notified.
20 class ConditionVariableInterface {
21 public:
22 enum Status {
23 OP_OK, //!< Operation was successful
24 ERROR_MUTEX_NOT_HELD, //!< When trying to wait but we don't hold the mutex
25 ERROR_DIFFERENT_MUTEX, //!< When trying to use a different mutex than expected mutex
26 ERROR_NOT_IMPLEMENTED, //!< When trying to use a feature that isn't implemented
27 NOT_SUPPORTED, //!< ConditionVariable does not support operation
28 ERROR_OTHER //!< All other errors
29 };
30
31 //! Default constructor
32 112 ConditionVariableInterface() = default;
33 //! Default destructor
34 224 virtual ~ConditionVariableInterface() = default;
35
36 //! \brief copy constructor is forbidden
37 ConditionVariableInterface(const ConditionVariableInterface& other) = delete;
38
39 //! \brief assignment operator is forbidden
40 virtual ConditionVariableInterface& operator=(const ConditionVariableInterface& other) = delete;
41
42 //! \brief wait on a condition variable
43 //!
44 //! Wait on a condition variable. This function will atomically unlock the provided mutex and block on the condition
45 //! in one step. Blocking will occur until a future `notify` or `notifyAll` call is made to this variable on another
46 //! thread of execution.
47 //!
48 //! \param mutex: mutex to unlock as part of this operation
49 //! \return status of the conditional wait
50 virtual Status pend(Os::Mutex& mutex) = 0;
51
52 //! \brief notify a single waiter on this condition variable
53 //!
54 //! Notify a single waiter on this condition variable. It is not necessary to hold the mutex supplied by the waiters
55 //! and it is advantageous not to hold the lock to prevent immediate re-blocking.
56 virtual void notify() = 0;
57
58 //! \brief notify all waiters on this condition variable
59 //!
60 //! Notify all waiters on this condition variable. It is not necessary to hold the mutex supplied by the waiters
61 //! and it is advantageous not to hold the lock to prevent immediate re-blocking.
62 virtual void notifyAll() = 0;
63
64 //! \brief return the underlying condition variable handle (implementation specific).
65 //! \return internal task handle representation
66 virtual ConditionVariableHandle* getHandle() = 0;
67
68 //! \brief provide a pointer to a Mutex delegate object
69 static ConditionVariableInterface* getDelegate(ConditionVariableHandleStorage& aligned_new_memory);
70 };
71
72 //! \brief condition variable implementation
73 //!
74 //! Condition variables allow a program to block on a condition while atomically releasing an Os::Mutex and atomically
75 //! reacquiring the mutex once the condition has been notified.
76 class ConditionVariable final : public ConditionVariableInterface {
77 public:
78 //! \brief default constructor
79 ConditionVariable();
80
81 //! \brief default virtual destructor
82 ~ConditionVariable() final;
83
84 //! \brief copy constructor is forbidden
85 ConditionVariable(const ConditionVariableInterface& other) = delete;
86
87 //! \brief copy constructor is forbidden
88 ConditionVariable(const ConditionVariableInterface* other) = delete;
89
90 //! \brief assignment operator is forbidden
91 ConditionVariableInterface& operator=(const ConditionVariableInterface& other) override = delete;
92
93 //! \brief wait on a condition variable
94 //!
95 //! Wait on a condition variable. This function will atomically unlock the provided mutex and block on the condition
96 //! in one step. Blocking will occur until a future `notify` or `notifyAll` call is made to this variable on another
97 //! thread of execution. This function delegates to the underlying implementation.
98 //!
99 //! \warning it is invalid to supply a mutex different from those supplied by others
100 //! \warning conditions *must* be rechecked after the condition variable unlocks
101 //! \warning the mutex must be locked by the calling task
102 //!
103 //! \param mutex: mutex to unlock as part of this operation
104 //! \return status of the conditional wait
105 Status pend(Os::Mutex& mutex) override;
106
107 //! \brief wait on a condition variable
108 //!
109 //! Wait on a condition variable. This function will atomically unlock the provided mutex and block on the condition
110 //! in one step. Blocking will occur until a future `notify` or `notifyAll` call is made to this variable on another
111 //! thread of execution. This function delegates to the underlying implementation.
112 //!
113 //! \warning it is invalid to supply a mutex different from those supplied by others
114 //! \warning conditions *must* be rechecked after the condition variable unlocks
115 //! \warning the mutex must be locked by the calling task
116 //!
117 //! \param mutex: mutex to unlock as part of this operation
118 void wait(Os::Mutex& mutex);
119
120 //! \brief notify a single waiter on this condition variable
121 //!
122 //! Notify a single waiter on this condition variable. It is not necessary to hold the mutex supplied by the waiters
123 //! and it is advantageous not to hold the lock to prevent immediate re-blocking. This function delegates to the
124 //! underlying implementation.
125 void notify() override;
126
127 //! \brief notify all waiters on this condition variable
128 //!
129 //! Notify all waiters on this condition variable. It is not necessary to hold the mutex supplied by the waiters
130 //! and it is advantageous not to hold the lock to prevent immediate re-blocking. This function delegates to the
131 //! underlying implementation.
132 void notifyAll() override;
133
134 //! \brief return the underlying condition variable handle (implementation specific). Delegates to implementation.
135 //! \return internal task handle representation
136 ConditionVariableHandle* getHandle() override;
137
138 private:
139 //! Pointer to mutex object previously used
140 Os::Mutex* m_lock = nullptr;
141
142 // This section is used to store the implementation-defined file handle. To Os::File and fprime, this type is
143 // opaque and thus normal allocation cannot be done. Instead, we allow the implementor to store then handle in
144 // the byte-array here and set `handle` to that address for storage.
145 alignas(FW_HANDLE_ALIGNMENT)
146 ConditionVariableHandleStorage m_handle_storage; //!< Storage for aligned FileHandle data
147 ConditionVariableInterface& m_delegate; //!< Delegate for the real implementation
148 };
149 } // namespace Os
150 #endif // OS_CONDITION_HPP_
151