Im new to Concurrency and parallelism programming in C/C++ so I need some help woth my project.
I want to run multiple process using POSIX and Semaphores in C++. So the structure of the program should be the following one.
First I Open Serial port (Serial communication of the Raspberry PI 4). While the Serial is Open Two processes are running
First one, the main one run automatically and do the following:
The thread ask for ODOM Updates(Pressure and IMU from the microcontroller) and Publish them. Also every 0.3 seconds check the modem inbox and if something new it publish.
The other one only on DEMAND from ROS Services detect that there is new message in the modem inbox do HALT( on the first main Process) and execute (publish) on the serial Port. Then the first process resume with normal work
So I trying to do first some pseudo C++ code that looks like these But I need help as Im new to Concurrency and parallelism. Here it is
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
sem_t mutex;
void* thread(void* arg) { //function which act like thread
//Main Thread
// Here code for ASK ODOM UPDATE..
// Here code for CHECK MODEM INBOX...
sem_wait(&mutex); //wait state
// ENTER in the second Process
// Here code for the second process which run on DEMAND..
// ROS SERVICES
// Here code for CHECK The MODEM INBOX and HALT the First Process
// Here code for EXECUTE on SERIAL PORT(PUBLISH)
sleep(0.1); //critical section
printf("\nCompleted...\n"); //comming out from Critical section
sem_post(&mutex);
}
main() {
sem_init(&mutex, 0, 1);
pthread_t th1,th2;
pthread_create(&th1,NULL,thread,NULL);
sleep(1);
pthread_create(&th2,NULL,thread,NULL);
//Join threads with the main thread
pthread_join(th1,NULL);
pthread_join(th2,NULL);
sem_destroy(&mutex);
}
So Im not sure this is the correct way of implementation on C++ . Any help in the implementation and maybe help on the actual C++ code?
Thanks
Fortunately, ROS lets you decide what threading model you want to use (http://wiki.ros.org/roscpp/Overview/Callbacks%20and%20Spinning).
You could use the ros::AsyncSpinner for that:
Your main thread starts the AsyncSpinner that runs in the background, listens to ROS messages, and calls your ROS callback functions in its own threads.
Then, your main thread cares about your serial port connection and forwards/publishes messages. In pseudo-code, it could look as follows:
#include <ros/ros.h>
#include <mutex>
#include <std_msgs/Float32.h>
std::mutex mutex_;
void callback(std_msgs::Float32ConstPtr msg) {
// reentrant preprocessing
{
std::lock_guard<std::mutex> guard( mutex_ );
// work with serial port
}
// reentrant posprocessing
}
int main(int argc, char* argv[]) {
ros::init(argc, argv, "name");
ros::NodeHandle node("~");
ros::Subscriber sub = node.subscribe("/test", 1, callback);
ros::AsyncSpinner spinner(1);
spinner.start();
while(ros::ok()) {
// reentrant preprocessing
{
std::lock_guard<std::mutex> guard(mutex_);
// work with serial port
}
// reentrant postprocessing
}
}
You can see the code block that is critical. Here, both threads are synchronized, i.e., only one thread is in its critical path at a time.
I used the C++ mutex, as it is the C++ std way, but you could change that of course.
Also, feel free to wait for serial port messages in the main thread to reduce heat production on your chip.
I am trying to create a thread that will handle the below MSDN example.
I have tested the example, changed in it only the path in lpSubKey paramater in the RegOpenKeyEx and it is working fine.
Here is the below thread I am trying to create that gives me a pop-up window of:
r6010 abort()......
The code:
#include <thread>
void listenerTest();
void main(){
std::thread threadTest(listenerTest);
for (int i = 0; i < 5; i++)
cout << "\ntest non thread\n";
}
Inside the void listenerTest() is the MSDN example with the minor changed I have made.
I also tried other approach, for instance, creating the thread without the WaitForSingleObject() (which gives that error) but I can't find a way to return a HANDLE for WaitForSingleObject() which waits OUTSIDE the thread (in the main).
I don't need synchronization between the threadTest thread and the main thread. All I am trying to achieve is that the threadTest will run for infinite time while main executes.
Any help would be appropriated.
Thank you.
I have the task of initialisation of an object, that is quite long. What is the right way to go about it?
here is the code i have so far (for simplicity, initialisation consists of adding entries to string list only):
#ifndef TASKINITIALIZER_H
#define TASKINITIALIZER_H
#include <QDir>
#include <QThread>
#include <QObject>
#include "task.h"
class TaskInitializer:public QThread
{
Q_OBJECT
QDir dir;
QString msg;
Task &result;
public:
TaskInitializer(QString dname, bool png, bool jpg, bool bmp, Task &res);
~TaskInitializer();
const QString& getMessage();
bool isOk();
private:
void run();
};
#endif // TASKINITIALIZER_H
#include <QDir>
#include <QDirIterator>
#include "taskinitializer.h"
TaskInitializer::TaskInitializer(QString dname, bool png, bool jpg, bool bmp, Task & res):
dir(dname),result(res)
{
QStringList filters;
if (png)
filters << "*.png";
if(jpg)
{
filters << "*.jpeg" << "*.jpg";
}
if(bmp)
filters << "*.bmp";
dir.setNameFilters(filters);
}
TaskInitializer::~TaskInitializer()
{
}
const QString &TaskInitializer::getMessage()
{
return msg;
}
bool TaskInitializer::isOk()
{
if (!dir.exists())
{
msg = ("Directory does not exist");
return false;
}
if (dir.nameFilters().length() < 1)
{
msg = ("No image types chosen");
return false;
}
return true;
}
void TaskInitializer::run()
{
QDirIterator di(dir,QDirIterator::Subdirectories);
while(di.hasNext())
{
result.addFilename(di.next());
}
}
The ides is to pass parameters to initialiser instance in constructor, check their validity and then run the initialisation itself. However, initialisation may take long and the application may be stopped abruptly; in this case initialiser should stop its activity properly and be cleaned up.
I have read on several methods of running async tasks, but still haven't understood how to detect the stop signal. As far as i can see, running QRunnable in thread pool or using QtConcurrent::run() does not gives any mechanism of checking whether it is time to stop or not.
Also, i am confused of the subject of how to pass the object being initialised properly to and from initialising task, so that it would be guaranteed to be cleaned up. Same with initialiser; how can it be guaranteed to be cleaned up?
here is the code i currently use to launch initialisation:
_temp = new Task();
TaskInitializer *worker = new TaskInitializer(_directoryName,flags[2],flags[1],flags[0],*_temp);
if (!worker->isOk())
{
delete _temp;
_temp = NULL;
emit logMessage(worker->getMessage());
return _temp;
}
//clearTempTask();
emit logMessage("New task created");
connect(worker,SIGNAL(finished()),SIGNAL(taskInitialized()));
connect(worker,SIGNAL(finished()),worker,SLOT(deleteLater()));
worker->start();
worker = NULL;
Well, the quick-and-dirty method would be to have a boolean variable (named pleaseStop or something) that the initializer thread checks every so often to see if the main thread has set it to true or not. If the main thread has set it to true, the thread task would see that and abort its initialization routine and exit.
A slightly nicer method would be to break up the initialization task into smaller parts -- e.g. do 50 milliseconds worth of initialization, then if there is still more initialization left to do, call QTimer::singleShot(0, this, SLOT(DoSomeMore()) and return from the method, such that the DoSomeMore() slot gets called on the next iteration of the Qt event loop, but in the meantime any other pending signals (such as a PleaseQuitNow() type of signal coming in from the main thread, which could be connected to the QThread's quit() slot) would get processed.
In fact, if you keep the time slices short enough, with the second method you may not even need to launch a second thread at all -- the initialization could run in the main thread but GUI events would still get serviced in a relatively timely manner, since they would get interspersed between short DoSomeMore() calls rather than being blocked by a single very lengthy DoEverythingAllInOneGo() call.
As for passing the data object back and forth, simply handing the initializer thread a pointer/reference to the data object is sufficient, as long as you are careful to ensure the following:
The main thread shouldn't read or write the data object until the initializer thread has completed its work
The main thread must guarantee that the data object will remain valid until after the initializer thread has completed its work (e.g. don't delete the data object while the initializer thread might still be using it!)
recently I set out to port ucos-ii to Ubuntu PC.
As we know, it's not possible to simulate the "process" in the ucos-ii by simply adding a flag in "while" loop in the pthread's call-back function to perform pause and resume(like the solution below). Because the "process" in ucos-ii can be paused or resumed at any time!
How to sleep or pause a PThread in c on Linux
I have found one solution on the web-site below, but it can't be built because it's out of date. It uses the process in Linux to simulate the task(acts like the process in our Linux) in ucos-ii.
http://www2.hs-esslingen.de/~zimmerma/software/index_uk.html
If pthread can act like the process which can be paused and resumed at any time, please tell me some related functions, I can figure it out myself. If it can't, I think I should focus on the older solution. Thanks a lot.
The Modula-3 garbage collector needs to suspend pthreads at an arbitrary time, not just when they are waiting on a condition variable or mutex. It does it by registering a (Unix) signal handler that suspends the thread and then using pthread_kill to send a signal to the target thread. I think it works (it has been reliable for others but I'm debugging an issue with it right now...) It's a bit kludgy, though....
Google for ThreadPThread.m3 and look at the routines "StopWorld" and "StartWorld". Handler itself is in ThreadPThreadC.c.
If stopping at specific points with a condition variable is insufficient, then you can't do this with pthreads. The pthread interface does not include suspend/resume functionality.
See, for example, answer E.4 here:
The POSIX standard provides no mechanism by which a thread A can suspend the execution of another thread B, without cooperation from B. The only way to implement a suspend/restart mechanism is to have B check periodically some global variable for a suspend request and then suspend itself on a condition variable, which another thread can signal later to restart B.
That FAQ answer goes on to describe a couple of non-standard ways of doing it, one in Solaris and one in LinuxThreads (which is now obsolete; do not confuse it with current threading on Linux); neither of those apply to your situation.
On Linux you can probably setup custom signal handler (eg. using signal()) that will contain wait for another signal (eg. using sigsuspend()). You then send the signals using pthread_kill() or tgkill(). It is important to use so-called "realtime signals" for this, because normal signals like SIGUSR1 and SIGUSR2 don't get queued, which means that they can get lost under high load conditions. You send a signal several times, but it gets received only once, because before while signal handler is running, new signals of the same kind are ignored. So if you have concurent threads doing PAUSE/RESUME , you can loose RESUME event and cause deadlock. On the other hand, the pending realtime signals (like SIGRTMIN+1 and SIGRTMIN+2) are not deduplicated, so there can be several same rt signals in queue at the same time.
DISCLAIMER: I had not tried this yet. But in theory it should work.
Also see man 7 signal-safety. There is a list of calls that you can safely call in signal handlers. Fortunately sigsuspend() seems to be one of them.
UPDATE: I have working code right here:
//Filename: pthread_pause.c
//Author: Tomas 'Harvie' Mudrunka 2021
//Build: CFLAGS=-lpthread make pthread_pause; ./pthread_pause
//Test: valgrind --tool=helgrind ./pthread_pause
//I've wrote this code as excercise to solve following stack overflow question:
// https://stackoverflow.com/questions/9397068/how-to-pause-a-pthread-any-time-i-want/68119116#68119116
#define _GNU_SOURCE //pthread_yield() needs this
#include <signal.h>
#include <pthread.h>
//#include <pthread_extra.h>
#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>
#include <errno.h>
#include <sys/resource.h>
#include <time.h>
#define PTHREAD_XSIG_STOP (SIGRTMIN+0)
#define PTHREAD_XSIG_CONT (SIGRTMIN+1)
#define PTHREAD_XSIGRTMIN (SIGRTMIN+2) //First unused RT signal
pthread_t main_thread;
sem_t pthread_pause_sem;
pthread_once_t pthread_pause_once_ctrl = PTHREAD_ONCE_INIT;
void pthread_pause_once(void) {
sem_init(&pthread_pause_sem, 0, 1);
}
#define pthread_pause_init() (pthread_once(&pthread_pause_once_ctrl, &pthread_pause_once))
#define NSEC_PER_SEC (1000*1000*1000)
// timespec_normalise() from https://github.com/solemnwarning/timespec/
struct timespec timespec_normalise(struct timespec ts)
{
while(ts.tv_nsec >= NSEC_PER_SEC) {
++(ts.tv_sec); ts.tv_nsec -= NSEC_PER_SEC;
}
while(ts.tv_nsec <= -NSEC_PER_SEC) {
--(ts.tv_sec); ts.tv_nsec += NSEC_PER_SEC;
}
if(ts.tv_nsec < 0) { // Negative nanoseconds isn't valid according to POSIX.
--(ts.tv_sec); ts.tv_nsec = (NSEC_PER_SEC + ts.tv_nsec);
}
return ts;
}
void pthread_nanosleep(struct timespec t) {
//Sleep calls on Linux get interrupted by signals, causing premature wake
//Pthread (un)pause is built using signals
//Therefore we need self-restarting sleep implementation
//IO timeouts are restarted by SA_RESTART, but sleeps do need explicit restart
//We also need to sleep using absolute time, because relative time is paused
//You should use this in any thread that gets (un)paused
struct timespec wake;
clock_gettime(CLOCK_MONOTONIC, &wake);
t = timespec_normalise(t);
wake.tv_sec += t.tv_sec;
wake.tv_nsec += t.tv_nsec;
wake = timespec_normalise(wake);
while(clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &wake, NULL)) if(errno!=EINTR) break;
return;
}
void pthread_nsleep(time_t s, long ns) {
struct timespec t;
t.tv_sec = s;
t.tv_nsec = ns;
pthread_nanosleep(t);
}
void pthread_sleep(time_t s) {
pthread_nsleep(s, 0);
}
void pthread_pause_yield() {
//Call this to give other threads chance to run
//Wait until last (un)pause action gets finished
sem_wait(&pthread_pause_sem);
sem_post(&pthread_pause_sem);
//usleep(0);
//nanosleep(&((const struct timespec){.tv_sec=0,.tv_nsec=1}), NULL);
//pthread_nsleep(0,1); //pthread_yield() is not enough, so we use sleep
pthread_yield();
}
void pthread_pause_handler(int signal) {
//Do nothing when there are more signals pending (to cleanup the queue)
//This is no longer needed, since we use semaphore to limit pending signals
/*
sigset_t pending;
sigpending(&pending);
if(sigismember(&pending, PTHREAD_XSIG_STOP)) return;
if(sigismember(&pending, PTHREAD_XSIG_CONT)) return;
*/
//Post semaphore to confirm that signal is handled
sem_post(&pthread_pause_sem);
//Suspend if needed
if(signal == PTHREAD_XSIG_STOP) {
sigset_t sigset;
sigfillset(&sigset);
sigdelset(&sigset, PTHREAD_XSIG_STOP);
sigdelset(&sigset, PTHREAD_XSIG_CONT);
sigsuspend(&sigset); //Wait for next signal
} else return;
}
void pthread_pause_enable() {
//Having signal queue too deep might not be necessary
//It can be limited using RLIMIT_SIGPENDING
//You can get runtime SigQ stats using following command:
//grep -i sig /proc/$(pgrep binary)/status
//This is no longer needed, since we use semaphores
//struct rlimit sigq = {.rlim_cur = 32, .rlim_max=32};
//setrlimit(RLIMIT_SIGPENDING, &sigq);
pthread_pause_init();
//Prepare sigset
sigset_t sigset;
sigemptyset(&sigset);
sigaddset(&sigset, PTHREAD_XSIG_STOP);
sigaddset(&sigset, PTHREAD_XSIG_CONT);
//Register signal handlers
//signal(PTHREAD_XSIG_STOP, pthread_pause_handler);
//signal(PTHREAD_XSIG_CONT, pthread_pause_handler);
//We now use sigaction() instead of signal(), because it supports SA_RESTART
const struct sigaction pause_sa = {
.sa_handler = pthread_pause_handler,
.sa_mask = sigset,
.sa_flags = SA_RESTART,
.sa_restorer = NULL
};
sigaction(PTHREAD_XSIG_STOP, &pause_sa, NULL);
sigaction(PTHREAD_XSIG_CONT, &pause_sa, NULL);
//UnBlock signals
pthread_sigmask(SIG_UNBLOCK, &sigset, NULL);
}
void pthread_pause_disable() {
//This is important for when you want to do some signal unsafe stuff
//Eg.: locking mutex, calling printf() which has internal mutex, etc...
//After unlocking mutex, you can enable pause again.
pthread_pause_init();
//Make sure all signals are dispatched before we block them
sem_wait(&pthread_pause_sem);
//Block signals
sigset_t sigset;
sigemptyset(&sigset);
sigaddset(&sigset, PTHREAD_XSIG_STOP);
sigaddset(&sigset, PTHREAD_XSIG_CONT);
pthread_sigmask(SIG_BLOCK, &sigset, NULL);
sem_post(&pthread_pause_sem);
}
int pthread_pause(pthread_t thread) {
sem_wait(&pthread_pause_sem);
//If signal queue is full, we keep retrying
while(pthread_kill(thread, PTHREAD_XSIG_STOP) == EAGAIN) usleep(1000);
pthread_pause_yield();
return 0;
}
int pthread_unpause(pthread_t thread) {
sem_wait(&pthread_pause_sem);
//If signal queue is full, we keep retrying
while(pthread_kill(thread, PTHREAD_XSIG_CONT) == EAGAIN) usleep(1000);
pthread_pause_yield();
return 0;
}
void *thread_test() {
//Whole process dies if you kill thread immediately before it is pausable
//pthread_pause_enable();
while(1) {
//Printf() is not async signal safe (because it holds internal mutex),
//you should call it only with pause disabled!
//Will throw helgrind warnings anyway, not sure why...
//See: man 7 signal-safety
pthread_pause_disable();
printf("Running!\n");
pthread_pause_enable();
//Pausing main thread should not cause deadlock
//We pause main thread here just to test it is OK
pthread_pause(main_thread);
//pthread_nsleep(0, 1000*1000);
pthread_unpause(main_thread);
//Wait for a while
//pthread_nsleep(0, 1000*1000*100);
pthread_unpause(main_thread);
}
}
int main() {
pthread_t t;
main_thread = pthread_self();
pthread_pause_enable(); //Will get inherited by all threads from now on
//you need to call pthread_pause_enable (or disable) before creating threads,
//otherwise first (un)pause signal will kill whole process
pthread_create(&t, NULL, thread_test, NULL);
while(1) {
pthread_pause(t);
printf("PAUSED\n");
pthread_sleep(3);
printf("UNPAUSED\n");
pthread_unpause(t);
pthread_sleep(1);
/*
pthread_pause_disable();
printf("RUNNING!\n");
pthread_pause_enable();
*/
pthread_pause(t);
pthread_unpause(t);
}
pthread_join(t, NULL);
printf("DIEDED!\n");
}
I am also working on library called "pthread_extra", which will have stuff like this and much more. Will publish soon.
UPDATE2: This is still causing deadlocks when calling pause/unpause rapidly (removed sleep() calls). Printf() implementation in glibc has mutex, so if you suspend thread which is in middle of printf() and then want to printf() from your thread which plans to unpause that thread later, it will never happen, because printf() is locked. Unfortunately i've removed the printf() and only run empty while loop in the thread, but i still get deadlocks under high pause/unpause rates. and i don't know why. Maybe (even realtime) Linux signals are not 100% safe. There is realtime signal queue, maybe it just overflows or something...
UPDATE3: i think i've managed to fix the deadlock, but had to completely rewrite most of the code. Now i have one (sig_atomic_t) variable per each thread which holds state whether that thread should be running or not. Works kinda like condition variable. pthread_(un)pause() transparently remembers this for each thread. I don't have two signals. now i only have one signal. handler of that signal looks at that variable and only blocks on sigsuspend() when that variable says the thread should NOT run. otherwise it returns from signal handler. in order to suspend/resume the thread i now set the sig_atomic_t variable to desired state and call that signal (which is common for both suspend and resume). It is important to use realtime signals to be sure handler will actualy run after you've modified the state variable. Code is bit complex because of the thread status database. I will share the code in separate solution as soon as i manage to simplify it enough. But i want to preserve the two signal version in here, because it kinda works, i like the simplicity and maybe people will give us more insight on how to optimize it.
UPDATE4: I've fixed the deadlock in original code (no need for helper variable holding the status) by using single handler for two signals and optimizing signal queue a bit. There is still some problem with printf() shown by helgrind, but it is not caused by my signals, it happens even when i do not call pause/unpause at all. Overall this was only tested on LINUX, not sure how portable the code is, because there seem to be some undocumented behaviour of signal handlers which was originaly causing the deadlock.
Please note that pause/unpause cannot be nested. if you pause 3 times, and unpause 1 time, the thread WILL RUN. If you need such behaviour, you should create some kind of wrapper which will count the nesting levels and signal the thread accordingly.
UPDATE5: I've improved robustness of the code by following changes: I ensure proper serialization of pause/unpause calls by use of semaphores. This hopefuly fixes last remaining deadlocks. Now you can be sure that when pause call returns, the target thread is actualy already paused. This also solves issues with signal queue overflowing. Also i've added SA_RESTART flag, which prevents internal signals from causing interuption of IO waits. Sleeps/delays still have to be restarted manualy, but i provide convenient wrapper called pthread_nanosleep() which does just that.
UPDATE6: i realized that simply restarting nanosleep() is not enough, because that way timeout does not run when thread is paused. Therefore i've modified pthread_nanosleep() to convert timeout interval to absolute time point in the future and sleep until that. Also i've hidden semaphore initialization, so user does not need to do that.
Here is example of thread function within a class with pause/resume functionality...
class SomeClass
{
public:
// ... construction/destruction
void Resume();
void Pause();
void Stop();
private:
static void* ThreadFunc(void* pParam);
pthread_t thread;
pthread_mutex_t mutex;
pthread_cond_t cond_var;
int command;
};
SomeClass::SomeClass()
{
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cond_var, NULL);
// create thread in suspended state..
command = 0;
pthread_create(&thread, NULL, ThreadFunc, this);
}
SomeClass::~SomeClass()
{
// we should stop the thread and exit ThreadFunc before calling of blocking pthread_join function
// also it prevents the mutex staying locked..
Stop();
pthread_join(thread, NULL);
pthread_cond_destroy(&cond_var);
pthread_mutex_destroy(&mutex);
}
void* SomeClass::ThreadFunc(void* pParam)
{
SomeClass* pThis = (SomeClass*)pParam;
timespec time_ns = {0, 50*1000*1000}; // 50 milliseconds
while(1)
{
pthread_mutex_lock(&pThis->mutex);
if (pThis->command == 2) // command to stop thread..
{
// be sure to unlock mutex before exit..
pthread_mutex_unlock(&pThis->mutex);
return NULL;
}
else if (pThis->command == 0) // command to pause thread..
{
pthread_cond_wait(&pThis->cond_var, &pThis->mutex);
// dont forget to unlock the mutex..
pthread_mutex_unlock(&pThis->mutex);
continue;
}
if (pThis->command == 1) // command to run..
{
// normal runing process..
fprintf(stderr, "*");
}
pthread_mutex_unlock(&pThis->mutex);
// it's important to give main thread few time after unlock 'this'
pthread_yield();
// ... or...
//nanosleep(&time_ns, NULL);
}
pthread_exit(NULL);
}
void SomeClass::Stop()
{
pthread_mutex_lock(&mutex);
command = 2;
pthread_cond_signal(&cond_var);
pthread_mutex_unlock(&mutex);
}
void SomeClass::Pause()
{
pthread_mutex_lock(&mutex);
command = 0;
// in pause command we dont need to signal cond_var because we not in wait state now..
pthread_mutex_unlock(&mutex);
}
void SomeClass::Resume()
{
pthread_mutex_lock(&mutex);
command = 1;
pthread_cond_signal(&cond_var);
pthread_mutex_unlock(&mutex);
}
I would like to visualise a running calculation in another thread with the visualisation tool kit in real time. The calculation spits out a new set of values to be visualised each iteration and the graphical thread must some how know this and load the new values.
One way to do this would be to have the main thread poll the state of the calculation. Ideally I'd not like to do any polling but if there is no other way then I will.
The best way I can think of would be to have the the calculation thread push an event onto the main thread's event queue every iteration of the calculation which is then processes by the GUI. I'm not sure how to go about doing this, or if it can be done in a thread safe manner.
I'm using vtk in gcc/C++ on linux using pthreads.
Listen to the Modified event on the object you're interested in, in the main thread using a vtkCommand (or appropriate derived class). You can then update your renderer and associated classes when the callback occurs.
But many VTK classes aren't thread-safe. You'll need to pause updation while rendering occurs. Otherwise, it'll segfault while trying to read and write the same memory.
I think it is a standard way. Create separate thread for window handling (i.e. window messages processing), and sometime put data into window (i.e. update the image).
Similar procedure with MathGL looks like following (see How I can create FLTK/GLUT/Qt window in parallel with calculation?)
//-----------------------------------------------------------------------------
#include <mgl/mgl_fltk.h>
#include <pthread.h>
#include <unistd.h>
mglPoint pnt; // some global variable for changable data
//-----------------------------------------------------------------------------
int sample(mglGraph *gr, void *)
{
gr->Box(); gr->Line(mglPoint(),pnt,"Ar2"); // just draw a vector
return 0;
}
//-----------------------------------------------------------------------------
void *mgl_fltk_tmp(void *) { mglFlRun(); return 0; }
int main (int argc, char ** argv)
{
mglGraphFLTK gr;
gr.Window(argc,argv,sample,"test"); // create window
static pthread_t tmp;
pthread_create(&tmp, 0, mgl_fltk_tmp, 0);
pthread_detach(tmp); // run window handling in the separate thread
for(int i=0;i<10;i++) // do calculation
{
sleep(1); // which can be very long
pnt = mglPoint(2*mgl_rnd()-1,2*mgl_rnd()-1);
gr.Update(); // update window
}
return 0; // finish calculations and close the window
}
//-----------------------------------------------------------------------------