Implementing Double Buffering using Futures and Promises using c++11 - c++

I started learning multi-threading and came across futures and promises for synchronizing threads over shared resources. So, I thought of implementing a famous Double Buffering problem using Futures and Promises( single producer and single consumer).
The basic methodology what I have thought is :
ProducerThread:
loop:
locks_buffer1_mutex
fills_buffer1
unlocks_buffer1_mutex
passes number 1 to Consumer thread using promise.setvalue()
locks_buffer2_mutex
fills_buffer2
unlocks_buffer2_mutex
passes number 2 to Consumer thread using promise.setvalue()
back_to_loop
ConsumerThread :
loop:
wait_for_value_from_promise
switch
case 1:
lock_buffer1_mutex
process(buffer1)
unlock_buffer1_mutex
print_values
break
case 2:
lock_buffer2_mutex
process(buffer2)
unlock_buffer2_mutex
print_values
break
back_to_loop
Here is the code:
#include <iostream>
#include <thread>
#include <vector>
#include <future>
#include <mutex>
#include <iterator>
std::mutex print_mutex;
std::mutex buffer1_mutex;
std::mutex buffer2_mutex;
std::vector<int> buffer1;
std::vector<int> buffer2;
bool notify;
void DataAcquisition(std::promise<int> &p)
{
std::this_thread::sleep_for(std::chrono::seconds(2));
while(true)
{
{
std::lock_guard<std::mutex> buff1_lock(buffer1_mutex);
for(int i=0;i<200;i++)
{
buffer1.push_back(i);
}
}
p.set_value(1);
{
std::lock_guard<std::mutex> buff2_lock(buffer2_mutex);
for(int i=0;i<200;i++)
{
buffer2.push_back(199-i);
}
}
p.set_value(2);
}
}
void DataExtraction(std::future<int> &f)
{
std::vector<int>::const_iterator first,last;
std::vector<int> new_vector;
std::ostream_iterator<int> outit(std::cout, " ");
while(true)
{
int i = f.get();
std::cout << "The value of i is :" << i << std::endl;
switch(i)
{
case 1:
{
std::lock_guard<std::mutex> buff1_lock(buffer1_mutex);
first = buffer1.begin();
last = first + 10;
}
new_vector = std::vector<int>(first,last);
{
std::lock_guard<std::mutex> print_lock(print_mutex);
std::copy(new_vector.begin(),new_vector.end(),outit);
}
break;
case 2:
{
std::lock_guard<std::mutex> buff2_lock(buffer2_mutex);
first = buffer2.begin();
last = first + 10;
}
new_vector = std::vector<int>(first,last);
{
std::lock_guard<std::mutex> print_lock(print_mutex);
std::copy(new_vector.begin(),new_vector.end(),outit);
}
break;
}
}
}
int main()
{
std::promise<int> p;
std::future<int> f = p.get_future();
std::thread thread1(DataAcquisition,std::ref(p));
std::thread thread2(DataExtraction,std::ref(f));
thread1.join();
thread2.join();
return 0;
}
When I execute this code I came across through his giagntic problem, which I am fully unaware of
terminate called after throwing an instance of 'std::future_error' terminate called recursively
what(): 0 1 2 3 4 5 6 7 8 9 Promise already satisfied
Press <RETURN> to close the window
I have googled about this error, it is suggested to link -lpthread switch during linking and compile time. but could n't resolve the issue.
Please help me, Where am i going wrong..

You can't call set_value for a promise more that once, which is illustrated by the following code:
#include <future>
int main() {
std::promise<int> p;
p.set_value(1);
p.set_value(2); // Promise already satisfied
}
You have to look for another approach. For example, you could use two std::condition_variables - set them in producer, and wait for them in consumer.

Related

Function Objects & multithreading Pool giving same thread ID

For below program, thread Pool always picks the same thread ID 0x7000095f9000! Why so?
Should every push condi.notify_one() wake up all threads same time? What could be the reason same thread ID get picked?
Computer supports 3 threads.
Any other info on using function objects would be helpful!!
O/P
Checking if not empty
Not Empty
0x700009576000 0
Checking if not empty
Checking if not empty
Checking if not empty
Not Empty
0x7000095f9000 1
Checking if not empty
Not Empty
0x7000095f9000 2
Checking if not empty
Not Empty
0x7000095f9000 3
Checking if not empty
Not Empty
0x7000095f9000 4
Checking if not empty
Not Empty
0x7000095f9000 5
Checking if not empty
Code
#include <iostream>
#include <vector>
#include <queue>
#include <thread>
#include <condition_variable>
#include <chrono>
using namespace std;
class TestClass{
public:
void producer(int i) {
unique_lock<mutex> lockGuard(mtx);
Q.push(i);
cond.notify_all();
}
void consumer() {
{
unique_lock<mutex> lockGuard(mtx);
cout << "Checking if not empty" << endl;
cond.wait(lockGuard, [this]() {
return !Q.empty();
});
cout << "Not Empty" << endl;
cout << this_thread::get_id()<<" "<<Q.front()<<endl;
Q.pop();
}
};
void consumerMain() {
while(1) {
consumer();
std::this_thread::sleep_for(chrono::seconds(1));
}
}
private:
mutex mtx;
condition_variable cond;
queue<int> Q;
};
int main()
{
std::vector<std::thread> vecOfThreads;
std::function<void(TestClass&)> func = [&](TestClass &obj) {
while(1) {
obj.consumer();
}
};
unsigned MAX_THREADS = std::thread::hardware_concurrency()-1;
TestClass obj;
for(int i=0; i<MAX_THREADS; i++) {
std::thread th1(func, std::ref(obj));
vecOfThreads.emplace_back(std::move(th1));
}
for(int i=0; i<4*MAX_THREADS/2; i++) {
obj.producer(i);
}
for (std::thread & th : vecOfThreads)
{
if (th.joinable())
th.join();
}
return 0;
}
Any other info on using function objects would be helpful!! Thanks in advance!!
Any other pointers?
The very short unlocking of the mutex that happens in the consumer threads will in your case most probably let the running thread acquire the lock again, and again and again.
If you instead simulate some work being done after the workload has been picked from the queue by calling consumerMain (which sleeps a little) instead of consumer, you would likely see different threads picking up the workload.
while(1) {
obj.consumerMain();
}

Condition variable basic example

I am learning condition variables in C++11 and wrote this program based on a sample code.
The goal is to accumulate in a vector the first ten natural integers that are generated by a producer and pushed into the vector by a consumer. However it does not work since, for example on some runs, the vector only contains 1, 7 and 10.
#include <mutex>
#include <condition_variable>
#include<vector>
#include <iostream>
#include <cstdio>
std::mutex mut;
#define MAX 10
int counter;
bool isIncremented = false;
std::vector<int> vec;
std::condition_variable condvar;
void producer() {
while (counter < MAX) {
std::lock_guard<std::mutex> lg(mut);
++counter;
isIncremented = true;
condvar.notify_one();
}
}
void consumer() {
while (true) {
std::unique_lock<std::mutex> ul(mut);
condvar.wait(ul, [] { return isIncremented; });
vec.push_back(counter);
isIncremented = false;
if (counter >= MAX) {
break;
}
}
}
int main(int argc, char *argv[]) {
std::thread t1(consumer);
std::thread t2(producer);
t2.join();
t1.join();
for (auto i : vec) {
std::cout << i << ", ";
}
std::cout << std::endl;
// Expected output: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
// Example of actual output: 1, 7, 10,
std::cout << "Press enter to quit";
getchar();
return 0;
}
The problem is that you only remember the last number your producer produced. And your producer never waits until the consumer has consumed what it produced. If your producer thread gets to do more than one iteration of its loop before the consumer thread gets to run (which is not unlikely since the loop doesn't do much), the consumer will only see the last number the producer produced and only push that one into the vector…
To solve this problem, either use a second condition variable to make the producer wait for someone to pick up the last result it produced, or use something that can store more than one result between producer and consumer, or a combination thereof…
Note: Notifying a condition variable is not a blocking call. If it were, it would have to ask you to hand over the mutex so it can internally release it or you'd end up in a deadlock. notify_one() will just wake up one of the threads that are waiting on the condition variable and return. The wait call that the woken thread was blocking on will reacquire the mutex before it returns. In your case, it's not unlikely that the consumer thread be woken and then fail to reacquire the mutex and block again right away because your producer thread is still holding on to the mutex when it's calling notify_one(). Thus, as a general rule of thumb, you want to release the mutex associated with a condition variable should you be holding it before you call notify…
A side note, apparently you used the lock_guard<> in producer, but unique_lock in consumer. In the consumer, the unique_lock also doesn't seem to guard the share resource exclusively.
Below is a modified code that uses unique_lock in both producer and consumer, that guard against shared resource counter.
The code adds a sleep in the producer so that the consumer can be notified of the counter change.
Output seems to be as expected.
#include <mutex>
#include <condition_variable>
#include<vector>
#include <iostream>
#include <cstdio>
#include <thread>
#include <chrono>
std::mutex mut;
#define MAX 10
int counter = 0;
bool isIncremented = false;
std::vector<int> vec;
std::condition_variable condvar;
void producer() {
while (counter < MAX) {
std::unique_lock<std::mutex> lg(mut);
++counter;
isIncremented = true;
lg.unlock();
condvar.notify_one();
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
void consumer() {
while (true) {
std::unique_lock<std::mutex> ul(mut);
condvar.wait(ul, [] { return isIncremented; });
vec.push_back(counter);
isIncremented = false;
if (counter >= MAX) {
break;
}
ul.unlock();
}
}
int main(int argc, char *argv[]) {
std::thread t1(consumer);
std::thread t2(producer);
t2.join();
t1.join();
for (auto i : vec) {
std::cout << i << ", ";
}
std::cout << std::endl;
return 0;
}
Using #MichaelKenzel suggestions from the answer, here is a working example. std::queue is used in order to store more than one result between producer and consumer.
#include<mutex>
#include<condition_variable>
#include<vector>
#include<iostream>
#include<cstdio>
#include<thread>
#include<queue>
std::mutex mut;
#define MAX 10
int counter;
std::queue<int> data_queue;
std::vector<int> vec;
std::condition_variable condvar;
void producer()
{
while (counter < MAX)
{
++counter;
std::lock_guard<std::mutex> lg(mut);
data_queue.push(counter);
condvar.notify_one();
}
}
void consumer()
{
while (true)
{
std::unique_lock<std::mutex> ul(mut);
condvar.wait(ul, [] { return !data_queue.empty(); });
int data = data_queue.front();
data_queue.pop();
ul.unlock();
vec.push_back(data);
if (data >= MAX)
{
break;
}
}
}
int main(int argc, char *argv[])
{
std::thread t1(consumer);
std::thread t2(producer);
t2.join();
t1.join();
for (auto i : vec)
{
std::cout << i << ", ";
}
std::cout << std::endl;
return 0;
}

Processing an array of objects with multithreading - invalid use of void expression error

I need to run some number of threads to process an array of objects.
So I've written this piece of code :
unsigned int object_counter = 0;
while(object_counter != (obj_max - left))
{
thread genThread[thread_num];//create thread objects
///launch threads
int thread_index = 0;
for (; thread_index<thread_num; thread_index++)
{
genThread[thread_index] = thread(object[object_counter].gen_maps());//launch a thread
object_counter++;
if(object_counter == (obj_max - left)
{
break;
}
}
///finish threads
for (; thread_index>0; thread_index--)
{
genThread[thread_index].join();
}
}
Basically, there is an array of objects (number of objects = obj_max - left).
Each object has a function (void type function) called gen_maps() that generates a terrain.
What I want to do is running all gen_maps() functions from all objects using multithreading.
A maximum number of threads is stored in thread_num variable.
But when I'm trying to compile this code I'm getting an error:
error: invalid use of void expression
genThread[thread_index] = thread(object[object_counter].gen_maps(), thread_index);//launch a thread
^
How can I fix this issue?
A more extendable way to manage an arbitrarily large number of jobs with a smaller number of threads is to use a thread pool.
Here's a naive implementation (for better efficiency there would be 2 condition variables to manage control and state reporting) which allows the initiator to add an arbitrary number of jobs or threads and wait for all jobs to be complete.
#include <thread>
#include <condition_variable>
#include <mutex>
#include <vector>
#include <functional>
#include <deque>
#include <cassert>
#include <ciso646>
#include <iostream>
struct work_pool
{
std::mutex control_mutex;
std::condition_variable control_cv;
std::deque<std::function<void()>> jobs;
bool terminating = false;
std::size_t running = 0;
std::vector<std::thread> threads;
work_pool(std::size_t n = std::thread::hardware_concurrency())
{
add_threads(n);
}
work_pool(const work_pool&) = delete;
work_pool& operator=(const work_pool&) = delete;
~work_pool()
{
wait();
shutdown();
}
void add_threads(std::size_t n)
{
while (n--)
{
threads.emplace_back([this]{
run_jobs();
});
}
}
void run_jobs()
{
while (1)
{
auto lock = std::unique_lock(control_mutex);
control_cv.wait(lock, [this] {
return terminating or not jobs.empty();
});
if (terminating) return;
++running;
auto job = std::move(jobs.front());
jobs.pop_front();
lock.unlock();
job();
lock.lock();
--running;
lock.unlock();
control_cv.notify_one();
}
}
void shutdown()
{
auto lock = std::unique_lock(control_mutex);
terminating = true;
lock.unlock();
control_cv.notify_all();
for (auto&& t : threads) {
if (t.joinable()) {
t.join();
}
}
threads.clear();
}
void wait()
{
auto lock = std::unique_lock(control_mutex);
control_cv.wait(lock, [this] {
return jobs.empty() and not running;
});
}
template<class F>
void add_work(F&& f)
{
auto lock = std::unique_lock(control_mutex);
assert(not terminating);
jobs.emplace_back(std::forward<F>(f));
lock.unlock();
control_cv.notify_all();
}
};
// dummy function for exposition
void generate_map() {}
int main()
{
work_pool pool;
for(int i = 0 ; i < 100000 ; ++i)
pool.add_work(generate_map);
pool.wait();
// maps are now all generated
std::cout << "done" << std::endl;
}
With object[object_counter].gen_maps() you call the function gen_maps and use the returned value as the thread function. Apparently gen_maps is declared to return void which leads to the error you get.
You need to pass a pointer to the function, and then pass the object it should be called on as an argument to the thread:
thread(&SomeClass::gen_maps, object[object_counter])

c++ thread does not execute

The thread1 function does not seem to get executed
#include <iostream>
#include <fstream>
#include <thread>
#include <condition_variable>
#include <queue>
std::condition_variable cv;
std::mutex mu;
std::queue<int> queue;
bool ready;
static void thread1() {
while(!ready) {std::this_thread::sleep_for(std::chrono::milliseconds(10));}
while(ready && queue.size() <= 4) {
std::unique_lock<std::mutex> lk(mu);
cv.wait(lk, [&]{return !queue.empty();});
queue.push(2);
}
}
int main() {
ready = false;
std::thread t(thread1);
while(queue.size() <= 4) {
{
std::lock_guard<std::mutex> lk(mu);
queue.push(1);
}
ready = true;
cv.notify_one();
}
t.join();
for(int i = 0; i <= queue.size(); i++) {
int a = queue.front();
std::cout << a << std::endl;
queue.pop();
}
return 0;
}
On my Mac the output is 1 2 1 2 but in my ubuntu its 1 1 1. I'm compiling with g++ -std=c++11 -pthread -o thread.out thread.cpp && ./thread.out. Am I missing something?
This:
for(int i = 0; i <= queue.size(); i++) {
int a = queue.front();
std::cout << a << std::endl;
queue.pop();
}
Is undefined behavior. A for loop that goes from 0 to size runs size+1 times. I would suggest that you write this in the more idiomatic style for a queue:
while(!queue.empty()) {
int a = queue.front();
std::cout << a << std::endl;
queue.pop();
}
When I run this on coliru, which I assume runs some kind of *nix machine, I get 4 1's: http://coliru.stacked-crooked.com/a/8de5b01e87e8549e.
Again, you haven't specified anything that would force each thread to run a certain amount of times. You only (try to*) cause an invariant where the queue will reach size 4, either way. It just happens to be that on the machines that we ran it on, thread 2 never manages to acquire the mutex.
This example will be more interesting if you add more work or even (just for pedagogical purposes) delays at various points. Simulating that the two threads are actually doing work. If you add sleeps at various points you can ensure that the two threads alternate, though depending where you add them you may see your invariant of 4 elements in the thread break!
*Note that even your 4 element invariant on the queue, is not really an invariant. It is possible (though very unlikely) that both threads pass the while condition at the exact same moment, when there are 3 elements in the queue. One acquires the lock first and pushes, and then the other. So you can end up with 5 elements in the queue! (as you can see, asynchronous programming is tricky). In particular you really need to check the queue size when you have the lock in order for this to work.
I was able to solve this by making the second thread wait on a separate predicate on a separate conditional variable. I'm not sure if queue.size() is thread safe.
#include <iostream>
#include <fstream>
#include <thread>
#include <condition_variable>
#include <queue>
std::condition_variable cv;
std::condition_variable cv2;
std::mutex mu;
std::queue<int> queue;
bool tick;
bool tock;
static void thread1() {
while(queue.size() < 6) {
std::unique_lock<std::mutex> lk(mu);
cv2.wait(lk, []{return tock;});
queue.push(1);
tock = false;
tick = true;
cv.notify_one();
}
}
int main() {
tick = false;
tock = true;
std::thread t(thread1);
while(queue.size() < 6) {
std::unique_lock<std::mutex> lk(mu);
cv.wait(lk, []{return tick;});
queue.push(2);
tick = false;
tock = true;
cv2.notify_one();
}
t.join();
while(!queue.empty()) {
int r = queue.front();
queue.pop();
std::cout << r << std::endl;
}
return 0;
}

Using a C++11 condition variable in VS2012

I can't get code working reliably in a simple VS2012 console application consisting of a producer and consumer that uses a C++11 condition variable. I am aiming at producing a small reliable program (to use as the basis for a more complex program) that uses the 3 argument wait_for method or perhaps the wait_until method from code I have gathered at these websites:
condition_variable:
wait_for,
wait_until
I'd like to use the 3 argument wait_for with a predicate like below except it will need to use a class member variable to be most useful to me later. I am receiving "Access violation writing location 0x__" or "An invalid parameter was passed to a service or function" as errors after only about a minute of running.
Would steady_clock and the 2 argument wait_until be sufficient to replace the 3 argument wait_for? I've also tried this without success.
Can someone show how to get the code below to run indefinitely with no bugs or weird behavior with either changes in wall-clock time from daylight savings time or Internet time synchronizations?
A link to reliable sample code could be just as helpful.
// ConditionVariable.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <condition_variable>
#include <mutex>
#include <thread>
#include <iostream>
#include <queue>
#include <chrono>
#include <atomic>
#define TEST1
std::atomic<int>
//int
qcount = 0; //= ATOMIC_VAR_INIT(0);
int _tmain(int argc, _TCHAR* argv[])
{
std::queue<int> produced_nums;
std::mutex m;
std::condition_variable cond_var;
bool notified = false;
unsigned int count = 0;
std::thread producer([&]() {
int i = 0;
while (1) {
std::this_thread::sleep_for(std::chrono::microseconds(1500));
std::unique_lock<std::mutex> lock(m);
produced_nums.push(i);
notified = true;
qcount = produced_nums.size();
cond_var.notify_one();
i++;
}
cond_var.notify_one();
});
std::thread consumer([&]() {
std::unique_lock<std::mutex> lock(m);
while (1) {
#ifdef TEST1
// Version 1
if (cond_var.wait_for(
lock,
std::chrono::microseconds(1000),
[&]()->bool { return qcount != 0; }))
{
if ((count++ % 1000) == 0)
std::cout << "consuming " << produced_nums.front () << '\n';
produced_nums.pop();
qcount = produced_nums.size();
notified = false;
}
#else
// Version 2
std::chrono::steady_clock::time_point timeout1 =
std::chrono::steady_clock::now() +
//std::chrono::system_clock::now() +
std::chrono::milliseconds(1);
while (qcount == 0)//(!notified)
{
if (cond_var.wait_until(lock, timeout1) == std::cv_status::timeout)
break;
}
if (qcount > 0)
{
if ((count++ % 1000) == 0)
std::cout << "consuming " << produced_nums.front() << '\n';
produced_nums.pop();
qcount = produced_nums.size();
notified = false;
}
#endif
}
});
while (1);
return 0;
}
Visual Studio Desktop Express had 1 important update which it installed and Windows Update has no other important updates. I'm using Windows 7 32-bit.
Sadly, this is actually a bug in VS2012's implementation of condition_variable, and the fix will not be patched in. You'll have to upgrade to VS2013 when it's released.
See:
http://connect.microsoft.com/VisualStudio/feedback/details/762560
First of all, while using condition_variables I personally prefer some wrapper classes like AutoResetEvent from C#:
struct AutoResetEvent
{
typedef std::unique_lock<std::mutex> Lock;
AutoResetEvent(bool state = false) :
state(state)
{ }
void Set()
{
auto lock = AcquireLock();
state = true;
variable.notify_one();
}
void Reset()
{
auto lock = AcquireLock();
state = false;
}
void Wait(Lock& lock)
{
variable.wait(lock, [this] () { return this->state; });
state = false;
}
void Wait()
{
auto lock = AcquireLock();
Wait(lock);
}
Lock AcquireLock()
{
return Lock(mutex);
}
private:
bool state;
std::condition_variable variable;
std::mutex mutex;
};
This may not be the same behavior as C# type or may not be as efficient as it should be but it gets things done for me.
Second, when I need to implement a producing/consuming idiom I try to use a concurrent queue implementation (eg. tbb queue) or write a one for myself. But you should also consider making things right by using Active Object Pattern. But for simple solution we can use this:
template<typename T>
struct ProductionQueue
{
ProductionQueue()
{ }
void Enqueue(const T& value)
{
{
auto lock = event.AcquireLock();
q.push(value);
}
event.Set();
}
std::size_t GetCount()
{
auto lock = event.AcquireLock();
return q.size();
}
T Dequeue()
{
auto lock = event.AcquireLock();
event.Wait(lock);
T value = q.front();
q.pop();
return value;
}
private:
AutoResetEvent event;
std::queue<T> q;
};
This class has some exception safety issues and misses const-ness on the methods but like I said, for a simple solution this should fit.
So as a result your modified code looks like this:
int main(int argc, char* argv[])
{
ProductionQueue<int> produced_nums;
unsigned int count = 0;
std::thread producer([&]() {
int i = 0;
while (1) {
std::this_thread::sleep_for(std::chrono::microseconds(1500));
produced_nums.Enqueue(i);
qcount = produced_nums.GetCount();
i++;
}
});
std::thread consumer([&]() {
while (1) {
int item = produced_nums.Dequeue();
{
if ((count++ % 1000) == 0)
std::cout << "consuming " << item << '\n';
qcount = produced_nums.GetCount();
}
}
});
producer.join();
consumer.join();
return 0;
}