windows c++ thread waiting on queue data-push - c++

My program is setup as follows:
There is a thread-safe queue class, one thread pushing data onto it while sitting in an infinite loop and a second thread popping data off of it while sitting in an infinite loop. I am trying to think of a way to use windows events, or some other mechanism to make the thread_1 (below), wait in the infinite while loop and only iterate when the queue depth is greater than or equal to 1.
class thread-safe_Queue
{
public:
push();
pop();
};
DWORD thread_1()
{
while(1)
{
// wait for thread-safe queue to have data on it
// pop data off
// process data
}
}
DWORD thread_2()
{
while(1)
{
// when data becomes available, push data onto thread-safe queue
}
}

I think this might do the trick. Derive class Event and overload the Process() function.
#include <process.h> // Along with all the normal windows includes
//*********************************************
using namespace os;
Mutex globalQueueMutex;
class QueueReader : public Event
{
public:
virtual void Process()
{
// Lock the queue
Locker l(globalQueueMutex);
// pop data off
// process data
return; // queue will automatically unlock
}
};
QueueReader myQueueReader;
//*********************************************
// The queue writer would have functions like :
void StartQueueReader()
{
Thread(QueueReader::StartEventHandler, &myQueueReader);
}
void WriteToQueue()
{
Locker l(globalQueueMutex);
// write to the queue
myQueueReader.SignalProcess(); // tell reader to wake up
}
// When want to shutdown
void Shutdown()
{
myQueueReader.SignalShutdown();
}
Here are the classes that perform the magic.
namespace os {
// **********************************************************************
/// Windows implementation to spawn a thread.
static uintptr_t Thread (void (*StartAddress)(void *), void *ArgList)
{
return _beginthread(StartAddress, 0, ArgList);
}
// **********************************************************************
/// Windows implementation of a critical section.
class Mutex
{
public:
// Initialize section on construction
Mutex() { InitializeCriticalSection( &cs_ ); }
// Delete section on destruction
~Mutex() { DeleteCriticalSection( &cs_ ); }
// Lock it
void lock() { EnterCriticalSection( &cs_ ); }
// Unlock it
void unlock() { LeaveCriticalSection( &cs_ ); }
private:
CRITICAL_SECTION cs_;
}; // class Mutex
/// Locks/Unlocks a mutex
class Locker
{
public:
// Lock the mutex on construction
Locker( Mutex& mutex ): mutex_( mutex ) { mutex_.lock(); }
// Unlock on destruction
~Locker() { mutex_.unlock(); }
private:
Mutex& mutex_;
}; // class Locker
// **********************************************************************
// Windows implementation of event handler
#define ProcessEvent hEvents[0]
#define SetTimerEvent hEvents[1]
#define ShutdownEvent hEvents[2]
/// Windows implementation of events
class Event
{
/// Flag set when shutdown is complete
bool Shutdown;
/// Max time to wait for events
DWORD Timer;
/// The three events - process, reset timer, and shutdown
HANDLE hEvents[3];
public:
/// Timeout is disabled by default and Events assigned
Event( DWORD timer = INFINITE) : Timer(timer)
{
Shutdown = false;
ProcessEvent = CreateEvent( NULL,TRUE,FALSE,NULL );
SetTimerEvent = CreateEvent( NULL,TRUE,FALSE,NULL );
ShutdownEvent = CreateEvent( NULL,TRUE,FALSE,NULL );
}
/// Close the event handles
virtual ~Event()
{
CloseHandle(ProcessEvent);
CloseHandle(SetTimerEvent);
CloseHandle(ShutdownEvent);
}
/// os::Thread calls this to start the Event handler
static void StartEventHandler(void *pMyInstance)
{ ((Event *)pMyInstance)->EventHandler(); }
/// Call here to Change/Reset the timeout timer
void ResetTimer(DWORD timer) { Timer = timer; SetEvent(SetTimerEvent); }
/// Set the signal to shutdown the worker thread processing events
void SignalShutdown() { SetEvent(ShutdownEvent); while (!Shutdown) Sleep(30);}
/// Set the signal to run the process
void SignalProcess() { SetEvent(ProcessEvent); }
protected:
/// Overload in derived class to process events with worker thread
virtual void Process(){}
/// Override to process timeout- return true to terminate thread
virtual bool Timeout(){ return true;}
/// Monitor thread events
void EventHandler()
{
DWORD WaitEvents;
while (!Shutdown)
{
// Wait here, looking to be signaled what to do next
WaitEvents = WaitForMultipleObjects(3, hEvents, FALSE, Timer);
switch (WaitEvents)
{
// Process event - process event then reset for the next one
case WAIT_OBJECT_0 + 0:
Process();
ResetEvent(ProcessEvent);
break;
// Change timer event - see ResetTimer(DWORD timer)
case WAIT_OBJECT_0 + 1:
ResetEvent(SetTimerEvent);
continue;
// Shutdown requested so exit this thread
case WAIT_OBJECT_0 + 2:
Shutdown = true;
break;
// Timed out waiting for an event
case WAIT_TIMEOUT:
Shutdown = Timeout();
break;
// Failed - should never happen
case WAIT_FAILED:
break;
default:
break;
}
}
}
};
} // namespace os

How about this one (I assume you are familiar with events mechanism).
1.
thread_safe_Queue::push(something)
{
// lock the queue
...
// push object
// Signal the event
SetEvent(notification);
// unlock the queue
}
2.
thread_safe_Queue::pop(something)
{
WaitForSingleObject(notification);
// lock the queue
...
// get object
// reset the event
if (queue is empty)
ResetEvent(notification);
// unlock the queue
}
3. thread_1 just tries to pop the object and handle it. As something is pushed, the event is enabled, so pop can be successfully called. Otherwise it will wait inside pop. Actually you can use other synchronizing objects like mutexes or critical sections instead of the events in this case.
UPDATE. External events:
thread 1:
void thread_1()
{
while(1)
{
WaitForSingleObject(notification);
if (!pop(object)) // pop should return if there are any objects left in queue
SetEvent(notification);
}
}
thread_2
void thread_2()
{
while(1)
{
// push the object and than signal event
ResetEvent(notification)
}
}

You can use named events. Each thread would call CreateEvent passing in the same name. Then use WaitForMultipleObjects to wait for either queue related event or end program event. The pop thread would wait on queue_has_data and end_program events. The push thread would wait on data_available and end_program events and set the queue_has_data event when it puts something into the queue.

Related

How should I wait for thread to finish with a timeout using C++11?

I have Windows multi-threaded code that I'm trying to make portable by using the C++11 thread and synchronization classes. How should the main thread wait for a worker thread with a timeout? I tried using a condition variable, but it's possible for the main thread to miss the worker's notification by waiting too late. In Windows I would use an "event object" as shown below:
#include "Windows.h"
HANDLE hWorkerDoneEvent; // synchronization event
DWORD WINAPI ThreadFunc(LPVOID lpParameter)
{
printf("worker: launched; working\n");
Sleep(1000); // pretend to work
printf("worker: signal done\n");
SetEvent(hWorkerDoneEvent); // signal main thread that we're done working
printf("worker: exit\n");
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
hWorkerDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL); // create auto-reset event
if (hWorkerDoneEvent == NULL) {
printf("main: error creating event\n");
return 0;
}
printf("main: launch worker\n");
if (CreateThread(NULL, 0, ThreadFunc, NULL, 0, NULL) == NULL) { // create worker thread
printf("main: error launching thread\n");
return 0;
}
printf("main: delay a bit\n");
Sleep(2000); // demonstrate that it's impossible to miss the worker's signal by waiting too late
printf("main: wait for worker's done signal\n");
if (WaitForSingleObject(hWorkerDoneEvent, 5000) == WAIT_OBJECT_0) { // wait for worker's signal
printf("main: worker finished normally\n");
} else {
printf("main: worker timeout or error\n");
}
return 0;
}
The Windows program's output is as expected:
main: launch worker
main: delay a bit
worker: launched; working
worker: signal done
worker: exit
main: wait for worker's done signal
main: worker finished normally
My attempt to replicate the above using C++11:
#include "thread"
#include "chrono"
#include "condition_variable"
using namespace std;
condition_variable cvWorkerDone;
mutex mtxWorkerDone;
void ThreadFunc()
{
printf("worker: launched; working\n");
this_thread::sleep_for(std::chrono::milliseconds(1000)); // pretend to work
printf("worker: signal done\n");
cvWorkerDone.notify_all(); // signal main thread that we're done working
printf("worker: exit\n");
}
int _tmain(int argc, _TCHAR* argv[])
{
printf("main: launch worker\n");
thread worker(ThreadFunc);
printf("main: delay a bit\n");
this_thread::sleep_for(std::chrono::milliseconds(2000)); // causes timeout because we waited too late and missed worker's notification
printf("main: wait for worker's done signal\n");
unique_lock<mutex> lk(mtxWorkerDone);
if (cvWorkerDone.wait_for(lk, std::chrono::milliseconds(5000))) {
printf("main: worker finished normally\n");
} else {
printf("main: worker timeout or error\n");
}
worker.join();
return 0;
}
The C+11 program's output; note that the main thread times out even though the worker did its work and signaled:
main: launch worker
worker: launched; working
main: delay a bit
worker: signal done
worker: exit
main: wait for worker's done signal
main: worker timeout or error
In the C++11 code, the main thread incorrectly times out because notification isn't sticky, in other words notify_all only works if a thread is already waiting. I understand that std::binary_semaphore would solve my problem, but that's only available in C++20 which I don't currently have access to. And yes, I could put a short wait at the start of the worker to give the main thread time to get to its wait, but that's gross and race-prone and inefficient.
I also tried having the worker lock a timed_mutex while the main thread does a try_lock_for on that same mutex, as shown below, but this is equally wrong (it deadlocks):
#include "thread"
#include "chrono"
#include "mutex"
using namespace std;
timed_mutex mtxWorkerDone;
void ThreadFunc()
{
printf("worker: launched\n");
printf("worker: delay a bit\n");
this_thread::sleep_for(std::chrono::milliseconds(500)); // fools main thread into locking mutex before we do, causing deadlock
printf("worker: locking mutex\n");
unique_lock<timed_mutex> lk(mtxWorkerDone);
printf("worker: mutex locked; working\n");
this_thread::sleep_for(std::chrono::milliseconds(1000)); // pretend to work
printf("worker: exit (releasing lock)\n");
}
int _tmain(int argc, _TCHAR* argv[])
{
printf("main: launch worker\n");
thread worker(ThreadFunc);
printf("main: wait for worker's done signal\n");
unique_lock<timed_mutex> lk(mtxWorkerDone, defer_lock);
if (lk.try_lock_for(std::chrono::milliseconds(5000))) {
printf("main: worker finished normally\n");
} else {
printf("main: worker timeout or error\n");
}
worker.join();
return 0;
}
The output; the main thread thinks the worker finished normally, but the worker is actually blocked at the unique_lock and never gets to its work.
main: launch worker
worker: launched
worker: delay a bit
main: wait for worker's done signal
main: worker finished normally
worker: locking mutex
To reiterate, I'm looking for a stdlib solution in C++11 that doesn't depend on sleeping to avoid races. I have often ported firmware from Windows to embedded platforms, and often faced similar issues. Windows is the Cadillac of synchronization APIs, with a tool for every occasion. Even twenty years later I still see posts asking how to replace WaitForMultipleObjects. Anyway I expected this to be a PITA and I'm not disappointed. :)
I very well may be missing something, and had to adapt your code a bit as I am doing this quickly on lunch, but I believe this is basically what you are looking for and as far as I can tell is the correct way to go about this. Note the addition of a lambda to the wait() call and the lock_guard in ThreadFunc():
#include "thread"
#include "chrono"
#include "condition_variable"
using namespace std;
condition_variable cvWorkerDone;
mutex mtxWorkerDone;
bool finished = false;
void ThreadFunc()
{
printf("worker: launched; working\n");
this_thread::sleep_for(std::chrono::milliseconds(1000)); // pretend to work
printf("worker: signal done\n");
std::lock_guard<std::mutex> lk(mtxWorkerDone);
finished = true;
cvWorkerDone.notify_all(); // signal main thread that we're done working
printf("worker: exit\n");
}
int main(int argc, char* argv[])
{
printf("main: launch worker\n");
thread worker(ThreadFunc);
printf("main: delay a bit\n");
this_thread::sleep_for(std::chrono::milliseconds(2000)); // causes timeout because we waited too late and missed worker's notification
printf("main: wait for worker's done signal\n");
{
unique_lock<mutex> lk(mtxWorkerDone);
if (cvWorkerDone.wait_for(lk, std::chrono::milliseconds(5000), []{return finished;})) {
printf("main: worker finished normally\n");
} else {
printf("main: worker timeout or error\n");
}
}
worker.join();
return 0;
}

SIGTERM is not captured by sigwait()

I'm writing a program that replys on SIGTERM/SIGINT to terminate. This is a multi-thread program. Basically I have a dedicated thread that is waiting for SIGTERM and SIGINT by calling sigwait and I will notify the main thread upon receving the signals in this thread.
I sent the SIGTERM signal to this program by executing command "killall nameofprocess". However, I found that it will work as expcted only in 10%. Most of times I have to run the "killall" command twice to terminate this program. I'm wondering why the sigwait doesn't capture the SIGTERM the first time. (Same case for SIGINT when I run kill -2)
Is it possible that the signal is received by some other threads?
static std::atomic<bool> shutdown_requested(false);
static std::mutex cv_mutex;
static std::condition_variable cv;
int main()
{
sigset_t sigset;
sigemptyset(&sigset);
sigaddset(&sigset, SIGINT);
sigaddset(&sigset, SIGTERM);
pthread_sigmask(SIG_BLOCK, &sigset, nullptr);
....do something including creating some threads.....
//a dedicated thread that waits for signals
auto signal_handler = [&sigset]() {
int signum = 0;
// wait until a signal is delivered:
sigwait(&sigset, &signum);
shutdown_requested.store(true);
// notify all waiting workers to check their predicate:
cv.notify_all();
return signum;
};
auto signal_handler_async = std::async(std::launch::async, signal_handler);
//wait for cv
while(shutdown_requested.load() == false)
{
std::unique_lock lock(cv_mutex);
cv.wait(lock, [](){return shutdown_requested.load();});
}
..........clean up and exit..............
return 0;
}

Taking in user input from a different thread

I'm making a timer program the counts the time passed since the program started. In the background I'm also checking for keyboard input (enter/return to exit, click on the window); this is done in a separate thread I've run as detached.
It seems the second thread cannot receive the input from the main thread. When I use the keyboard or mouse, nothing happens. Also, nothing appears on the screen, just white.
std::mutex g_mutex;
std::condition_variable cv;
// check for input from the user using the window object
// sets stopProgram to true if the user wishes to exit
void poll(sf::RenderWindow& window, bool& stopProgram) {
std::unique_lock<std::mutex> lk(g_mutex);
// wait for main thread to open window
cv.wait(lk, [&] { return !stopProgram && window.isOpen(); });
sf::Event event;
while (true) {
if (window.pollEvent(event)) {
// if user wants to exit program
if (event.type == sf::Event::Closed || (event.type == sf::Event::KeyPressed &&
(event.key.code == sf::Keyboard::Return || event.key.code == sf::Keyboard::Escape))) {
window.close();
// main thread will explicitly exit the main loop
stopProgram = true;
break;
}
}
}
}
int main()
{
int hour = 0, minute = 0, second = 0;
auto text = textObject();
bool stopProgram = false;
// run a background thread that checks for input while the main program runs
std::thread(poll, std::ref(window), std::ref(stopProgram)).detach();
std::once_flag flag;
std::lock_guard<std::mutex> lk(g_mutex);
while (window.isOpen()) {
// notify once window opens
std::call_once(flag, [&] { cv.notify_one(); });
// set timestamp
text->setString(makeTimeStamp(hour, minute, second));
// if the background thread set stopProgram, end the program
if (stopProgram) break;
window.clear(sf::Color::White);
window.draw(*text);
window.display();
// update time
second = (second + 1) % MAX_SEC;
if (second == 0) minute = (minute + 1) % MAX_MIN;
if (second == 0 && minute == 0) hour = (hour + 1) % MAX_HOUR;
// sleep one second
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
Is my use of multithreading correct? If so, can only the main thread receive input and that's why it's not working?
Update: If I get rid of the while (true) and use while (window.pollEvent(event)) and move the lock_guard to just before if (stopProgram) then the text (timestamp) appears on the screen, but I still cannot process input.
main thread launches poll thread.
std::thread(poll, std::ref(window), std::ref(stopProgram)).detach();
main thread acquires g_mutex and never ever releases it.
std::lock_guard<std::mutex> lk(g_mutex);
poll thread waits for g_mutex to be released:
std::unique_lock<std::mutex> lk(g_mutex);
but the main thread never releases it, so the poll thread never does anything.
To fix it. Change the beginning of the main() function:
int main()
{
int hour = 0, minute = 0, second = 0;
auto text = textObject();
volatile bool stopProgram = false;
// run a background thread that checks for input while the main program runs
std::thread(poll, std::ref(window), std::ref(stopProgram)).detach();
while (!window.isOpen()) { /* busy loop */ }
{
std::lock_guard<std::mutex> lk(g_mutex);
cv.notify_all();
}
while (window.isOpen()) {
...
This SFML API makes things more difficult than other windowing frameworks that I've used. It would be sooo useful if there were a thread-safe window.pushCustomEvent() function.

How to receive the signal from child

Write a program that creates a child process using fork (). The child prints its parent’s name, Parent ID and Own ID while the parent waits for the signal from the child process. Parent sets an alarm 10 seconds after the Child termination.
The below code does not receive the alarm signal from child and also it does not go in the alarm handler i.e. ding function.
what should i do?
using namespace std;
static int alarm_fired = 0;
void ding(int sig)
{
sleep(10);
cout<<"Alarm\n";
}
int main()
{
int cpid,i,ppid;
int status = 0;
cpid=fork();
switch(cpid)
{
case -1:
cout<<"error";
break;
case 0:
cout<<"Child Block"<<endl;
cout<<"Parent\n"<<"ParentID: "<<getppid()<<"\nChildID: "<<getpid();
kill(getppid(), SIGALRM);
default:
cout<<"Parent Waiting"<<endl;
wait(&status);
cout<<"Parent Waiting is Finished"<<endl;
signal(SIGALRM, ding);
}
}
You need to setup parent signal handler "signal(SIGALRM, ding)" before the child sends SIGALARM. In your case you can move "signal(SIGALRM, ding)" one line above fork().

Qt - get data and forward them on serial connection

I am trying to develop a simple Qt application.
After I press a "START" button, the application should continuosly retrieves data from a device (using third party libraries) and forward them as soon as possible on a serial connection.
The (ugly) software I used till now was a console application that ran in a sequential way and got data frame as soon as they are made available by the host, using the following cycle:
while(1)
{
[...]
while( MyClient.GetFrame().Result != Result::Success )
{
Sleep( 200 );
std::cout << ".";
}
[... pack and send on serial]
}
I was wondering which is the more convinient way to implement this in Qt, in order to keep the GUI responsive but also with the minimum possible latency between getFrame and the serial write function.
Should I use a timer triggered SLOT? QtConcurrent namespace? QRunnable?
Which are the main advantages and disadvantages of each of these approaches?
Thanks
for your help!
Since the existing library forces you to poll for data, the only thing to do is to run it on a timer. It's your choice as to if the object that does this job will run in the main thread, or in a worker thread. There's no need to use Qt Concurrent nor QRunnable - using a QObject makes life somewhat simpler since you can easily provide feedback to the GUI.
For example, making some assumptions about your client's API:
class Worker : public QObject {
Client m_client;
QSerialPort m_port;
QBasicTimer m_timer;
void processFrame() {
if (m_client.GetFrame().Result != Result::Success) return;
QByteArray frame = QByteArray::fromRawData(
m_client.GetFrame().Data, m_client.GetFrame().Size);
... process the frame
if (m_port.write(frame) != frame.size()) {
... process the error
}
}
void timerEvent(QTimerEvent * ev) {
if (ev->timerId() == m_timer.timerId()) processFrame();
}
public:
Worker(QObject * parent = 0) : QObject(parent) {}
Q_SLOT bool open(const QString & name) {
m_port.close();
m_port.setPortName(name);
if (!m_port.open(name)) return false;
if (!m_port.setBaudRate(9600)) return false;
if (!m_port.setDataBits(QSerialPort::Data8)) return false;
... other settings go here
return true;
}
Q_SLOT void start() { m_timer.start(200, this); }
Q_SLOT void stop() { m_timer.stop(); }
...
}
/// A thread that's always safe to destruct
class Thread : public QThread {
using QThread::run; // lock the default implementation
public:
Thread(QObject * parent = 0) : QThread(parent) {}
~Thread() { quit(); wait(); }
};
int main(int argc, char ** argv) {
QApplication app(argc, argv);
Worker worker;
Thread thread; // worker must be declared before thread!
if (true) {
// this code is optional, disabling it should not change things
// too much unless the client implementation blocks too much
thread.start();
worker.moveToThread(&thread);
}
QPushButton button("Start");
QObject::connect(&button, &QPushButton::clicked, [&worker]{
// Those are cross-thread calls, they can't be done directly
QMetaObject::invoke(&worker, "open", Q_ARG(QString, "COM1");
QMetaObject::invoke(&worker, "start");
});
button.show();
return app.exec(argc, argv);
}