C++11 std::condition_variable - notify_one() not behaving as expected? - c++11

I don't see this program having any practical usage, but while experimenting with c++ 11 concurrency and conditional_variables I stumbled across something I don't fully understand.
At first I assumed that using notify_one() would allow the program below to work. However, in actuality the program just froze after printing one. When I switched over to using notify_all() the program did what I wanted it to do (print all natural numbers in order). I am sure this question has been asked in various forms already. But my specific question is where in the doc did I read wrong.
I assume notify_one() should work because of the following statement.
If any threads are waiting on *this, calling notify_one unblocks one of the waiting threads.
Looking below only one of the threads will be blocked at a given time, correct?
class natural_number_printer
{
public:
void run()
{
m_odd_thread = std::thread(
std::bind(&natural_number_printer::print_odd_natural_numbers, this));
m_even_thread = std::thread(
std::bind(&natural_number_printer::print_even_natural_numbers, this));
m_odd_thread.join();
m_even_thread.join();
}
private:
std::mutex m_mutex;
std::condition_variable m_condition;
std::thread m_even_thread;
std::thread m_odd_thread;
private:
void print_odd_natural_numbers()
{
for (unsigned int i = 1; i < 100; ++i) {
if (i % 2 == 1) {
std::cout << i << " ";
m_condition.notify_all();
} else {
std::unique_lock<std::mutex> lock(m_mutex);
m_condition.wait(lock);
}
}
}
void print_even_natural_numbers()
{
for (unsigned int i = 1; i < 100; ++i) {
if (i % 2 == 0) {
std::cout << i << " ";
m_condition.notify_all();
} else {
std::unique_lock<std::mutex> lock(m_mutex);
m_condition.wait(lock);
}
}
}
};

The provided code "works" correctly and gets stuck by design. The cause is described in the documentation
The effects of notify_one()/notify_all() and
wait()/wait_for()/wait_until() take place in a single total order, so
it's impossible for notify_one() to, for example, be delayed and
unblock a thread that started waiting just after the call to
notify_one() was made.
The step-by-step logic is
The print_odd_natural_numbers thread is started
The print_even_natural_numbers thread is started also.
The m_condition.notify_all(); line of print_even_natural_numbers is executed before than the print_odd_natural_numbers thread reaches the m_condition.wait(lock); line.
The m_condition.wait(lock); line of print_odd_natural_numbers is executed and the thread gets stuck.
The m_condition.wait(lock); line of print_even_natural_numbers is executed and the thread gets stuck also.

Related

boost::asio::thread_pool - How to cancel workers before work is finished?

OS windows. I would like to create a back-buffer before paint. I want to use boost::asio::thread_pool to increase speed. I need to stop back-buffer creating, if my "input data"(tasks) is updated.
I wrote Test_CreateAndCancel function to simplify test.
class Task
{
public:
virtual void operator()
{
std::cout << "Task started " << std::endl;
DoSomeWork();
std::cout << "Task in progress" << std::endl;
for (int i = 0; i < 15; ++i)
boost::this_thread::sleep_for(boost::chrono::milliseconds(1000));
std::cout << "Task ended" << std::endl;
}
};
using TaskPtr = std::shared_ptr<Task>;
void Test_CreateAndCancel(std::vector<TaskPtr> &tasks)
{
//start back-buffer creating
boost::asio::thread_pool _thread_pool(4);
for (auto task : tasks)
{
boost::asio::post(thread_pool, [task] {
task->operator()();
});
}
// simulate cancel
thread_pool.stop(); // wait untill all threads are finished?
}
vector tasks has 4 items.
Result is: 4 "Task started" "Task in progress" "Task ended"
I am thinking to add custom IsCanceled() checkes in task::operator().
Is there are any other ways to make my tasks cancelable?
How can I implement cancel logic?
I will be grateful for any advices
Thanks
The easiest approach is to add a (probably atomic) variable "please_stop" to your Task and
query it inside the operator() regularly
set it from the outside (another task)
The basic problem is that you cannot cancel an operation that is running in a different task. You can only "ask it politely" to stop working.
boost::thread has an interrupt mechanism (see the link, #sehe posted above). This basically does not do anything different than what I suggested, except it's baked into boost::thread. There are certain "interruption points" that will query the "please stop" state and throw an exception, if it is set.
You have to catch the exception though, otherwise the thread itself will stop and you want only the operation to stop.
So you could do something like this:
class Task {
virtual void operator()()
{
try {
do_something();
boost::this_thread::sleep(boost::chrono::seconds(10000);
}
catch (boost::thread_interrupted&) { //
handle_please_stop_request();
}
}
};
// and later
task_thread.interrupt();
The problem with this approach is that you have to know the thread and you probably want to interrupt not the thread but the operation. Which is why the atomic approach has its charms.
BTW, your example has several problems. The task operation (operator()()) never stops at all. You are creating a task pool for every vector of tasks. I assume these are just artifacts of your example and your real world code is different.
One thing though. I haven't looked into asio::thread_pool yet, but I am missing the boost::asio::work object. Search stackoverflow on how to use the work object.

c++ 11 condition_variable wait spurious wake up is not working

I tried to write a simple producer/consumer by using condition_variable,
include <iostream>
#include <thread>
#include <condition_variable>
#include <mutex>
#include <chrono>
#include <queue>
#include <chrono>
using namespace std;
condition_variable cond_var;
mutex m;
int main()
{
int c = 0;
bool done = false;
cout << boolalpha;
queue<int> goods;
thread producer([&](){
for (int i = 0; i < 10; ++i) {
m.lock();
goods.push(i);
c++;
cout << "produce " << i << endl;
m.unlock();
cond_var.notify_one();
this_thread::sleep_for(chrono::milliseconds(100));
}
done = true;
cout << "producer done." << endl;
cond_var.notify_one();
});
thread consumer([&](){
unique_lock<mutex> lock(m);
while(!done || !goods.empty()){
/*
cond_var.wait(lock, [&goods, &done](){
cout << "spurious wake check" << done <<endl;
return (!goods.empty() || done);
});
*/
while(goods.empty())
{
cout<< "consumer wait" <<endl;
cout<< "consumer owns lock " << lock.owns_lock() <<endl;
cond_var.wait(lock);
}
if (!goods.empty()){
cout << "consume " << goods.front()<<endl;
goods.pop();
c--;
}
}
});
producer.join();
consumer.join();
cout << "Net: " << c << endl;
}
The problem I have now is when the consumer consumes the last item before the producer set done to true, the consumer thread will stuck in
while(goods.empty())
{
cout<< "consumer wait" <<endl;
cout<< "consumer owns lock " << lock.owns_lock() <<endl;
cond_var.wait(lock);
}
My understanding is cond_var.wait(lock) will wake up spuriously and thus exit the while(good.empty()) loop, but it seems not the case?
Spurious wakeups are not a regular occurance which you can rely on to break a loop in the manner you're suggesting. The risk of having a spurious wakeup is an unfortunate side-effect of the current implementations of condition variables which you must account for, but there is no guarantee about when (if ever) you will experience a spurious wakeup.
If you want to ensure that the consumer thread doesn't get stuck waiting for a notify that never comes, you might try using std::condition_variable::wait_for() instead. It takes a duration and will timeout and reaquire the lock if the duration expires. It might be viewed as closer to a busy wait but if the timeout is long enough the implications on performance should be negligible.
As #Karlinde says, and as the name implies, spurious wakeups are not guaranteed to happen. Rather, they will normally not happen at all.
But, even if spurious wakeups would happen, that would not fix your issue: you simply have an infinite loop in your program. Once the producer has stopped, goods.empty() is true and it will never change again. So change the while loop to:
while(!done && goods.empty())
{
...
}
Now it should exit... most of the time. You still have a possible race condition, because in the producer, you set done = true without holding the lock.
If the Producer notifies {cond_var.notify_one();} without any consumer waiting {cond_var.wait(lock);} then the 1'st notification that is sent to the consumer has gone unnoticed.
#tesla1060
"The problem I have now is when the consumer consumes the last item before the producer set done to true, the consumer thread will stuck in" , this is not ture. The fact is that the Consumer has not received any notification from the Producer (as it has missed one notification (the 1'st one)).

Callback passed to boost::asio::async_read_some never invoked in usage where boost::asio::read_some returns data

I have been working on implementing a half duplex serial driver by learning from a basic serial terminal example using boost::asio::basic_serial_port:
http://lists.boost.org/boost-users/att-41140/minicom.cpp
I need to read asynchronously but still detect when the handler is finished in the main thread so I pass async_read_some a callback with several additional reference parameters in a lambda function using boost:bind. The handler never gets invoked but if I replace the async_read_some function with the read_some function it returns data without an issue.
I believe I'm satisfying all of the necessary requirements for this function to invoke the handler because they are the same for the asio::read some function which returns:
The buffer stays in scope
One or more bytes is received by the serial device
The io service is running
The port is open and running at the correct baud rate
Does anyone know if I'm missing another assumption unique to the asynchronous read or if I'm not setting up the io_service correctly?
Here is an example of how I'm using the code with async_read_some (http://www.boost.org/doc/libs/1_56_0/doc/html/boost_asio/reference/basic_serial_port/async_read_some.html):
void readCallback(const boost::system::error_code& error, size_t bytes_transfered, bool & finished_reading, boost::system::error_code& error_report, size_t & bytes_read)
{
std::cout << "READ CALLBACK\n";
std::cout.flush();
error_report = error;
bytes_read = bytes_transfered;
finished_reading = true;
return;
}
int main()
{
int baud_rate = 115200;
std::string port_name = "/dev/ttyUSB0";
boost::asio::io_service io_service_;
boost::asio::serial_port serial_port_(io_service_,port_name);
serial_port_.set_option(boost::asio::serial_port_base::baud_rate(baud_rate));
boost::thread service_thread_;
service_thread = boost::thread(boost::bind(&boost::asio::io_service::run, &io_service_));
std::cout << "Starting byte read\n";
boost::system::error_code ec;
bool finished_reading = false;
size_t bytes_read;
int max_response_size = 8;
uint8_t read_buffer[max_response_size];
serial_port_.async_read_some(boost::asio::buffer(read_buffer, max_response_size),
boost::bind(readCallback,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred,
finished_reading, ec, bytes_read));
std::cout << "Waiting for read to finish\n";
while (!finished_reading)
{
boost::this_thread::sleep(boost::posix_time::milliseconds(1));
}
std::cout << "Finished byte read: " << bytes_read << "\n";
for (int i = 0; i < bytes_read; ++i)
{
printf("0x%x ",read_buffer[i]);
}
}
The result is that the callback does not print out anything and the while !finished loop never finishes.
Here is how I use the blocking read_some function (boost.org/doc/libs/1_56_0/doc/html/boost_asio/reference/basic_serial_port/read_some.html):
int main()
{
int baud_rate = 115200;
std::string port_name = "/dev/ttyUSB0";
boost::asio::io_service io_service_;
boost::asio::serial_port serial_port_(io_service_,port_name);
serial_port_.set_option(boost::asio::serial_port_base::baud_rate(baud_rate));
boost::thread service_thread_;
service_thread = boost::thread(boost::bind(&boost::asio::io_service::run, &io_service_));
std::cout << "Starting byte read\n";
boost::system::error_code ec;
int max_response_size = 8;
uint8_t read_buffer[max_response_size];
int bytes_read = serial_port_.read_some(boost::asio::buffer(read_buffer, max_response_size),ec);
std::cout << "Finished byte read: " << bytes_read << "\n";
for (int i = 0; i < bytes_read; ++i)
{
printf("0x%x ",read_buffer[i]);
}
}
This version prints from 1 up to 8 characters that I send, blocking until at least one is sent.
The code does not guarantee that the io_service is running. io_service::run() will return when either:
All work has finished and there are no more handlers to be dispatched
The io_service has been stopped.
In this case, it is possible for the service_thread_ to be created and invoke io_service::run() before the serial_port::async_read_some() operation is initiated, adding work to the io_service. Thus, the service_thread_ could immediately return from io_service::run(). To resolve this, either:
Invoke io_service::run() after the asynchronous operation has been initiated.
Create a io_service::work object before starting the service_thread_. A work object prevents the io_service from running out of work.
This answer may provide some more insight into the behavior of io_service::run().
A few other things to note and to expand upon Igor's answer:
If a thread is not progressing in a meaningful way while waiting for an asynchronous operation to complete (i.e. spinning in a loop sleeping), then it may be worth examining if mixing synchronous behavior with asynchronous operations is the correct solution.
boost::bind() copies its arguments by value. To pass an argument by reference, wrap it with boost::ref() or boost::cref():
boost::bind(..., boost::ref(finished_reading), boost::ref(ec),
boost::ref(bytes_read));
Synchronization needs to be added to guarantee memory visibility of finished_reading in the main thread. For asynchronous operations, Boost.Asio will guarantee the appropriate memory barriers to ensure correct memory visibility (see this answer for more details). In this case, a memory barrier is required within the main thread to guarantee the main thread observes changes to finished_reading by other threads. Consider using either a Boost.Thread synchronization mechanism like boost::mutex, or Boost.Atomic's atomic objects or thread and signal fences.
Note that boost::bind copies its arguments. If you want to pass an argument by reference, wrap it with boost::ref (or std::ref):
boost::bind(readCallback, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred, boost::ref(finished_reading), ec, bytes_read));
(However, strictly speaking, there's a race condition on the bool variable you pass to another thread. A better solution would be to use std::atomic_bool.)

STXXL: limited parallelism during sorting?

I populate a very large array using a stxxl::VECTOR_GENERATOR<MyData>::result::bufwriter_type (something like 100M entries) which I need to sort in parallel.
I use the stxxl::sort(vector->begin(), vector->end(), cmp(), memoryAmount) method, which in theory should do what I need: sort the elements very efficiently.
However, during the execution of this method I noticed that only one processor is fully utilised, and all the other cores are quite idle (I suspect there is little activity to fetch the input, but in practice they don't do anything).
This is my question: is it possible to exploit more cores during the sorting phase, or is the parallelism used only to fetch the input asynchronously? If so, are there documents that explain how to enable it? (I looked extensively the documentation on the website, but I couldn't find anything).
Thanks very much!
EDIT
Thanks for the suggestion. I provide below some more information.
First of all I use MacOs for my experiments. What I do is that I launch the following program and I study its behaviour.
typedef struct Triple {
long t1, t2, t3;
Triple(long s, long p, long o) {
this->t1 = s;
this->t2 = p;
this->t3 = o;
}
Triple() {
t1 = t2 = t3 = 0;
}
} Triple;
const Triple minv(std::numeric_limits<long>::min(),
std::numeric_limits<long>::min(), std::numeric_limits<long>::min());
const Triple maxv(std::numeric_limits<long>::max(),
std::numeric_limits<long>::max(), std::numeric_limits<long>::max());
struct cmp: std::less<Triple> {
bool operator ()(const Triple& a, const Triple& b) const {
if (a.t1 < b.t1) {
return true;
} else if (a.t1 == b.t1) {
if (a.t2 < b.t2) {
return true;
} else if (a.t2 == b.t2) {
return a.t3 < b.t3;
}
}
return false;
}
Triple min_value() const {
return minv;
}
Triple max_value() const {
return maxv;
}
};
typedef stxxl::VECTOR_GENERATOR<Triple>::result vector_type;
int main(int argc, const char** argv) {
vector_type vector;
vector_type::bufwriter_type writer(vector);
for (int i = 0; i < 1000000000; ++i) {
if (i % 10000000 == 0)
std::cout << "Inserting element " << i << std::endl;
Triple t;
t.t1 = rand();
t.t2 = rand();
t.t3 = rand();
writer << t;
}
writer.finish();
//Sort the vector
stxxl::sort(vector.begin(), vector.end(), cmp(), 1024*1024*1024);
std::cout << vector.size() << std::endl;
}
Indeed there seems to be only one or maximum two threads working during the execution of this program. Notice that the machine has only a single disk.
Can you please confirm me whether the parallelism work on macos? If not, then I will try to use linux to see what happens. Or is perhaps because there is only one disk?
In principle what you are doing should work out-of-the-box. With everything working you should see all cores doing processing.
Since it doesnt work, we'll have to find the error, and debugging why we see no parallel speedups is still tricky business these days.
The main idea is to go from small to large examples:
what platform is this? There is no parallelism on MSVC, only on Linux/gcc.
By default STXXL builds on Linux/gcc with USE_GNU_PARALLEL. you can turn it off to see if it has an effect.
Try reproducing the example values shown in http://stxxl.sourceforge.net/tags/master/stxxl_tool.html - with and without USE_GNU_PARALLEL
See if just in memory parallel sorting scales on your processor/system.

How to record the running information of functions in your program?

I recently attended a coding interview and I was asked a question which I didn't know the answer to. After searching the answer on the internet for a few day, I come here call for help.
The question is described as followed: You should propose a approach to record the running information of function in your program, for example, the times of a function called, and so on.
By the way, you are not allowed to modify these functions. Maybe you want to define a global variant in these function to record the running function, but that is not allowed.
Ok! That's all about the question I met in a coding interview.
This is the best I could come up with using C++ macros. I don't know whether it conforms to the requirements.
A very basic version just recording the count. The macro replaces all existing calls to the function with the contents of the macro, which records the stats and calls the function. Can easily be extended to record more details. Assumes there's only one function with that name or you want one count for all of them. Requires a macro for each function.
// here's our function
void func()
{ /* some stuff */ }
// this was added
int funcCount = 0;
#define func(...) do { funcCount++; func(__VA_ARGS__); } while(0)
int main()
{
// call the function
func();
// print stats
cout << funcCount << endl;
return 0;
}
Prints 1.
A more generic version. Requires changes to how the function is called.
// here are our functions
void someFunc()
{ /* some stuff */ }
void someOtherFunc()
{ /* some stuff */ }
// this was added
map<string, int> funcCounts;
#define call(func, ...) do { funcCounts[ #func ]++; func(##__VA_ARGS__); } while(0)
int main()
{
// call the functions
// needed to change these from 'someFunc();' format
call(someFunc);
call(someOtherFunc);
call(someFunc);
// print stats
for (map<string, int>::iterator i = funcCounts.begin(); i != funcCounts.end(); i++)
cout << i->first << " - " << i->second << endl;
return 0;
}
Prints:
someFunc - 2
someOtherFunc - 1

Resources