YAHAL
Yet Another Hardware Abstraction Library
Loading...
Searching...
No Matches
condition_variable.h
1// ---------------------------------------------
2// This file is part of
3// _ _ __ _ _ __ __
4// ( \/ ) /__\ ( )_( ) /__\ ( )
5// \ / /(__)\ ) _ ( /(__)\ )(__
6// (__)(__)(__)(_) (_)(__)(__)(____)
7//
8// Yet Another HW Abstraction Library
9// Copyright (C) Andreas Terstegge
10// BSD Licensed (see file LICENSE)
11//
12// ---------------------------------------------
13//
14// Simple condition variable implementation. It
15// relies on a lock_base implementation of a
16// specific HW platform, which is passed in as the
17// template parameter. The condition variable stores
18// the locks in a circular list and uses these to
19// control the waiting tasks.
20//
21#ifndef _CONDITION_VARIABLE_H_
22#define _CONDITION_VARIABLE_H_
23
24#include "circular_list.h"
25#include "mutex.h"
26
27template<typename T>
29public:
30
31 condition_variable() = default;
32
33 void wait(mutex_interface & m) {
34 // create a new element and store task pointer
35 stop_list_elem elem;
36 elem._task = task::currentTask();
37 // store element so we can resume the task later
38 _stop_list_mutex.lock();
39 _stop_list.push_back(&elem);
40 _stop_list_mutex.unlock();
41 // Stop now. We have to suspend this task and
42 // also unlock the mutex m. This operation has
43 // to be atomic, so a critical section is used.
44 task::enterCritical();
45 elem._task->suspend();
46 m.unlock();
47 task::leaveCritical();
48 // Switch to other task
49 task::yield();
50 m.lock();
51 }
52
53 template<typename Predicate>
54 void wait(mutex_interface & m, Predicate p) {
55 while (!p()) wait(m);
56 }
57
58 void notify_one() {
59 _stop_list_mutex.lock();
60 if (_stop_list.getSize()) {
61 stop_list_elem * elem = _stop_list.getHead();
62 _stop_list.remove(elem);
63 elem->_task->resume();
64 }
65 _stop_list_mutex.unlock();
66 // Give the resumed task a chance to run
67 task::yield();
68 }
69
70 void notify_all() {
71 _stop_list_mutex.lock();
72 while (_stop_list.getSize()) {
73 stop_list_elem * elem = _stop_list.getHead();
74 _stop_list.remove(elem);
75 elem->_task->resume();
76 }
77 _stop_list_mutex.unlock();
78 // Give the resumed tasks a chance to run
79 task::yield();
80 }
81
82 // No copy, no assignment
83 condition_variable (const condition_variable &) = delete;
84 condition_variable & operator= (const condition_variable &) = delete;
85
86private:
87
88 struct stop_list_elem {
89 stop_list_elem * _prev;
90 stop_list_elem * _next;
91 bool _linked_in;
92 task * _task;
93 };
94
95 mutex<T> _stop_list_mutex;
97};
98
99#endif // _CONDITION_VARIABLE_H_
Definition mutex.h:27
Definition task.h:39