I am converting a previous thread wrapper around pthreads to std::thread.
However c++11 does not have any way to cancel the thread. I REQUIRE, nonetheless, to cancel threads since they may be performing a very lengthy task inside an external library.
I was considering using the native_handle that gives me pthread_id in my platform. I'm using gcc 4.7 in Linux (Ubuntu 12.10). The idea would be:
#include <iostream>
#include <thread>
#include <chrono>
using namespace std;
int main(int argc, char **argv) {
cout << "Hello, world!" << endl;
auto lambda = []() {
cout << "ID: "<<pthread_self() <<endl;
while (true) {
cout << "Hello" << endl;
this_thread::sleep_for(chrono::seconds(2));
}
};
pthread_t id;
{
std::thread th(lambda);
this_thread::sleep_for(chrono::seconds(1));
id = th.native_handle();
cout << id << endl;
th.detach();
}
cout << "cancelling ID: "<< id << endl;
pthread_cancel(id);
cout << "cancelled: "<< id << endl;
return 0;
}
The thread is canceled by an exception thrown by pthreads.
My question is:
Will there be any problem with this approach (besides not being portable)?
No, I don't think that you will not have additional problems than:
not being portable
having to program _very_very_ carefully that all objects of the cancelled thread are destroyed...
For example, the Standard says that when a thread ends variables will be destroyed. If you cancel a thread this will be much harder for the compiler, if not impossible.
I would, therefore recommend not to cancel a thread if you can somehow avoid it. Write a standard polling-loop, use a condition variable, listen on a signal to interrupt reads and so on -- and end the thread regularly.
Related
I have written a small test program to understand the signal and slot mechanism provided by boost and their behavior when posted in different thread. I want to have slot's being called in different threads but the output of my program shows slots are not being called in different thread from which signal was emitted.
#include <iostream>
#include <boost/thread.hpp>
#include <boost/chrono.hpp>
#include <boost/random.hpp>
#include <boost/signals2.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/signals2/signal.hpp>
boost::signals2::signal<void (int)> randomNumberSig;
// ---------------- Thread 1 ----------------
boost::asio::io_service thread1_serv;
void handle_rnd_1(int number)
{
std::cout << "Thread1: " << boost::this_thread::get_id() << " & Number is " << number << std::endl;
}
void thread1_init(void)
{
std::cout << "Thread 1 Init" << std::endl;
boost::asio::io_service::work work (thread1_serv);
randomNumberSig.connect([] (int num) -> void {
std::cout << "Slot called from main thread" << std::endl;
thread1_serv.post(boost::bind(handle_rnd_1, num));
});
}
void thread1_loop(void)
{
}
void thread1(void)
{
thread1_init();
while (true) {
thread1_serv.run();
thread1_loop();
}
}
int main(int argc, char *argv[])
{
std::cout << "Starting the Program" << std::endl;
boost::thread t1(&thread1);
while (1) {
int num = 2;
std::cout << "Thread " << boost::this_thread::get_id() << " & Number: " << num << std::endl;
randomNumberSig(num);
boost::this_thread::sleep_for(boost::chrono::seconds(num));
}
return 0;
}
The output of the program is:
Starting the Program
Thread 7fae3a2ba3c0 & Number: 2
Thread 1 Init
Thread 7fae3a2ba3c0 & Number: 2
Slot called from main thread
Thread 7fae3a2ba3c0 & Number: 2
Slot called from main thread
Thread 7fae3a2ba3c0 & Number: 2
Slot called from main thread
I suspect post() method of the io_service is not working properly or I have missed something in initializing the io_service.
You don't handle invocation of run function properly.
You used work to prevent run from ending when there is no work to do.
But your work is local inside thread1_init so when this function ends, work
is destroyed and io_service::run exits when there are no handlers to be called.
After run finished, io_service is marked as stopped, and you need to call restart before
calling run (as subsequent invocation).
If you don't call restart, run returns immediately without processing any handlers - that is why you don't see them.
So first solution is to create work whose lifetime is the same as io_service (just use global variable - ugly):
boost::asio::io_service thread1_serv;
boost::asio::io_service::work work(thread1_serv);
Another solution, don't use work, just call restart before run:
thread1_init();
while (true) {
thread1_serv.restart();
thread1_serv.run();
thread1_loop();
}
Wandbox test
I'm trying to switch an application over from using boost::interprocess::named_mutex to boost::interprocess::file_lock for interprocess synchronization, but when I did so I noticed that my condition variables were never being woken up.
I've created two examples that demonstrate the types of changes I made and the issues I'm seeing. In both examples the same application should periodically send notifications if invoked with any arguments, or wait for notifications if invoked with no arguments
Originally my application used name_mutex and named_condition. The below example using name_mutex and named_condition works as expected: every time the "sender" application prints out "Notifying" the "receiver" application prints out "Notified!" (provided I manually clean out /dev/shm/ between runs).
#include <iostream>
#include <boost/interprocess/sync/scoped_lock.hpp>
#include <boost/interprocess/sync/named_condition.hpp>
#include <boost/interprocess/sync/named_mutex.hpp>
#include <boost/thread.hpp>
int main(int argc, char** argv)
{
boost::interprocess::named_mutex mutex(boost::interprocess::open_or_create,
"mutex");
// Create condition variable
boost::interprocess::named_condition cond(boost::interprocess::open_or_create, "cond");
while(true)
{
if(argc > 1)
{// Sender
std::cout << "Notifying" << std::endl;
cond.notify_all();
boost::this_thread::sleep_for(boost::chrono::seconds(1));
}
else
{// Receiver
std::cout << "Acquiring lock..." << std::endl;
boost::interprocess::scoped_lock<boost::interprocess::named_mutex> lock(mutex);
std::cout << "Locked. Waiting for notification..." << std::endl;
cond.wait(lock);
std::cout << "Notified!" << std::endl;
}
}
return 0;
}
The following code represents my attempt to change the working code above from using name_mutex and named_condition to using file_lock and named_condition_any
#include <iostream>
#include <boost/interprocess/sync/scoped_lock.hpp>
#include <boost/interprocess/sync/named_condition_any.hpp>
#include <boost/interprocess/sync/file_lock.hpp>
#include <boost/thread.hpp>
int main(int argc, char** argv)
{
// Second option for locking
boost::interprocess::file_lock flock("/tmp/flock");
// Create condition variable
boost::interprocess::named_condition_any cond(boost::interprocess::open_or_create,
"cond_any");
while(true)
{
if(argc > 1)
{// Sender
std::cout << "Notifying" << std::endl;
cond.notify_all();
boost::this_thread::sleep_for(boost::chrono::seconds(1));
}
else
{// Receiver
std::cout << "Acquiring lock..." << std::endl;
boost::interprocess::scoped_lock<boost::interprocess::file_lock> lock(flock);
std::cout << "Locked. Waiting for notification..." << std::endl;
cond.wait(lock);
std::cout << "Notified!" << std::endl;
}
}
return 0;
}
However I can't seem to get the "receiver" application to wake up when notified. The "sender" happily prints "Notifying" at ~1Hz, but the "receiver" hangs after printing "Locked. Waiting for notification..." once.
What am I doing wrong with my file_lock/named_condition_any implementation?
This appears to be caused by a bug in the implementation of boost::interprocess::named_condition_any.
boost::interprocess::named_condition_any is implemented using an instance of boost::interprocess::ipcdetail::shm_named_condition_any. boost::interprocess::ipcdetail::shm_named_condition_any has all of the member variables associated with its implementation aggregated into a class called internal_condition_members. When shm_named_condition_any is constructed it either creates or opens shared memory. If it creates the shared memory it also instantiates an internal_condition_members object in that shared memory.
The problem is that shm_named_condition_any also maintains a "local" (i.e. just on the stack, not in shared memory) member instance of an internal_condition_members object, and its wait, timed_wait, notify_one, and notify_all functions are all implemented using the local internal_condition_members member instead of the internal_condition_members from shared memory.
I was able to get the expected behavior from my example by editing boost/interprocess/sync/shm/named_condition_any.hpp and changing the implementation of the shm_named_condition_any class as follows:
typedef ipcdetail::condition_any_wrapper<internal_condition_members> internal_condition;
internal_condition m_cond;
to
typedef ipcdetail::condition_any_wrapper<internal_condition_members> internal_condition;
internal_condition &internal_cond()
{ return *static_cast<internal_condition*>(m_shmem.get_user_address()); }
and changing all usages of m_cond to this->internal_cond(). This is analogous to how the shm_named_condition class is implemented.
I have a "watch thread" which checks whether other threads are running and calculates some data. If these threads end I want to finish my watch thread, too. How can I do it?
#include <iostream>
#include <thread>
using namespace std;
void f1() {
cout << "thread t1" << endl;
for (int i=0; i<1000; ++i) {
cout << "t1: " << i << endl;
}
}
void f2() {
cout << "thread t2" << endl;
while (T1_IS_RUNNING) {
cout << "t1 still running" << endl;
}
}
int main() {
thread t1(f1);
thread t2(f2);
t1.join();
t2.join();
return 0;
}
In the example above I need to implement T1_IS_RUNNING. Any ideas how to do it? My guess is to get number of running threads but I haven't found any related method in STL.
There is a How to check if a std::thread is still running? already, but I think they use too complicated solutions for my case. Isn't a simple thread counter (std::atomic) good enough?
You can just use a flag for it (running example):
#include <iostream>
#include <thread>
using namespace std;
bool T1_IS_RUNNING = true;
void f1() {
cout << "thread t1" << endl;
for (int i=0; i<1000; ++i) {
cout << "t1: " << i << endl;
}
T1_IS_RUNNING = false;
cout << "thread t1 finish" << endl;
}
void f2() {
cout << "thread t2" << endl;
while (T1_IS_RUNNING) {
cout << "t1 still running" << endl;
}
cout << "thread t2 finish" << endl;
}
int main() {
thread t1(f1);
thread t2(f2);
t1.join();
t2.join();
return 0;
}
This is safe as long as only one of them writes the flag and the other reads it, otherwise you need to use an atomic flag, a mutex or a semaphore.
With atomic_int:
int main(){
std::atomic_int poor_man_semaphore{0};
poor_man_semaphore++;
std::thread t1([&]()
{
std::this_thread::sleep_for(std::chrono::seconds(100));
poor_man_semaphore--;
});
poor_man_semaphore++;
std::thread t2([&]()
{
std::this_thread::sleep_for(std::chrono::seconds(1));
poor_man_semaphore--;
});
poor_man_semaphore++;
std::thread t3([&]()
{
std::this_thread::sleep_for(std::chrono::seconds(1));
poor_man_semaphore--;
});
t2.join();
t3.join();
while ( poor_man_semaphore > 0 )
{
std::this_thread::sleep_for(std::chrono::seconds(1));
}
t1.join();
return 0;
}
Let me give a quick fix to the code, as there is already a detailed post, this will not be long.
This answer exists because there are many wrong answers here.
My interpretation of your problem is you want a "watch thread" to do work while other threads are still alive, but stop whenever others stop.
#include <fstream>
#include <thread>
#include <atomic> // this is REQUIRED, NOT OPTIONAL
using namespace std;
atomic_int count(1); // REQUIRED to be atomic
void f1() {
ofstream f1out{"f1out.txt"};
f1out << "thread t1" << endl;
for (int i=0; i<1000; ++i) {
f1out << "t1: " << i << endl;
}
count--;
}
void f2() {
ofstream f2out{"f2out.txt"};
f2out << "thread t2" << endl;
while (count > 0) {
f2out << "t1 still running" << endl;
}
}
int main() {
thread t1(f1);
thread t2(f2);
t1.join();
t2.join();
}
Notes on atomic
The syntax of atomic_int might look like an int but they are different and failing to use atomic_int is undefined behaviour.
From [intro.races], emphasis mine
Two expression evaluations conflict if one of them modifies a memory location and the other one reads or modifies the same memory location. [...]
The execution of a program contains a data race if it contains two potentially concurrent conflicting actions, at least one of which is not atomic, and neither happens before the other [...] . Any such data race results in undefined behavior.
Notes on cout
Likewise, it is a data race if the threads use cout concurrently, I can't find a simple replacement to preserve the meaning and effect. I opt into using ofstream in the end.
For people concerned
Yes, the atomic operations need not be sequentially consistent but that really doesn't help with clarity.
This link might help you.
Amongst a lot of solutions, one seems quite easy to implement :
An easy solution is to have a boolean variable that the thread sets to true on regular intervals, and that is checked and set to false by the thread wanting to know the status. If the variable is false for to long then the thread is no longer considered active.
A more thread-safe way is to have a counter that is increased by the child thread, and the main thread compares the counter to a stored value and if the same after too long time then the child thread is considered not active.
May be you could set an array of boolean, one by thread you run, and then check it whenever you want to know if other threads are running ?
I have the book "beyond the C++ standard library" and there are no examples of multithreading using boost. Would somebody be kind enough to show me a simple example where two threads are executed using boost- lets say asynchronously?
This is my minimal Boost threading example.
#include <boost/thread.hpp>
#include <iostream>
using namespace std;
void ThreadFunction()
{
int counter = 0;
for(;;)
{
cout << "thread iteration " << ++counter << " Press Enter to stop" << endl;
try
{
// Sleep and check for interrupt.
// To check for interrupt without sleep,
// use boost::this_thread::interruption_point()
// which also throws boost::thread_interrupted
boost::this_thread::sleep(boost::posix_time::milliseconds(500));
}
catch(boost::thread_interrupted&)
{
cout << "Thread is stopped" << endl;
return;
}
}
}
int main()
{
// Start thread
boost::thread t(&ThreadFunction);
// Wait for Enter
char ch;
cin.get(ch);
// Ask thread to stop
t.interrupt();
// Join - wait when thread actually exits
t.join();
cout << "main: thread ended" << endl;
return 0;
}
I've read about synchronized thread in Posix threads tutorial. They say that function pthread_join is used for waiting thread until it stops. But why doesn't this idea work in that case?
Here is my code:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
int a[5];
void* thread(void *params)
{
cout << "Hello, thread!" << endl;
cout << "How are you, thread? " << endl;
cout << "I'm glad to see you, thread! " << endl;
}
void* thread2(void *params)
{
cout << "Hello, second thread!" << endl;
cout << "How are you, second thread? " << endl;
cout << "I'm glad to see you, second thread! " << endl;
// for (;;);
}
int main()
{
pthread_t pt1, pt2;
int iret = pthread_create(&pt1, NULL, thread, NULL);
int iret2 = pthread_create(&pt2, NULL, thread2, NULL);
cout << "Hello, world!" << endl;
pthread_join(pt1, NULL);
cout << "Hello, middle!" << endl;
pthread_join(pt2, NULL);
cout << "The END" << endl;
return 0;
}
Threads are executed asynchronously, as someone already mentioned in answer to question you linked. Thread execution starts right after you create() it. So, at this point:
int iret = pthread_create(&pt1, NULL, thread, NULL);
thread() is already executing in another thread, possibly on another core (but it doesn't really matter). If you add a for (;;); in your main() right after that, you will still see thread message being printed to console.
You also misunderstood what join() does. It waits for thread termination; as your threads don't do any real work, they will (most probably) reach their ends and terminate way before you call join() on them. Once again: join() doesn't start execution of thread in given place, but waits for it to terminate (or just returns, if it's already terminated).