@@ -10786,27 +10786,27 @@ A `thread` that has not been `detach()`ed when it is destroyed terminates the pr
10786
10786
void f() { std::cout << "Hello "; }
10787
10787
10788
10788
struct F {
10789
- void operator()() { std::cout << "parallel world "; }
10789
+ void operator()() { std::cout << "parallel world "; }
10790
10790
};
10791
10791
10792
10792
int main()
10793
10793
{
10794
- std::thread t1{f}; // f() executes in separate thread
10795
- std::thread t2{F()}; // F()() executes in separate thread
10794
+ std::thread t1{f}; // f() executes in separate thread
10795
+ std::thread t2{F()}; // F()() executes in separate thread
10796
10796
} // spot the bugs
10797
10797
10798
10798
##### Example
10799
10799
10800
10800
void f() { std::cout << "Hello "; }
10801
10801
10802
10802
struct F {
10803
- void operator()() { std::cout << "parallel world "; }
10803
+ void operator()() { std::cout << "parallel world "; }
10804
10804
};
10805
10805
10806
10806
int main()
10807
10807
{
10808
- std::thread t1{f}; // f() executes in separate thread
10809
- std::thread t2{F()}; // F()() executes in separate thread
10808
+ std::thread t1{f}; // f() executes in separate thread
10809
+ std::thread t2{F()}; // F()() executes in separate thread
10810
10810
10811
10811
t1.join();
10812
10812
t2.join();
@@ -10992,20 +10992,20 @@ A `wait` without a condition can miss a wakeup or wake up simply to find that th
10992
10992
10993
10993
void thread1()
10994
10994
{
10995
- while (true) {
10996
- // do some work ...
10997
- std::unique_lock<std::mutex> lock(mx);
10998
- cv.notify_one(); // wake other thread
10999
- }
10995
+ while (true) {
10996
+ // do some work ...
10997
+ std::unique_lock<std::mutex> lock(mx);
10998
+ cv.notify_one(); // wake other thread
10999
+ }
11000
11000
}
11001
11001
11002
11002
void thread2()
11003
11003
{
11004
- while (true) {
11005
- std::unique_lock<std::mutex> lock(mx);
11006
- cv.wait(lock); // might block forever
11007
- // do work ...
11008
- }
11004
+ while (true) {
11005
+ std::unique_lock<std::mutex> lock(mx);
11006
+ cv.wait(lock); // might block forever
11007
+ // do work ...
11008
+ }
11009
11009
}
11010
11010
11011
11011
Here, if some other `thread` consumes `thread1`'s notification, `thread2` can wait forever.
@@ -11015,30 +11015,30 @@ Here, if some other `thread` consumes `thread1`'s notification, `thread2` can wa
11015
11015
template<typename T>
11016
11016
class Sync_queue {
11017
11017
public:
11018
- void put(const T& val);
11019
- void put(T&& val);
11020
- void get(T& val);
11018
+ void put(const T& val);
11019
+ void put(T&& val);
11020
+ void get(T& val);
11021
11021
private:
11022
- mutex mtx;
11023
- condition_variable cond; // this controls access
11024
- list<T> q;
11022
+ mutex mtx;
11023
+ condition_variable cond; // this controls access
11024
+ list<T> q;
11025
11025
};
11026
11026
11027
11027
template<typename T>
11028
11028
void Sync_queue<T>::put(const T& val)
11029
11029
{
11030
- lock_guard<mutex> lck(mtx);
11031
- q.push_back(val);
11032
- cond.notify_one();
11030
+ lock_guard<mutex> lck(mtx);
11031
+ q.push_back(val);
11032
+ cond.notify_one();
11033
11033
}
11034
11034
11035
11035
template<typename T>
11036
11036
void Sync_queue<T>::get(T& val)
11037
11037
{
11038
- unique_lock<mutex> lck(mtx);
11039
- cond.wait(lck,[this]{ return !q.empty(); }); // prevent spurious wakeup
11040
- val=q.front();
11041
- q.pop_front();
11038
+ unique_lock<mutex> lck(mtx);
11039
+ cond.wait(lck,[this]{ return !q.empty(); }); // prevent spurious wakeup
11040
+ val=q.front();
11041
+ q.pop_front();
11042
11042
}
11043
11043
11044
11044
Now if the queue is empty when a thread executing `get()` wakes up (e.g., because another thread has gotton to `get()` before it),
@@ -11251,15 +11251,15 @@ It's error-prone and requires expert level knowledge of language features, machi
11251
11251
11252
11252
##### Example, bad
11253
11253
11254
- extern atomic<Link*> head; // the shared head of a linked list
11254
+ extern atomic<Link*> head; // the shared head of a linked list
11255
11255
11256
- Link* nh = new Link(data,nullptr); // make a link ready for insertion
11257
- Link* h = head.load(); // read the shared head of the list
11256
+ Link* nh = new Link(data,nullptr); // make a link ready for insertion
11257
+ Link* h = head.load(); // read the shared head of the list
11258
11258
11259
11259
do {
11260
- if (h->data<=data) break; // if so, insert elsewhere
11261
- nh->next = h; // next element is the previous head
11262
- } while (!head.compare_exchange_weak(h,nh)); // write nh to head or to h
11260
+ if (h->data<=data) break; // if so, insert elsewhere
11261
+ nh->next = h; // next element is the previous head
11262
+ } while (!head.compare_exchange_weak(h,nh)); // write nh to head or to h
11263
11263
11264
11264
Spot the bug.
11265
11265
It would be really hard to find through testing.
0 commit comments