In my c++11 project, I need to generate two threads which run infinitely. Here is an example:
static vector<int> vec;
static std::mutex mtx;
static std::condition_variable cond;
static bool done = false;
void f1()
{
while(!done)
{
// do something with vec and mtx
}
}
void f2()
{
while(!done)
{
// do something with vec and mtx
}
}
thread t1(f1);
thread t2(f2);
void finish(int s)
{
done = true;
// what should I do???
}
int main()
{
signal(SIGINT, finish);
t1.join();
t2.join();
return 0;
}
Normally, I won't stop or kill this program. But in case of exception, I think I need to do something for ctrl-c, which is used to kill the program. But I don't know how to quit this program properly.
If I'm right, t1 and t2 might continue executing even if the main has returned 0. So I think I need to make them detach like this:
void finish()
{
done = true;
t1.detach();
t2.detach();
}
However, when I execute the program and do ctrl-c, I get an error:
terminate called after throwing an instance of 'std::system_error'
I've found this link, so I think the problem is the same: mtx and/or cond has been destroyed while t1 or t2 hasn't finished yet.
So how could I kill the program properly? Or I don't need to deal with the signal ctrl-c and the program itself knows what to do to quit properly?
done should be std::atomic<bool>, or unsequenced reads/writes are not legal.
Accessing atomic variables is only safe in a signal handler if std::atomic<bool>::is_lock_free is true. Check that. If it isn't true, your program should probably abort with an error in main.
When you .join(), you wait for the thread to finish executing. And you don't want to exit main unless the threads have finished.
In short, do this:
static std::atomic<bool> done = false;
(rest of code goes here)
int main()
{
if (!done.is_lock_free()) return 10; // error
signal(SIGINT, finish);
t1.join();
t2.join();
}
Related
I have a timer that will create a new thread and wait for the timer to expire before calling the notify function. It works correctly during the first execution, but when the timer is started a second time, an exception is thrown trying to create the new thread. The debug output shows that the previous thread has exited before attempting to create the new thread.
Timer.hpp:
class TestTimer
{
private:
std::atomic<bool> active;
int timer_duration;
std::thread thread;
std::mutex mtx;
std::condition_variable cv;
void timer_func();
public:
TestTimer() : active(false) {};
~TestTimer() {
Stop();
}
TestTimer(const TestTimer&) = delete; /* Remove the copy constructor */
TestTimer(TestTimer&&) = delete; /* Remove the move constructor */
TestTimer& operator=(const TestTimer&) & = delete; /* Remove the copy assignment operator */
TestTimer& operator=(TestTimer&&) & = delete; /* Remove the move assignment operator */
bool IsActive();
void StartOnce(int TimerDurationInMS);
void Stop();
virtual void Notify() = 0;
};
Timer.cpp:
void TestTimer::timer_func()
{
auto expire_time = std::chrono::steady_clock::now() + std::chrono::milliseconds(timer_duration);
std::unique_lock<std::mutex> lock{ mtx };
while (active.load())
{
if (cv.wait_until(lock, expire_time) == std::cv_status::timeout)
{
lock.unlock();
Notify();
Stop();
lock.lock();
}
}
}
bool TestTimer::IsActive()
{
return active.load();
}
void TestTimer::StartOnce(int TimerDurationInMS)
{
if (!active.load())
{
if (thread.joinable())
{
thread.join();
}
timer_duration = TimerDurationInMS;
active.store(true);
thread = std::thread(&TestTimer::timer_func, this);
}
else
{
Stop();
StartOnce(TimerDurationInMS);
}
}
void TestTimer::Stop()
{
if (active.load())
{
std::lock_guard<std::mutex> _{ mtx };
active.store(false);
cv.notify_one();
}
}
The error is being thrown from my code block here:
thread = std::thread(&TestTimer::timer_func, this);
during the second execution.
Specifically, the error is being thrown from the move_thread function: _Thr = _Other._Thr;
thread& _Move_thread(thread& _Other)
{ // move from _Other
if (joinable())
_XSTD terminate();
_Thr = _Other._Thr;
_Thr_set_null(_Other._Thr);
return (*this);
}
_Thrd_t _Thr;
};
And this is the exception: Unhandled exception at 0x76ED550B (ucrtbase.dll) in Sandbox.exe: Fatal program exit requested.
Stack trace:
thread::move_thread(std::thread &_Other)
thread::operator=(std::thread &&_Other)
TestTimer::StartOnce(int TimerDurationInMS)
If it's just a test
Make sure the thread handler is empty or joined when calling the destructor.
Make everything that can be accessed from multiple threads thread safe (specifically, reading the active flag). Simply making it an std::atomic_flag should do.
It does seem like you are killing a thread handle pointing to a live thread, but hard to say without seeing the whole application.
If not a test
...then generally, when need a single timer, recurreing or not, you can just go away with scheduling an alarm() signal into itself. You remain perfectly single threaded and don't even need to link with the pthread library. Example here.
And when expecting to need more timers and stay up for a bit it is worth to drop an instance of boost::asio::io_service (or asio::io_service if you need a boost-free header-only version) into your application which has mature production-ready timers support. Example here.
You create the TestTimer and run it the first time via TestTimer::StartOnce, where you create a thread (at the line, which later throws the exception). When the thread finishes, it sets active = false; in timer_func.
Then you call TestTimer::StartOnce a second time. As active == false, Stop() is not called on the current thread, and you proceed to creating a new thread in thread = std::thread(&TestTimer::timer_func, this);.
And then comes the big but:
You have not joined the first thread before creating the second one. And that's why it throws an exception.
I'm trying to use threads to manage several things in GTK+, however, as soon as I try to use any GUI function in the new thread, it locks up the GUI and this makes sense since GTK+ is not thread safe. Is there anyway around this?
Here's my code:
int main(int argc, char *argv[])
{
GError *error = NULL;
/* init threads */
g_thread_init(NULL);
gdk_threads_init();
/* init gtk */
gtk_init(&argc, &argv);
....
//Multithreaded functions
g_thread_create(argument_thread, (gpointer)label7, FALSE, &error );
gdk_threads_enter();
gtk_main();
gdk_threads_leave();
return 0;
}
void *argument_thread(void *args)
{
while(1)
{
gdk_threads_enter();
gtk_entry_set_text(entry2,"random stuff");
gdk_threads_leave();
}
}
Not sure if this could be an issue (don't know GTK) but maybe there is a race condition if the thread acquires the lock before the gtk_main has started.
Then you could try:
gdk_threads_enter();
//Multithreaded functions
g_thread_create(argument_thread, (gpointer)label7, FALSE, &error );
gtk_main();
gdk_threads_leave();
Moreover you should temporize your loop:
void *argument_thread(void *args)
{
while(1)
{
gdk_threads_enter();
gtk_entry_set_text(entry2,"random stuff");
gdk_threads_leave();
sleep(10);
}
}
I have resolved the problem using g_timeout e gthread:http://www.freemedialab.org/wiki/doku.php?id=programmazione:gtk:gtk_e_i_thread
Basically I use 3 functions, one that launches the thread, one that does the job without manipulating widgets (thread) and a third type that serves as a timeout timer checking every n seconds certain values written by the thread and updates the ' graphic interface.
Or you can use "g_idle_add" : http://www.freemedialab.org/wiki/doku.php?id=programmazione:gtk:gtk_e_i_thread#versione_con_g_idle_add
gdk_threads_enter() and gdk_threads_leave() are deprecated from 3.6 version of Gtk.
I have a class ChunkManager that has a few (supposed to be) asynchronous methods. These methods handle tasks in my game engine such as loading the map blocks (similar to Minecraft) on a different thread so as not to completely halt the main thread (they are lengthy operations)
Here is one of those methods:
void ChunkManager::asyncRenderChunks(){
boost::thread loadingThread(&ChunkManager::renderChunks,this);
}
Where renderChunks looks like:
void ChunkManager::renderChunks(){
activeChunksMutex->lock();
for(int z=0; z < CHUNK_MAX; z=z+1)
{
for(int y=0; y < CHUNK_MAX; y=y+1)
{
for(int x=0; x < CHUNK_MAX; x=x+1)
{
activeChunks[x][y][z]->Render(scnMgr);
}
}
}
activeChunksMutex->unlock();
}
This should work, right? However it crashes when this runs. I have a feeling it has to do with what I do with the thread after it's created, because if I put
loadingThread.join();
in the aforementioned method, it works fine, but the main thread is halted because obviously its just waiting for the new thread to finish, effectively bringing me back to square one.
Any advice?
Sorry if this is a retarded question, I am new to the concept of threads.
Thanks.
Update (4/9/2013):
I found this gem: http://threadpool.sourceforge.net/
..and solved my problem!
If you can join the thread, it must be joinable.
As it says in the documentation:
When the boost::thread object that represents a thread of execution is destroyed the program terminates if the thread is joinable.
You created a local thread object and immediately let it go out of scope: it is destroyed when ChunkManager::asyncRenderChunks returns.
Either:
make it a detached (non-joinable) thread
void ChunkManager::asyncRenderChunks() {
boost::thread loadingThread(&ChunkManager::renderChunks,this);
loadingThread.detach();
}
or create the thread object elsewhere and keep it alive
class ChunkManager {
boost::thread renderingThread;
bool renderChunkWork; // work to do flag
Chunk activeChunks[CHUNK_MAX][CHUNK_MAX][CHUNK_MAX];
boost::mutex activeChunksMutex;
boost::condition_variable activeChunksCV;
bool shutdown; // shutdown flag
void renderChunks() {
for(int z=0; z < CHUNK_MAX; ++z)
for(int y=0; y < CHUNK_MAX; ++y)
for(int x=0; x < CHUNK_MAX; ++x)
activeChunks[x][y][z]->Render(scnMgr);
}
void renderChunkThread() {
boost::unique_lock<boost::mutex> guard(activeChunksMutex);
while (true) {
while (!(renderChunkWork || shutdown))
activeChunksCV.wait(guard);
if (shutdown)
break;
renderChunks();
doRenderChunks = false;
}
}
public:
ChunkManager()
: loadingThread(&ChunkManager::renderChunkThread, this),
renderChunkWork(false), shutdown(false)
{}
~ChunkManager() {
{ // tell the rendering thread to quit
boost::unique_lock<boost::mutex> guard(activeChunksMutex);
renderChunkShutdown = true;
activeChunksCV.notify_one();
}
renderingThread.join()
}
void asyncRenderChunks() {
boost::unique_lock<boost::mutex> guard(activeChunksMutex);
if (!renderChunkWork) {
renderChunkWork = true;
activeChunksCV.notify_one();
}
}
};
NB. In general, creating threads on-the-fly is less good than creating your threads up-front, and just waking them when there's something to do. It avoids figuring out how to handle a second call to asyncRenderChunks before the last one is complete (start a second thread? block?), and moves the latency associated with thread creation.
Note on object lifetime
It's important to realise that in this code:
void ChunkManager::asyncRenderChunks() {
SomeType myObject;
}
the instance myObject will be created and then immediately destroyed.
It crashes, because in the current version of Boost.Thread, you have to either join() a thread or detach() it - otherwise ~thread would terminate the program. (In earlier versions ~thread used to call detach() automatically.)
So if you don't want to join the thread - just detach it:
boost::thread loadingThread(&ChunkManager::renderChunks,this);
loadingThread.detach();
Have a pthread that sleeps while waiting on a condition variable. I use a boolean in the outer while loop to keep it running. The problem I seem to have is when I change this variable the thread does not die.
I took a look in instruments and if I start a thread , tell it to die, then start a new one my thread count is 2 not 1.
How can I properly destroy this thread when I want to?
int worktodo=0;
BOOL runthread=NO;
pthread_cond_t cond=PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;
void *threadfunc(void *parm)
{
int rc;
while(runthread==YES)
{
rc=pthread_mutex_lock(&mutex);
while(!worktodo)
{
printf("thtread blocked\n");
rc=pthread_cond_wait(&cond, &mutex);
}
printf("thtread awake.... doing work\n");
// doing work
worktodo=0;
rc=pthread_mutex_unlock(&mutex);
}
// never reaches here!!
pthread_detach(NULL);
}
void makeThread()
{
pthread_attr_t attr;
int returnVal;
returnVal = pthread_attr_init(&attr);
assert(!returnVal);
runthread=YES;
returnVal = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
assert(!returnVal);
int threadError = pthread_create(&str->thread, &attr, &threadfunc, NULL);
returnVal = pthread_attr_destroy(&attr);
assert(!returnVal);
if (threadError != 0)
{
// Report an error.
}
}
void wakethread()
{
pthread_mutex_lock(&mutex);
worktodo=1;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
}
void killthread
{
runthread=NO;
}
thiton was correct. I couldnt kill the thread while it was blocked. Theres probably a better way to do this but the solution that worked for me was to set runthread to false then wake the thread.
void killthread
{
runthread=NO;
pthread_mutex_lock(&mutex);
worktodo=1;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
}
You initialize runthread to NO and compare it to YES. The thread should never reach the inside of its
while(runthread==YES)
loop. Besides, when the thread waits for work, killthread will not wake it up and runthread will stay in its work-waiting loop.
I'm trying to create a thread and let it run until my main signals it to start, which I think is done with SetEvent. But the code in the thread is never executed. Below is the bare code I have stripped down of (I think) unrelated functions. Is the algorithm correct ?
Here is what I thought it did :
When in the main, the thread is created, which means it'll run in the background. When the event is set (SetEvent), the thread picks it up at WaitForSingleObject and then execute the code in the thread, right ?
HANDLE hThread;
HANDLE Event;
DWORD Thread()
{
while(1)
{
wait = WaitForSingleObject(Event, INFINITE)
//This is where I want to execute something
}
}
int _tmain()
{
DWORD dw;
int i;
Event = CreateEvent(NULL,false,false,NULL);
hThread = CreateThread(NULL,0,Thread,EventA,0,NULL);
while(1)
{
if (condition is correct)
{
SetEvent(Event);
}
CloseHandle(Thread);
CloseHandle(Event);
}
return 0;
}
Thanks for having read.
Move CloseHandle lines out of the while loop.