Pthread loop function never gets called - c++

Below is my code, my problem is that readEvent() function never gets called.
Header file
class MyServer
{
public :
MyServer(MFCPacketWriter *writer_);
~MyServer();
void startReading();
void stopReading();
private :
MFCPacketWriter *writer;
pthread_t serverThread;
bool stopThread;
static void *readEvent(void *);
};
CPP file
MyServer::MyServer(MFCPacketWriter *writer_):writer(writer_)
{
serverThread = NULL;
stopThread = false;
LOGD(">>>>>>>>>>>>> constructed MyServer ");
}
MyServer::~MyServer()
{
writer = NULL;
stopThread = true;
}
void MyServer::startReading()
{
LOGD(">>>>>>>>>>>>> start reading");
if(pthread_create(&serverThread,NULL,&MyServer::readEvent, this) < 0)
{
LOGI(">>>>>>>>>>>>> Error while creating thread");
}
}
void *MyServer::readEvent(void *voidptr)
{
// this log never gets called
LOGD(">>>>>>>>>>>>> readEvent");
while(!MyServer->stopThread){
//loop logic
}
}
Another class
MyServer MyServer(packet_writer);
MyServer.startReading();

Since you are not calling pthread_join, your main thread is terminating without waiting for your worker thread to finish.
Here is a simplified example that reproduces the problem:
#include <iostream>
#include <pthread.h>
class Example {
public:
Example () : thread_() {
int rcode = pthread_create(&thread_, nullptr, Example::task, nullptr);
if (rcode != 0) {
std::cout << "pthread_create failed. Return code: " << rcode << std::endl;
}
}
static void * task (void *) {
std::cout << "Running task." << std::endl;
return nullptr;
}
private:
pthread_t thread_;
};
int main () {
Example example;
}
View Results
No output is produced when running this program, even though pthread_create was successfully called with Example::task as the function parameter.
This can be fixed by calling pthread_join on the thread:
#include <iostream>
#include <pthread.h>
class Example {
public:
Example () : thread_() {
int rcode = pthread_create(&thread_, nullptr, Example::task, nullptr);
if (rcode != 0) {
std::cout << "pthread_create failed. Return code: " << rcode << std::endl;
}
}
/* New code below this point. */
~Example () {
int rcode = pthread_join(thread_, nullptr);
if (rcode != 0) {
std::cout << "pthread_join failed. Return code: " << rcode << std::endl;
}
}
/* New code above this point. */
static void * task (void *) {
std::cout << "Running task." << std::endl;
return nullptr;
}
private:
pthread_t thread_;
};
int main () {
Example example;
}
View Results
Now the program produces the expected output:
Running task.
In your case, you could add a call to pthread_join to the destructor of your MyServer class.

Related

member variable in std::async thread

I am working on a project in which I am using threads. The threads are launched with std::async and I ran into some things with member variables in a class that I do not understand. In the code below there are four different implementations of the thread launching function "start_thread_n". The four different functions give somewhat different results when executed and the output I get when running them is shown in the comment before each of the functions. The difference between the functions is in the call std::async(std::launch::async, &ThreadTest::run, &h) and specifically the param "h". What I would like to get is what start_thread_3 delivers (and _4). The difference in behaviour is what the variable m_a contains at different places in the execution of the code, as can be seen in the print outs to the screen (in the comments before each function).
Can you hint on why I get the different results? I run on Linux with C++14.
Many thanks
#include <future>
#include <thread>
#include <vector>
#include <signal.h>
sig_atomic_t g_stop(false);
std::vector<std::future<void>> my_futures;
std::future<void> g_thread;
class ThreadTest
{
public:
ThreadTest();
void run();
private:
unsigned m_a;
};
ThreadTest::ThreadTest()
{
m_a = 1;
std::cout << m_a << std::endl;
}
void ThreadTest::run()
{
std::cout << "Thread started" << std::endl;
while (not g_stop) {
std::cout << "." << std::flush;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
std::cout << std::endl;
std::cout << m_a << std::endl;
std::cout << "Thread stopped" << std::endl;
}
void start_thread_1();
void start_thread_2();
void start_thread_3();
ThreadTest start_thread_4();
void stop_threads();
int main()
{
start_thread_1();
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
g_stop = true;
stop_threads();
}
/*
* > ./thread_test
* 1
* Thread started
* ..........
* 0
* Thread stopped
*/
void start_thread_1()
{
ThreadTest h;
g_thread = std::async(std::launch::async, &ThreadTest::run, &h);
my_futures.push_back(std::move(g_thread));
}
/*
* > ./thread_test
* Thread started
* ..........
* fish: “./thread_test” terminated by signal SIGSEGV (Address boundary error)
*/
void start_thread_2()
{
std::shared_ptr<ThreadTest> h;
g_thread = std::async(std::launch::async, &ThreadTest::run, h);
my_futures.push_back(std::move(g_thread));
}
/*
* > ./thread_test
* 1
* Thread started
* ..........
* 1
* Thread stopped
*/
void start_thread_3()
{
ThreadTest h;
g_thread = std::async(std::launch::async, &ThreadTest::run, h);
my_futures.push_back(std::move(g_thread));
}
/*
* > ./thread_test
* 1
* Thread started
* ..........
* 1
* Thread stopped
*/
ThreadTest start_thread_4()
{
ThreadTest h;
g_thread = std::async(std::launch::async, &ThreadTest::run, h);
my_futures.push_back(std::move(g_thread));
return h;
}
void stop_threads()
{
size_t m = my_futures.size();
for(size_t n = 0; n < m; n++) {
auto e = std::move(my_futures.back());
e.get();
my_futures.pop_back();
}
}```

Why is my Qt application crashing when accessing the IWMPMedia interface?

I have built a Qt (5.7) application that interfaces with the Windows Media Player COM API to parse track meta data. For some in-explicit reason my application is crashing when calling into IWMPMedia3::getAttributeCountByType.
The line where the crash keeps occurring is:
if (pMedia3Item && pMedia3Item->getAttributeCountByType(L"TrackingID", 0, &l) == S_OK) //Will eventually crash here
It does not crash on the first instance, it takes a couple of hundred loops and seems to be connected to when the call repeatedly returns 0. If I switch to an attribute that I know exists then it runs fine.
What is posted below is the object stripped right back, but it still crashes. This object is designed to run in its own QThread and all the COM symbols are defined and contained within the QThread.
The code forms part of a larger app that makes use of many other Qt modules, GUI, web engine being two of the biggest.
#include "WMPMLImport.h"
#include <QDebug>
#include "Wininet.h"
#define WMP_CLSID L"{6BF52A52-394A-11d3-B153-00C04F79FAA6}"
#define WMP_REFIID L"{D84CCA99-CCE2-11d2-9ECC-0000F8085981}"
#define WMP_PL_ALL_MUSIC L"All Music"
#define SAFE_RELEASE(ptr) if(NULL!=(ptr)){(ptr)->Release();ptr=NULL;}
#define BSTR_RELEASE(bstr) {SysFreeString(bstr);(bstr)=NULL;}
class CCoInitialize
{
public:
CCoInitialize() :
m_hr(CoInitialize(NULL))
{}
~CCoInitialize()
{
if(SUCCEEDED(m_hr)) {
qDebug() << "CCoInitialize: DTOR";
CoUninitialize();
}
}
HRESULT m_hr;
};
/**
Worker class that will step through the WMP COM interface
and extact the audio meta data contained within it,
*/
class WMPMLComHandler : public QObject
{
public:
WMPMLComHandler(WMPMLImport* t) :
m_thread(t)
{
qDebug() << "WMPMLComHandler::CTOR" << QThread::currentThreadId();
}
~WMPMLComHandler()
{
qDebug() << "WMPMLComHandler::DTOR" << QThread::currentThreadId();
}
/**
Method responsible for walking through the COM interface and extracting
all the track and playlist metadata including the artwork.
#returns Return false if the COM API was not parsed correctly.
*/
bool parse()
{
bool b = true;
CCoInitialize cCoInit;
IWMPCore* pIWMPCore = NULL;
IWMPCore3* pIWMPCore3 = NULL;
IWMPPlaylistCollection *pPlaylistCollection;
IWMPPlaylist *pMainLibplaylist;
CLSID clsID;
CLSID refID;
CLSIDFromString(WMP_CLSID, &clsID);
CLSIDFromString(WMP_REFIID, &refID);
if(SUCCEEDED(CoCreateInstance(clsID, NULL, CLSCTX_ALL, refID, (void**)&pIWMPCore)))
{
if(SUCCEEDED(pIWMPCore->get_playlistCollection(&pPlaylistCollection)))
{
if(SUCCEEDED(pIWMPCore->QueryInterface(__uuidof(IWMPCore3), reinterpret_cast<void**>(&pIWMPCore3))))
{
IWMPPlaylistArray* pPlaylistArray = NULL;
if(SUCCEEDED(pPlaylistCollection->getAll(&pPlaylistArray)))
{
long playlistCount = 0;
if(SUCCEEDED(pPlaylistArray->get_count(&playlistCount)))
{
IWMPPlaylist* pPlaylist = NULL;
for(int playlistIndex=0; playlistIndex < playlistCount; playlistIndex++)
{
if (SUCCEEDED(pPlaylistArray->item(playlistIndex, &pPlaylist)))
{
long lMediaCount = 0;
if (SUCCEEDED(pPlaylist->get_count(&lMediaCount)))
{
fetchPlaylist(pPlaylist, NULL, playlistIndex, lMediaCount);
}
SAFE_RELEASE(pPlaylist);
}
}
}
SAFE_RELEASE(pPlaylistArray);
}
SAFE_RELEASE(pIWMPCore3);
}
SAFE_RELEASE(pPlaylistCollection);
}
SAFE_RELEASE(pIWMPCore);
}
SAFE_RELEASE(pMainLibplaylist);
return b;
}
private:
void fetchPlaylist(IWMPPlaylist* pPlaylist, BSTR bstrName, unsigned int playlistIndex, long count)
{
//get the playlist items
for(long mediaIndex=0; mediaIndex<count-1; mediaIndex++)
{
IWMPMedia* pMediaItem = NULL;
if(SUCCEEDED(pPlaylist->get_item(mediaIndex, &pMediaItem)))
{
IWMPMedia3 *pMedia3Item = NULL;
if (pMediaItem->QueryInterface(__uuidof(IWMPMedia3), reinterpret_cast<void **>(&pMedia3Item)) == S_OK)
{
long l = 0;
qDebug() << "About to call method for" << mediaIndex << "time";
if (pMedia3Item && pMedia3Item->getAttributeCountByType(L"TrackingID", 0, &l) == S_OK) //Will eventually crash here
{
qDebug() << "Exited method for" << mediaIndex << "time";
}
}
SAFE_RELEASE(pMedia3Item);
SAFE_RELEASE(pMediaItem);
}
}
qDebug() << "*********COMPLETE*********";
}
WMPMLImport* m_thread;
};
//==
WMPMLImport::WMPMLImport() :
m_comHandler(NULL)
{
qDebug() << "WMPMLImporter CTOR" << QThread::currentThreadId();
}
WMPMLImport::~WMPMLImport()
{
}
/**
Reimplemented function that runs the function contents in a new thread context.
The parsing of the COM is all ran through this thread. Returning out of this
thread will end its execution.
*/
void WMPMLImport::run()
{
QMutexLocker g(&m_lock);
m_comHandler = new WMPMLComHandler(this);
g.unlock();
bool parseOk = m_comHandler->parse();
g.relock();
delete m_comHandler;
m_comHandler = NULL;
}

Assertion failed on __pthread_mutex_cond_lock_full in a load test

I used the following code to create a timer object in my c++ application running on a debian 8.
class Timer
{
private:
std::condition_variable cond_;
std::mutex mutex_;
int duration;
void *params;
public:
Timer::Timer(void (*func)(void*))
{
this->handler = func;
this->duration = 0;
this->params = NULL;
};
Timer::~Timer(){};
void Timer::start(int duree, void* handlerParams)
{
this->duration = duree;
this->params = handlerParams;
/*
* Launch the timer thread and wait it
*/
std::thread([this]{
std::unique_lock<std::mutex> mlock(mutex_);
std::cv_status ret = cond_.wait_for(mlock,
std::chrono::seconds(duration));
if ( ret == std::cv_status::timeout )
{
handler(params);
}
}).detach();
};
void Timer::stop()
{
cond_.notify_all();
}
};
It works correctly under gdb and under normal conditions, but in a load test of 30 requests or more, it crashes with the assertion :
nptl/pthread_mutex_lock.c:350: __pthread_mutex_cond_lock_full: Assertion `(-(e)) != 3 || !robust' failed.
I don't understand the cause of this assertion. Can anyone help me please ??
Thank you
Basically you have a detached thread that accesses the timer object, so it's likely that you destroyed the Timer object but the thread is still running and accessing it's member(mutex, conditional variable).
The assert itself says, from glibc source code, that the owner of the mutex has died.
Thanks a lot for your comments ! I'll try to change the thread detach, and do the load tests.
This is a MVCE of my problem, which is a part of a huge application.
/**
* \file Timer.hxx
* \brief Definition of Timer class.
*/
#include <chrono>
#include <thread>
#include <mutex>
#include <condition_variable>
class Timer
{
private:
std::condition_variable cond_;
std::mutex mutex_;
int duration;
void *params;
public:
Timer(void (*func)(void*));
~Timer();
void (*handler)(void*);
void start(int duree, void* handlerParams);
void stop();
};
/*
* Timer.cxx
*/
#include "Timer.hxx"
Timer::Timer(void (*func)(void*))
{
//this->set_handler(func, params);
this->handler = func;
this->duration = 0;
this->params = NULL;
}
Timer::~Timer()
{
}
void Timer::start(int duree, void* handlerParams)
{
this->duration = duree;
this->params = handlerParams;
/*
* Launch the timer thread and wait it
*/
std::thread([this]{
std::unique_lock<std::mutex> mlock(mutex_);
std::cv_status ret = cond_.wait_for(mlock, std::chrono::seconds(duration));
if ( ret == std::cv_status::timeout )
{
handler(params);
}
}).detach();
}
void Timer::stop()
{
cond_.notify_all();
}
/*
* MAIN
*/
#include <stdio.h>
#include <iostream>
#include <unistd.h>
#include "Timer.hxx"
using namespace std;
void timeoutHandler(void* params)
{
char* data= (char*)params;
cout << "Timeout triggered !! Received data is: " ;
if (data!=NULL)
cout << data << endl;
}
int main(int argc, char **argv)
{
int delay=5;
char data[20] ="This is a test" ;
Timer *t= new Timer(&timeoutHandler) ;
t->start(delay, data);
cout << "Timer started !! " << endl;
sleep(1000);
t->stop();
delete t;
cout << "Timer deleted !! " << endl;
return 0;
}

can't create threads suspended using windows.h

i searched for an answer but couldnt find it. im working on threads. i have a thread class and 3 subclass of it. when i call one of these 3 subclass i have to create a thread in thread class and use their main(since threads main is pure virtual abstract) but the problem is before it call the Create Thread function(c'tor of thread) it calls those sub-mains.
thread.h
#ifndef _THREAD_H_
#define _THREAD_H_
#include <string>
#include <Windows.h>
#include <iosfwd>
#include "Mutex.h"
#include "SynchronizedArray.h"
#include "SynchronizedCounter.h"
std::string message = "";
class Thread{
private:
HANDLE hThread;
int idThread;
protected:
SynchronizedArray *arr;
int size;
SynchronizedCounter *counter;
public:
Thread(DWORD funct){ //creates a thread by calling subclasses main functions appropriately
hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) funct, NULL, 0, (LPDWORD)&idThread);
}
virtual DWORD WINAPI main(void*) = 0; // pure virtual abstract class
void suspend(){ //suspent the thread
SuspendThread(hThread);
}
void resume(){// retume the thread
ResumeThread(hThread);
}
void terminate(){ // terminates the thread
TerminateThread(hThread,0);
}
void join(){ // joins the thread
Mutex mut;
mut.lock();
}
static void sleep(int sec){ //wrapper of sleep by sec
Sleep(sec*1000);
}
};
#endif
1 of 3 inherited class of Thread as example (all of them do the same)
PrintThread.h
#ifndef _PRINTINGTHREAD_H_
#define _PRINTINGTHREAD_H_
#include "SynchronizedArray.h"
#include "SynchronizedCounter.h"
#include "Thread.h"
#include <iostream>
#include "SortingThread.h"
#include "CountingThread.h"
#include <string>
#include <Windows.h>
extern CountingThread counterThread1;
extern CountingThread counterThread2;
extern SortingThread sortingThread1;
extern SortingThread sortingThread2;
class PrintingThread:public Thread{
private:
char temp;
public:
PrintingThread() :Thread(main(&temp)){
}
DWORD WINAPI main(void* param)
{
std::cout << "Please enter an operation ('showcounter1','showcounter2','showarray1','showarray2' or 'quit')" << std::endl;
std::cin >> message;
while (message != "quit")
{
if (message == "showcounter1")
{
std::cout << counterThread1<<std::endl;
}
else if (message == "showcounter2")
{
std::cout << counterThread2 << std::endl;
}
else if (message == "showarray1")
{
std::cout << sortingThread1 << std::endl;
}
else if (message == "showarray2")
{
std::cout << sortingThread2 << std::endl;
}
else {
std::cout << "Invalid operation";
}
std::cout << "Please enter an operation ('show counter 1','show counter 2','show array 1','show array 2' or 'quit')" << std::endl;
std::cin >> message;
}
return 0;
}
};
#endif
Why its calling mains before it calls the c'tor of thread.
Your PrintingThread constructor initializer list is actually calling PrintingThread::main and passing the result of that to the Thread constructor. That means that the CreateThread call is receiving a DWORD (in this case, 0) as its function argument.
You need to change your class design to actually pass the function pointer and context argument around, e.g.:
Thread(DWORD funct){
hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) funct, NULL, 0, (LPDWORD)&idThread);
should be:
Thread(LPTHREAD_START_ROUTINE funct, LPVOID arg) {
hThread = CreateThread(NULL, 0, funct, arg, 0, (LPDWORD)&idThread);
(The fact that you had to cast funct should have been a giant red flag.)
Likewise, the subclass constructors will change from:
PrintingThread() :Thread(main(&temp)){
to:
PrintingThread(): Thread(main, &temp) {
Note that your code will still have other issues, like the fact that the thread functions should be static (so you can't try to access member functions).
you need to do something more like this instead:
thread.h:
#ifndef _THREAD_H_
#define _THREAD_H_
#include <string>
#include <Windows.h>
#include <iosfwd>
#include "Mutex.h"
#include "SynchronizedArray.h"
#include "SynchronizedCounter.h"
class Thread
{
private:
HANDLE hThread;
DWORD idThread;
void *pParam;
static DWORD WINAPI ThreadProc(LPVOID lpParameter)
{
Thread *pThis = (Thread*) lpParameter;
return pThis->main(pThis->pParam);
}
protected:
SynchronizedArray *arr;
int size;
SynchronizedCounter *counter;
public:
Thread(void *aParam)
{
//creates a thread by calling subclasses main functions appropriately
pParam = aParam;
hThread = CreateThread(NULL, 0, &ThreadProc, this, 0, &idThread);
}
virtual DWORD main(void*) = 0; // pure virtual abstract class
void suspend()
{
//suspent the thread
SuspendThread(hThread);
}
void resume()
{
// resume the thread
ResumeThread(hThread);
}
void terminate()
{
// terminates the thread
TerminateThread(hThread, 0);
}
void join()
{
// joins the thread
Mutex mut;
mut.lock();
}
static void sleep(int sec)
{
//wrapper of sleep by sec
Sleep(sec*1000);
}
};
#endif
PrintThread.h:
include <iostream>
#include "SortingThread.h"
#include "CountingThread.h"
#include <string>
#include <Windows.h>
extern CountingThread counterThread1;
extern CountingThread counterThread2;
extern SortingThread sortingThread1;
extern SortingThread sortingThread2;
class PrintingThread : public Thread
{
private:
char temp;
public:
PrintingThread() : Thread(&temp)
{
}
virtual DWORD main(void* param)
{
std::string message;
do
{
std::cout << "Please enter an operation ('showcounter1','showcounter2','showarray1','showarray2' or 'quit')" << std::endl;
std::cin >> message;
if (message == "quit")
{
break;
}
if (message == "showcounter1")
{
std::cout << counterThread1 << std::endl;
}
else if (message == "showcounter2")
{
std::cout << counterThread2 << std::endl;
}
else if (message == "showarray1")
{
std::cout << sortingThread1 << std::endl;
}
else if (message == "showarray2")
{
std::cout << sortingThread2 << std::endl;
}
else
{
std::cout << "Invalid operation";
}
}
while (true);
return 0;
}
};
#endif

Writing at multiple positions in real-time

I am trying to develop a console application, where I will display the system date and time in real time (or as real as I can get). This is the easy part. The hard part is that I must also have the cursor available for the user to enter information through. I can't use NCurses in my application, nor any other library that it not included in vanilla GCC 4.4 (there goes boost! Noooo....)
This is my code so far:
The realtime class, where I am incorporating the solution given by Jeremy Friesner here pthreads in c++ inside classes
#ifndef _REALTIME_H_
#define _REALTIME_H_
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
class MyThreadClass
{
public:
MyThreadClass() {/* empty */}
virtual ~MyThreadClass() {/* empty */}
/** Returns true if the thread was successfully started, false if there was an error starting the thread */
bool startMainThread()
{
return (pthread_create(&_mainThread, NULL, mainRunnerFunc, this) == 0);
}
bool startDisplayThread()
{
return (pthread_create(&_displayThread, NULL, displayThreadFunc, this) == 0);
}
/** Will not return until the main thread has exited. */
void waitForMainThreadToExit()
{
(void) pthread_join(_mainThread, NULL);
}
void waitForDisplayThreadToExit()
{
(void) pthread_join(_displayThread, NULL);
}
protected:
/** Implement this method in your subclass with the code you want your thread to run. */
virtual void mainRunner() = 0;
virtual void displayTime() = 0;
private:
static void * mainRunnerFunc(void * This) {((MyThreadClass *)This)->mainRunner(); return NULL;}
static void * displayThreadFunc(void * This) {((MyThreadClass *)This)->displayTime(); return NULL;}
pthread_t _mainThread;
pthread_t _displayThread;
};
class DynamicTime : public MyThreadClass
{
private:
const string currentDate();
void gotoxy(int,int);
void displayTime();
void mainRunner();
pthread_mutex_t mutex1;
public:
// pthread_mutex_t mutex1;
DynamicTime();
unsigned int lifeTime;
unsigned int updateTime;
void start();
int Exit;
};
const string DynamicTime::currentDate()
{
time_t now = time(0);
struct tm tstruct;
char buf[80];
tstruct = *localtime(&now);
strftime(buf,sizeof(buf),"%I:%M:%S %p, %d-%m-%y",&tstruct);
return buf;
}
DynamicTime::DynamicTime()
{
pthread_mutex_init(&(mutex1),NULL);
lifeTime=-1; /* 100 seconds */
updateTime = 1; /* 5 seconds interval */
Exit=1;
}
void DynamicTime::gotoxy(int x,int y)
{
/* go to location */
printf("\033[%d;%df",y,x);
}
void DynamicTime::displayTime()
{
pthread_mutex_lock(&mutex1);
/* save the cursor location */
printf("\033[s");
gotoxy(75,30);
cout << "Date : " << currentDate() << endl;
/* restore the cursor location */
printf("\033[u");
pthread_mutex_unlock(&mutex1);
}
void DynamicTime::mainRunner()
{
unsigned long iterate, iterate2;
int iret1,iret2;
if(lifeTime!=-1)
{
for(iterate=0;iterate<lifeTime*100000;iterate++)
{
if(iterate%(updateTime*50)==0)
{
iret2 = startDisplayThread();
waitForDisplayThreadToExit();
}
for(iterate2=0;iterate2<100000;iterate2++);
}
std::cout << "Ending main thread..." << endl;
}
else
{
while(1&Exit) /* infinitely */
{
iret2 = startDisplayThread();
waitForDisplayThreadToExit();
for(iterate2=0;iterate2<100000;iterate2++);
}
std::cout << "Exiting Application.... " << endl;
}
}
void DynamicTime::start()
{
//system("clear");
//cout << "Starting...." << endl;
if(startMainThread()==false)
{
std::cerr << "Coudln't start main Thread! " << endl;
}
/* call this function in the main program
* else
{
waitForMainThreadToExit();
}*/
}
/* Example
* on how to use the program
* int main()
{
DynamicTime DT;
DT.lifeTime = 100;
DT.start();
return 0;
}
*/
#endif
and my example program, where I am trying to read data from the user, while showing the time at the same time:
//#include <iostream>
#include "realtime2.h"
int main()
{
DynamicTime DT;
string temp="abcd";
DT.start();
while(temp!="exit")
{
std::cout << "$> " ;
std::cin >> temp;
}
DT.waitForMainThreadToExit();
return 0;
}
This would be called a fully-functional program, if only I could get the user to enter data without interruption from the display thread. Any ideas as to how to get around this ? Or if I can't get around this, what would be the proper way to do so ?