Capturing boost::asio::thread_pool in lambda function - c++

I'm trying to capture thread_pool object in a lambda function. This lambda function is called inside a thread. Upon this call, it creates(obtains) a new thread with asio::post. However, it throws segmentation fault. I tried create weak ptr with shared_ptr<thread_pool> but it didn't work as well. Simple example written below,
#include <boost/asio.hpp>
#include <boost/bind/bind.hpp>
#include <iostream>
void thread1(std::function<void()> createThread) {
createThread();
}
void thread2() {
cout << "You made it" << std::endl;
}
int main(int argc, char **argv) {
boost::asio::thread_pool pool(std::thread::hardware_concurrency());
std::function<void()> createThread;
createThread = [&pool] () {
boost::asio::post(pool, boost::bind(thread2));
return true;
};
boost::asio::post(pool, boost::bind(thread1, createThread));
pool.join();
}
It works if I create another thread_pool object inside the lambda function. However, this is not the right way to do this. Therefore, I am open for your suggestions.
Edit: Added libraries to code snippet and removed while loop.

I'd simplify:
#include <boost/asio.hpp>
#include <boost/bind/bind.hpp>
#include <iostream>
void thread1(std::function<void()> createThread) {
createThread();
while (true) {
std::cout << "Sleeping" << std::endl;
sleep(1);
}
}
void thread2() { std::cout << "You made it" << std::endl; }
int main() {
boost::asio::thread_pool pool;
post(pool,
boost::bind(thread1, [&pool]() { post(pool, boost::bind(thread2)); }));
pool.join();
}
Note the endl that forces stdout to flush, which helps getting results you can expect.
HOWEVER
There's a code smell with:
using explicit "threads" when using a thread-pool
nullary bind expressions
createThread doesn't (create a thread)
passing references to execution contexts. Instead, pass executors
Applying these:
#include <boost/asio.hpp>
#include <boost/bind/bind.hpp>
#include <iostream>
using Executor = boost::asio::thread_pool::executor_type;
void task_loop(Executor ex, std::function<void()> task) {
while (true) {
post(ex, task);
sleep(1);
}
}
void task_function() { std::cout << "Task executes" << std::endl; }
int main() {
boost::asio::thread_pool pool;
post(pool, boost::bind(task_loop, pool.get_executor(), task_function));
pool.join();
}
Prints each second:
Task executes
Task executes
...

Is this one what you look for? :
typedef std::unique_ptr<boost::asio::io_service::work> work_ptr;
std::atomic<bool> closeFlag(false);
int main(int argc, char** argv) {
boost::asio::io_service service;
// keep the workers occupied
work_ptr work(new boost::asio::io_service::work(service));
boost::thread_group workers;
for(size_t i = 0; i < std::thread::hardware_concurrency(); ++i) {
workers.create_thread([&service]() {
service.run();
});
}
service.post([] { std::cout << "You made first job"; });
service.post([] { std::cout << "You made second job"; });
while(!closeFlag) {
boost::this_thread::sleep(boost::posix_time::milliseconds(100));
}
service.stop();
work.reset(); // destroy work object: signals end of work
workers.join_all(); // wait for all worker threads to finish
return 0;
}

Related

Why my thread is not running at all? (Cpp multithreading)

I am new to threading, and i am trying to write a function that keep outputing an variable while i should be able to change that variable at runtime, and the output should change to my input once I input a new value in. By the following program is not running as i expected, whats wrong here? is there anything i can reference to so i can build this funciton out?
int a;
void* ptr;
void* Input(void* arg){
while(true){
std::cin >> a;
std::cout << std::endl;
}
return ptr;
}
void* Output(void *arg){
while(true){
std::cout << a << std::endl;
}
return ptr;
}
int main(){
pthread_t GetInput;
pthread_create(&GetInput,NULL,Input,NULL);
pthread_t GetOutput;
pthread_create(&GetOutput,NULL,Output,NULL);
}
Your main thread is not waiting for your child thread and exited when main() returned. To make your main thread to wait for children finish their jobs, you should call pthread_join() for them.
int main(){
pthread_t GetInput;
pthread_create(&GetInput,NULL,Input,NULL);
pthread_t GetOutput;
pthread_create(&GetOutput,NULL,Output,NULL);
pthread_join(GetInput, NULL);
pthread_join(GetOutput, NULL);
return 0;
}
Here's another alternative using std::async() for your code.
#include <chrono>
#include <future>
#include <iostream>
#include <mutex>
int a;
std::mutex mtx_;
void Input(void* arg) {
while (true) {
int tmp_a;
std::cin >> tmp_a;
{
std::lock_guard<std::mutex> lock(mtx_);
a = tmp_a;
}
std::cout << std::endl;
}
}
void Output(void* arg) {
while (true) {
{
std::lock_guard<std::mutex> lock(mtx_);
std::cout << a << std::endl;
}
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
int main() {
auto ft_in = std::async(std::launch::async, Input, &a);
auto ft_out = std::async(std::launch::async, Output, &a);
ft_in.wait();
ft_out.wait();
return 0;
}
Well,I don't know how to use pthread.
And it seems Mr.john-park or Ms.john-park already gave a answer.
But I think use thread is a better choice.
To use it,we should:
#include<thread>
After that,if u want to start a new thread,and "connect" it with a function(In fact,we usually do)
There is a class named thread.
First,we should
thread *thread name*(*function name*);
WARNING:function nameshould be without "(" and ")"
May because here should be a pointer.
Then,to the question.
Suppose we wrote:
thread GetInput(Input);
thread GetOutput(Output);
When u want to stop GetOutput some time and run GetInput,
just
GetInput.join()
Here's a not so good example:
#include <iostream>
#include <thread>
using namespace std;
void f1()
{
while (true)
{
cout << "THREAD 1!" << endl;
}
}
void f2()
{
for (int i = 0; i < 10; i++)
cout << "THREAD 2!" << endl;
thread t1(f1);
t1.join();
for (int i = 0; i < 10; i++)
cout << "THREAD 2!" << endl;
}
int main()
{
thread t2(f2);
return 0;
}
First,we started t2.
Then t2 started t1.
Now we can know why we use join().
If we don't join(),
It'll be hard for us to read the output because it'll close the cmd window quickly.
But we can know,
after t2 end,
return 0;
ran.
But if we used join()
Here's the output:
THREAD 2!
THREAD 2!
THREAD 2!
...(THREAD 2!*10)
THREAD 1!
THREAD 1!
...(Always THREAD 1!)

Crash when calling interrupt() on a boost::thread, which has another boost::thread

I'm getting a crash when calling interrupt() on an outer boost::thread, which runs an inner boost::thread, which is connected to a thread_guard. It's not crashing when calling join() manually on the inner thread.
Crash:
terminate called after throwing an instance of 'boost::thread_interrupted'
Source:
https://gist.github.com/elsamuko/6e178c37fa2cf8742cb6bf512f2ff866
#include <iostream>
#include <thread>
#include <boost/thread/thread.hpp>
#include <boost/thread/thread_guard.hpp>
#define LOG( A ) std::cout << A << std::endl;
void double_interrupt() {
boost::thread outer([] {
boost::thread inner([]{
while(true) {
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
});
{
std::this_thread::sleep_for(std::chrono::milliseconds(1));
LOG("Interrupting inner");
boost::thread_guard<boost::join_if_joinable> guard(inner); // crashes
// inner.join(); // works
}
});
LOG("Interrupting outer");
outer.interrupt();
outer.join();
}
int main(int argc, char* argv[]) {
LOG("Start");
double_interrupt();
LOG("End");
return 0;
}
Compile & Run:
http://coliru.stacked-crooked.com/a/46c512bf9a385fff
I'm running on Ubuntu 18.04. with g++ 7.5.0 and got the latest boost 1.78.0.
I opened this issue on github, too: https://github.com/boostorg/thread/issues/366
You're mixing std::thread and boost::thread.
Only Boost Thread knows about interruption points. Use that to fix:
Live On Coliru
#include <iostream>
#include <thread>
#include <boost/thread.hpp>
#include <boost/thread/thread_guard.hpp>
void double_interrupt() {
boost::thread outer([] {
boost::thread inner([] {
while (true) {
boost::this_thread::sleep_for(boost::chrono::milliseconds(1));
}
});
{
boost::this_thread::sleep_for(boost::chrono::milliseconds(1));
std::cout << "Interrupting inner" << std::endl;
boost::thread_guard<boost::join_if_joinable> guard(inner);
}
});
std::cout << "Interrupting outer" << std::endl;
outer.interrupt();
outer.join();
}
int main() {
std::cout << "Start" << std::endl;
double_interrupt();
std::cout << "End" << std::endl;
}
Prints
Start
Interrupting outer
End
I got a solution. The problem was, that the join() of the thread_guard waits for the inner thread with a condition_variable::wait(). condition_variable::wait() itself checks, if it's interruptible and throws an exception.
The solution is to use a custom thread_guard with disable_interruption:
#include <iostream>
#include <thread>
#include <boost/thread.hpp>
#include <boost/thread/thread_guard.hpp>
#define LOG( A ) std::cout << A << std::endl;
void work() {
size_t sum = 0;
for(int i = 0; i < 1E7; ++i) { sum += 1; }
LOG("work: " << sum);
}
// helper struct to interrupt a boost::thread within a boost::thread
struct non_interruptable_interrupt_and_join_if_joinable {
template <class Thread>
void operator()(Thread& t) {
if(t.joinable()) {
boost::this_thread::disable_interruption di;
t.interrupt();
t.join();
}
}
};
void double_interrupt() {
boost::thread outer([] {
boost::thread inner([] {
while(true) {
boost::this_thread::interruption_point();
work();
}
});
{
boost::thread_guard<non_interruptable_interrupt_and_join_if_joinable> guard(inner);
LOG("Interrupting inner");
}
});
LOG("Interrupting outer");
outer.interrupt();
outer.join();
}
int main() {
LOG("Start");
double_interrupt();
LOG("End");
}
Run here:
http://coliru.stacked-crooked.com/a/a365e40a2bd574cc

Is using std::future the best way to safely stop a thread?

I'm reading this tutorial on how to safely exit from threads.
In essence, it passes a future object to the function that is going to be executed from the thread, and checks, at every while loop, if that future already has a value (if it has, it exits the thread). See:
void threadFunction(std::future<void> futureObj)
{
std::cout << "Thread Start" << std::endl;
while (futureObj.wait_for(std::chrono::milliseconds(1)) == std::future_status::timeout)
{
std::cout << "Doing Some Work" << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}
std::cout << "Thread End" << std::endl;
}
The problem is that in order to check if futureObj is already setted, it has to wait for some time (here, 1 millissecond). So, I'm losing 1 millissecond on every iteration of the thread. Shouldn't this be preferable:
void threadFunction(bool *shouldStop)
{
std::cout << "Thread Start" << std::endl;
while (!*shouldStop)
{
std::cout << "Doing Some Work" << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}
std::cout << "Thread End" << std::endl;
}
In order to check shouldStop, no time is wasted. So my thread runs faster. Why he didn't do that?
UPDATE:
Here's a simple class that should do the same thing, I guess.
class Stoppable
{
private:
std::atomic<bool> _shouldContinue;
public:
Stoppable()
{
_shouldContinue.store(true);
}
virtual void run() = 0;
void operator()()
{
run();
}
bool shouldContinue()
{
return _shouldContinue.load();
}
void stop()
{
_shouldContinue.store(false);
}
};
Then, to use it, just subclass Stoppable and do like this:
void MySubClass::run()
{
while (shouldContinue())
{
//...
}
}
The second proposal:
void threadFunction(bool *shouldStop)
Is I am afraid wrong if you intend to set *shouldStop from another thread.
In this case it should be void threadFunction(std::atomic<bool> *shouldStop).
There is no one "right way" to signal a thread to stop as it will depend on whether you want your thread to work continually or only work when there is work to do. But there are wrong ways - usually involving undefined behaviour because of writing to a non-atomic variable in one thread and reading from it in another.
If you want your thread to continually work until stopped (for example, this is common in graphics rendering threads or real-time game logic threads) then there is no reason to wait before checking your stop signal.
If your thread is a worker thread which will only run while there is work to do, then it's more normal to use a std::condition_variable, std::mutex and a queue plus a signal.
In case it's interesting, here's an example of an implementation of a work queue. Note that this one permits completion of the work out of order with respect to submission. There are many strategies available:
#include <condition_variable>
#include <mutex>
#include <queue>
#include <functional>
#include <thread>
#include <vector>
#include <iostream>
#include <iomanip>
struct worker_control
{
std::queue<std::function<void()>> work_queue;
std::mutex m;
std::condition_variable cv;
bool stop_signal = false;
void post_work(std::function<void()> f)
{
auto lock = std::unique_lock(m);
work_queue.push(std::move(f));
lock.unlock();
cv.notify_one();
}
void request_stop()
{
auto lock = std::unique_lock(m);
stop_signal = true;
lock.unlock();
cv.notify_all();
}
};
std::mutex emit_mutex;
template<class...Args>
void emit(Args&&...args)
{
auto lock = std::unique_lock(emit_mutex);
std::cout << std::this_thread::get_id() << " : ";
((std::cout << args), ...);
std::cout << '\n';
}
void run_worker(worker_control& control)
{
auto should_run = [&]
{
return not control.work_queue.empty() or control.stop_signal;
};
while (1)
{
auto lock = std::unique_lock(control.m);
control.cv.wait(lock, should_run);
// at this point we own the lock on control.m
if (not control.work_queue.empty())
{
auto work = std::move(control.work_queue.front());
control.work_queue.pop();
lock.unlock(); // allow other workers access to the queue
work();
}
else
{
// we can only have got here if there is no work to do and we have been asked to stop
return;
}
}
}
int main()
{
std::vector<std::thread> worker_threads;
auto control = worker_control();
worker_threads.emplace_back([&]{ run_worker(control); });
worker_threads.emplace_back([&]{ run_worker(control); });
worker_threads.emplace_back([&]{ run_worker(control); });
control.post_work([]{ emit("the"); });
control.post_work([]{ emit("quick"); });
control.post_work([]{ emit("brown"); });
control.post_work([]{ emit("fox"); });
control.post_work([]{ emit("jumps"); });
control.post_work([]{ emit("over"); });
control.post_work([]{ emit("the"); });
control.post_work([]{ emit("lazy"); });
control.post_work([]{ emit("dog"); });
control.request_stop();
for (auto& t : worker_threads)
if (t.joinable())
t.join();
}
Example output:
140244960823040 : the
140244960823040 : fox
140244960823040 : jumps
140244960823040 : over
140244960823040 : the
140244960823040 : lazy
140244960823040 : dog
140244969215744 : quick
140244952430336 : brown
https://coliru.stacked-crooked.com/a/c1612695a3cfc955

How to cancel std::async when condition is met?

I am running an asynchronous task and want to cancel it when a certain condition (bool) is met.
void MyClass::createTask()
{
this->future = std::async(std::launch::async, [this](){
while(this->CONDITION == false)
{
// do work
}
});
}
void MyClass::cancelTask()
{
this->CONDITION = true;
this->future.get();
}
Obviously, calling MyClass::cancelTask() would cause a data-race, because this->CONDITION is being written to and read from at the same time. So the first thing that came to my mind is to use a std::mutex. However that would mean that the task has to lock and unlock the mutex on every new iteration of the while-loop. Since the async task is performance critical, this seems like a bad choice.
Is there a cleaner, and especially a more perfomant way to achieve what I am trying to do? Switching from std::async to std::thread would be ok if it enabled an efficient solution.
As far as I know there is no elegant way to close a thread/async task in C++.
A simple way is to use std::atomic<bool> or std::atomic_flag instead of a mutex.
If you are familiar with boost library, than you could use boost::thread with interruption_points.
I have a solution for this kind of requeirements. I use std::mutex, std::condition_variable and std::unique_lock<std::mutex> to create tow methods: pauseThread and resumeThread.
The idea is use the condition_variable and unique_lock to make the thread wait for a time, for example 5 seconds, and after the time os over the thread continue its execution. But, if you want to interrupt the condition_variable you could use its method notify_one().
Using your code, and continue with your idea, i made some changes to your class:
MODIFICATION: I modify the flag bKeepRunning.
MyClass.h
#include <mutex>
#include <chrono>
#include <future>
#include <atomic>
class MyClass
{
std::atomic<bool> bKeepRunning;
std::mutex mtx_t;
std::condition_variable cv_t;
std::future<void> _future;
public:
MyClass();
~MyClass();
void createTask();
void stopTask();
void pauseThread(int time);
void resumeThread();
}
MyClass.cpp
#include "MyClass.h"
#include <iostream>
using namespace std;
MyClass::MyClass()
{
bKeepRunning = false;
}
MyClass::~MyClass()
{
}
void MyClass::createTask()
{
bKeepRunning = true;
_future = std::async(std::launch::async, [this]() {
int counter = 0;
cout << "Thread running" << endl;
while (bKeepRunning)
{
counter++;
cout << "Asynchronous thread counter = [" << counter << "]" << endl;
this->pauseThread(5);//Wait for 5 seconds
}
cout << "Thread finished." << endl;
});
}
void MyClass::stopTask()
{
cout << "Stoping Thread." << endl;
bKeepRunning = false;
resumeThread();
}
void MyClass::pauseThread(int time)
{
std::unique_lock<std::mutex> lck_t(mtx_t);
cv_t.wait_for(lck_t, chrono::seconds(time));
}
void MyClass::resumeThread()
{
cout << "Resumming thread" << endl;
cv_t.notify_one();
}
I made a console sample to show how it works:
Main.cpp
#include <iostream>
#include <sstream>
#include <string>
#include "MyClass.h"
using namespace std;
int main(int argc, char* argv[])
{
MyClass app;
char line[80];
cout << "Press Enter to stop thread." << endl;
app.createTask();
cin.getline(line,80);
app.stopTask();
}
If you need some other period of time to pause your thread, you can try to change the interval and time of chrono::seconds(time) to, for example, chrono::milliseconds(time) that is using milliseconds.+
At the end, if you execute this sample, you could get an output like:

boost asio deadline_timer async_wait(N seconds) twice within N seconds cause operation canceled

What I want is when one message queue receives an int N, the handler function will be called after N seconds. below is my code.
It runs OK if the duration seconds of two near message queue is larger than the int N, but the handler will print "Operation canceled" in one handler when the duration seconds between two received message queues are smaller than N, which is not what I want.
I'd appreciate a lot for any help.
#include <boost/asio.hpp>
#include <zmq.h>
#include <boost/thread.hpp>
#include <iostream>
boost::asio::io_service io_service;
void* context = zmq_ctx_new();
void* sock_pull = zmq_socket(context, ZMQ_PULL);
void handler(const boost::system::error_code &ec) {
std::cout << "hello, world" << "\t" << ec.message() << std::endl;
}
void run() {
io_service.run();
}
void thread_listener() {
int nRecv;
boost::asio::deadline_timer timer(io_service, boost::posix_time::seconds(0));
while( true ) {
zmq_recv(sock_pull, &nRecv, sizeof(nRecv), 0);
std::cout << nRecv << std::endl;
timer.expires_from_now(boost::posix_time::seconds(nRecv));
timer.async_wait(handler);
}
}
int main(int argc, char* argv[]) {
boost::asio::io_service::work work(io_service);
zmq_bind(sock_pull, "tcp://*:60000");
boost::thread tThread(thread_listener);
boost::thread tThreadRun(run);
tThread.join();
tThreadRun.join();
return 0;
}
When you call
timer.expires_from_now(boost::posix_time::seconds(nRecv));
this, as the documentation states, cancels any async timer pending.
If you want to have overlapping requests in flight at a given time, one timer is clearly not enough. Luckily there is a wellknown pattern around bound shared pointers in Asio that you can use to mimick a "session" per response.
Say you define a session to contain it's own private timer:
struct session : boost::enable_shared_from_this<session> {
session(boost::asio::io_service& svc, int N) :
timer(svc, boost::posix_time::seconds(N))
{
// Note: shared_from_this is not allowed from ctor
}
void start() {
// it's critical that the completion handler is bound to a shared
// pointer so the handler keeps the session alive:
timer.async_wait(boost::bind(&session::handler, shared_from_this(), boost::asio::placeholders::error));
}
private:
void handler(const boost::system::error_code &ec) {
std::cout << "hello, world" << "\t" << ec.message() << std::endl;
}
boost::asio::deadline_timer timer;
};
Now, it's trivial to replace the code that used the hardcoded timer instance:
timer.expires_from_now(boost::posix_time::seconds(nRecv));
timer.async_wait(handler);
with the session start:
boost::make_shared<session>(io_service, nRecv)->start();
A fully working example (with suitably stubbed ZMQ stuff): Live On Coliru
#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/make_shared.hpp>
#include <iostream>
boost::asio::io_service io_service;
/////////////////////////////////////////////////////////////////////////
// I love stubbing out stuff I don't want to install just to help others
enum { ZMQ_PULL };
static void* zmq_ctx_new() { return nullptr; }
static void* zmq_socket(void*,int) { return nullptr; }
static void zmq_bind(void*,char const*) {}
static void zmq_recv(void*,int*data,size_t,int)
{
boost::this_thread::sleep_for(boost::chrono::milliseconds(rand()%1000));
*data = 2;
}
// End of stubs :)
/////////////////////////////////////////////////////////////////////////
void* context = zmq_ctx_new();
void* sock_pull = zmq_socket(context, ZMQ_PULL);
struct session : boost::enable_shared_from_this<session> {
session(boost::asio::io_service& svc, int N) :
timer(svc, boost::posix_time::seconds(N))
{
// Note: shared_from_this is not allowed from ctor
}
void start() {
// it's critical that the completion handler is bound to a shared
// pointer so the handler keeps the session alive:
timer.async_wait(boost::bind(&session::handler, shared_from_this(), boost::asio::placeholders::error));
}
~session() {
std::cout << "bye (session end)\n";
}
private:
void handler(const boost::system::error_code &ec) {
std::cout << "hello, world" << "\t" << ec.message() << std::endl;
}
boost::asio::deadline_timer timer;
};
void run() {
io_service.run();
}
void thread_listener() {
int nRecv = 0;
for(int n=0; n<4; ++n) {
zmq_recv(sock_pull, &nRecv, sizeof(nRecv), 0);
std::cout << nRecv << std::endl;
boost::make_shared<session>(io_service, nRecv)->start();
}
}
int main() {
auto work = boost::make_shared<boost::asio::io_service::work>(io_service);
zmq_bind(sock_pull, "tcp://*:60000");
boost::thread tThread(thread_listener);
boost::thread tThreadRun(run);
tThread.join();
work.reset();
tThreadRun.join();
}