µOS++ IIIe Reference 7.0.0
The third edition of µOS++, a POSIX inspired open source framework, written in C++
Loading...
Searching...
No Matches
os::rtos::internal::waiting_threads_list Class Reference

Priority ordered list of threads. More...

#include <os-lists.h>

+ Inheritance diagram for os::rtos::internal::waiting_threads_list:

Public Types

Types and constants
using iterator = utils::double_list_iterator< thread, waiting_thread_node, &waiting_thread_node::thread_ >
 Iterator over the list threads.
 

Public Member Functions

Constructors & Destructor
 waiting_threads_list ()
 Construct a list of waiting threads.
 
 ~waiting_threads_list ()
 Destruct the list.
 
Public Member Functions
void link (waiting_thread_node &node)
 Add a new thread node to the list.
 
volatile waiting_thread_nodehead (void) const
 Get list head.
 
bool resume_one (void)
 Wake-up one thread (the oldest with the highest priority)
 
void resume_all (void)
 Wake-up all threads in the list.
 
iterator begin () const
 Iterator begin.
 
iterator end () const
 Iterator begin.
 
Public Member Functions
bool uninitialized (void) const
 Check if the list is uninitialised.
 
void clear (void)
 Clear the list.
 
bool empty (void) const
 Check if the list is empty.
 
volatile static_double_list_links * tail (void) const
 Get the list tail.
 

Protected Member Functions

Private Member Functions
void insert_after (static_double_list_links &node, static_double_list_links *after)
 Insert a new node after existing node.
 

Protected Attributes

Private Member Variables
static_double_list_links head_
 A list node used to point to head and tail.
 

Detailed Description

There are at least two strategies:

  • keep the list ordered by priorities and have the top node easily accessible the head
  • preserve the insertion order and perform a full list traversal to determine the top node.

The first strategy requires a partial list traverse with each insert, to find the place to insert the node, but makes retrieving the top priority node trivial, by a single access to the list head.

The second strategy might minimise the overall processing time, but always requires a full list traversal to determine the top priority node.

On the other hand, typical waiting lists contain only one element, and in this case there is no distinction. Mutex objects occasionally might have two entries (and rarely more). Condition variables might also have several waiting threads, the number is usually small. In these cases, the distinction between the two strategies is also minimal.

In the rare cases when the waiting list is large, the first strategy favours top node retrieval, possibly improving the response time, and is thus preferred.

Definition at line 542 of file os-lists.h.

Member Typedef Documentation

◆ iterator

Constructor & Destructor Documentation

◆ waiting_threads_list()

os::rtos::internal::waiting_threads_list::waiting_threads_list ( )
inline

The initial list status is empty.

Definition at line 916 of file os-lists.h.

917 {
918 }

◆ ~waiting_threads_list()

os::rtos::internal::waiting_threads_list::~waiting_threads_list ( )
inline

Definition at line 920 of file os-lists.h.

921 {
922 }

Member Function Documentation

◆ begin()

waiting_threads_list::iterator os::rtos::internal::waiting_threads_list::begin ( ) const
inline
Returns
An iterator positioned at the first element.

Definition at line 937 of file os-lists.h.

938 {
939 return iterator{
941 head_.next ())
942 };
943 }
utils::double_list_iterator< thread, waiting_thread_node, &waiting_thread_node::thread_ > iterator
Iterator over the list threads.
Definition os-lists.h:555
N * iterator_pointer
Type of reference to the iterator internal pointer.
Definition lists.h:234
static_double_list_links head_
A list node used to point to head and tail.
Definition lists.h:473

References os::utils::static_double_list::head_, and os::utils::static_double_list_links::next().

◆ clear()

void os::utils::static_double_list::clear ( void  )
inherited
Parameters
None.
Returns
Nothing.

Initialise the mandatory node with links to itself.

Definition at line 108 of file lists.cpp.

109 {
110#pragma GCC diagnostic push
111#if defined(__clang__)
112#elif defined(__GNUC__)
113#pragma GCC diagnostic ignored "-Wuseless-cast"
114#endif
115 head_.next (const_cast<static_double_list_links*> (&head_));
116 head_.prev (const_cast<static_double_list_links*> (&head_));
117#pragma GCC diagnostic pop
118 }

References os::utils::static_double_list::head_, os::utils::static_double_list_links::next(), and os::utils::static_double_list_links::prev().

Referenced by os::utils::double_list::double_list(), os::rtos::internal::ready_threads_list::link(), and os::rtos::internal::terminated_threads_list::link().

◆ empty()

bool os::utils::static_double_list::empty ( void  ) const
inlineinherited
Parameters
None.
Return values
trueThe list has no nodes.
falseThe list has at least one node.

Definition at line 1001 of file lists.h.

1002 {
1003 // If it points to itself, it is empty.
1004 return (head_.next () == &head_) || (head_.next () == nullptr);
1005 }

References os::utils::static_double_list::head_, and os::utils::static_double_list_links::next().

Referenced by os::utils::double_list::~double_list(), os::rtos::internal::clock_timestamps_list::check_timestamp(), os::rtos::internal::clock_timestamps_list::link(), os::rtos::internal::ready_threads_list::link(), link(), resume_one(), and os::rtos::internal::ready_threads_list::unlink_head().

◆ end()

waiting_threads_list::iterator os::rtos::internal::waiting_threads_list::end ( ) const
inline
Returns
An iterator positioned after the last element.

Definition at line 946 of file os-lists.h.

947 {
948 return iterator{
950 const_cast<utils::static_double_list_links*> (&head_))
951 };
952 }

References os::utils::static_double_list::head_.

◆ head()

volatile waiting_thread_node * os::rtos::internal::waiting_threads_list::head ( void  ) const
inline
Parameters
None.
Returns
Casted pointer to head node.

Definition at line 925 of file os-lists.h.

926 {
927 return static_cast<volatile waiting_thread_node*> (
928 double_list::head ());
929 }

Referenced by link(), and resume_one().

◆ insert_after()

void os::utils::static_double_list::insert_after ( static_double_list_links node,
static_double_list_links after 
)
protectedinherited
Parameters
nodeReference to node to insert.
afterReference to existing node.
Returns
Nothing.

Definition at line 121 of file lists.cpp.

123 {
124#if defined(OS_TRACE_UTILS_LISTS)
125 trace::printf ("%s() n=%p after %p\n", __func__, &node, after);
126#endif
127
128 // Unlinked nodes must have both pointers null.
129 // If not, most probably the node was already linked.
130 // Or the memory is corrupted.
131 assert (node.prev () == nullptr);
132 assert (node.next () == nullptr);
133
134 // The `after` node must be linked. Only the `next` pointer is
135 // tested, since only it is used.
136 assert (after->next () != nullptr);
137
138 // Make the new node point to its neighbours.
139 node.prev (after);
140 node.next (after->next ());
141
142 // Make the neighbours point to the node. The order is important.
143 after->next ()->prev (&node);
144 after->next (&node);
145 }
int printf(const char *format,...)
Write a formatted string to the trace device.
Definition trace.cpp:59

References os::utils::static_double_list_links::next(), os::utils::static_double_list_links::prev(), and os::trace::printf().

Referenced by os::rtos::internal::thread_children_list::link(), os::rtos::internal::clock_timestamps_list::link(), os::rtos::internal::ready_threads_list::link(), link(), and os::rtos::internal::terminated_threads_list::link().

◆ link()

void os::rtos::internal::waiting_threads_list::link ( waiting_thread_node node)
Parameters
[in]nodeReference to a list node.
Returns
Nothing.

Based on priority, the node is inserted

  • at the end of the list,
  • at the beginning of the list,
  • in the middle of the list, which requires a partial list traversal (done from the end).

To satisfy the circular double linked list requirements, an empty list still contains the head node with references to itself.

Definition at line 194 of file os-lists.cpp.

195 {
196 thread::priority_t prio = node.thread_->priority ();
197
198 waiting_thread_node* after = static_cast<waiting_thread_node*> (
199 const_cast<utils::static_double_list_links*> (tail ()));
200
201 if (empty ())
202 {
203 // Insert at the end of the list.
204#if defined(OS_TRACE_RTOS_LISTS)
205 trace::printf ("wait %s() empty +%u\n", __func__, prio);
206#endif
207 }
208 else if (prio <= after->thread_->priority ())
209 {
210 // Insert at the end of the list.
211#if defined(OS_TRACE_RTOS_LISTS)
212 trace::printf ("wait %s() back %u +%u \n", __func__,
213 after->thread_->priority (), prio);
214#endif
215 }
216 else if (prio > head ()->thread_->priority ())
217 {
218#pragma GCC diagnostic push
219#if defined(__clang__)
220#elif defined(__GNUC__)
221#pragma GCC diagnostic ignored "-Wuseless-cast"
222#endif
223 // Insert at the beginning of the list.
224 after = static_cast<waiting_thread_node*> (
225 const_cast<utils::static_double_list_links*> (&head_));
226#pragma GCC diagnostic pop
227
228#if defined(OS_TRACE_RTOS_LISTS)
229 trace::printf ("wait %s() front +%u %u \n", __func__, prio,
230 head ()->thread_->priority ());
231#endif
232 }
233 else
234 {
235#pragma GCC diagnostic push
236#if defined(__clang__)
237#elif defined(__GNUC__)
238#pragma GCC diagnostic ignored "-Wuseless-cast"
239#endif
240 // Insert in the middle of the list.
241 // The loop is guaranteed to terminate, and not hit the head.
242 // The weight is relatively small, priority() is not heavy.
243 while (prio > after->thread_->priority ())
244 {
245 after = static_cast<waiting_thread_node*> (
246 const_cast<utils::static_double_list_links*> (
247 after->prev ()));
248 }
249#pragma GCC diagnostic pop
250
251#if defined(OS_TRACE_RTOS_LISTS)
252 trace::printf ("wait %s() middle %u +%u \n", __func__,
253 after->thread_->priority (), prio);
254#endif
255 }
256
257 insert_after (node, after);
258 }
volatile waiting_thread_node * head(void) const
Get list head.
Definition os-lists.h:925
void insert_after(static_double_list_links &node, static_double_list_links *after)
Insert a new node after existing node.
Definition lists.cpp:121
bool empty(void) const
Check if the list is empty.
Definition lists.h:1001
volatile static_double_list_links * tail(void) const
Get the list tail.
Definition lists.h:1014
uint8_t priority_t
Type of variables holding thread priorities.
Definition os-thread.h:271

References os::utils::static_double_list::empty(), head(), os::utils::static_double_list::head_, os::utils::static_double_list::insert_after(), os::utils::static_double_list_links::prev(), os::trace::printf(), os::rtos::thread::priority(), os::utils::static_double_list::tail(), and os::rtos::internal::waiting_thread_node::thread_.

◆ resume_all()

void os::rtos::internal::waiting_threads_list::resume_all ( void  )
Parameters
None.
Returns
Nothing.

Definition at line 303 of file os-lists.cpp.

304 {
305 while (resume_one ())
306 ;
307 }
bool resume_one(void)
Wake-up one thread (the oldest with the highest priority)
Definition os-lists.cpp:266

References resume_one().

◆ resume_one()

bool os::rtos::internal::waiting_threads_list::resume_one ( void  )
Parameters
None.
Return values
trueThe list may have further entries.
falseThe list is empty.

Atomically get the top thread from the list, remove the node and wake-up the thread.

Definition at line 266 of file os-lists.cpp.

267 {
268 thread* th;
269 {
270 // ----- Enter critical section -------------------------------------
271 interrupts::critical_section ics;
272
273 // If the list is empty, silently return.
274 if (empty ())
275 {
276 return false;
277 }
278
279 // The top priority is to remove the entry from the list
280 // so that subsequent wakeups to address different threads.
281 th = head ()->thread_;
282 const_cast<waiting_thread_node*> (head ())->unlink ();
283 // ----- Exit critical section --------------------------------------
284 }
285 assert (th != nullptr);
286
287 thread::state_t state = th->state ();
288 if (state != thread::state::destroyed)
289 {
290 th->resume ();
291 }
292 else
293 {
294#if defined(OS_TRACE_RTOS_LISTS)
295 trace::printf ("%s() gone \n", __func__);
296#endif
297 }
298
299 return true;
300 }
rtos::thread * thread_
Pointer to waiting thread.
Definition os-lists.h:107
uint8_t state_t
Type of variables holding thread states.
Definition os-thread.h:357
Standard thread.
int unlink(const char *name)
@ destroyed
Terminated and resources (like stack) released.
Definition os-thread.h:398

References os::rtos::thread::state::destroyed, os::utils::static_double_list::empty(), head(), os::trace::printf(), os::rtos::thread::resume(), os::rtos::thread::state(), os::rtos::internal::waiting_thread_node::thread_, and unlink().

Referenced by resume_all().

◆ tail()

volatile static_double_list_links * os::utils::static_double_list::tail ( void  ) const
inlineinherited

◆ uninitialized()

bool os::utils::static_double_list::uninitialized ( void  ) const
inlineinherited
Parameters
None.
Return values
trueThe list was not initialised.
falseThe list was initialised.

Definition at line 994 of file lists.h.

995 {
996 // If it points to nowhere, it is not yet initialised.
997 return (head_.prev () == nullptr);
998 }

References os::utils::static_double_list::head_, and os::utils::static_double_list_links::prev().

Member Data Documentation

◆ head_


The documentation for this class was generated from the following files: