Coffee break: Here's a worked example based on the OP code - though note that I had to "de-C++ify" it to make it work with the somewhat ancient compiler on this particular machine!
#include <memory>
#include <string>
#include "FL/Fl.H"
#include "FL/Fl_Double_Window.H"
#include "FL/Fl_Browser.H"
#include "FL/Fl_Button.H"
#include "FL/Fl_Toggle_Button.H"
#ifdef _WIN32
# include <process.h>
typedef unsigned long Fl_Thread;
extern "C" {
typedef void * (__cdecl Fl_Thread_Func) (void *);
}
static int fl_create_thread (Fl_Thread &t, Fl_Thread_Func *f, void *p)
{
return t = (Fl_Thread)_beginthread ((void (__cdecl *) (void *))f, 0, p);
}
#define DELAY(XX) Sleep(XX)
#else
# include <pthread.h>
typedef pthread_t Fl_Thread;
extern "C" {
typedef void * (Fl_Thread_Func) (void *);
}
static int fl_create_thread (Fl_Thread &t, Fl_Thread_Func *f, void *p)
{
return pthread_create ((pthread_t *)&t, 0, f, p);
}
#define DELAY(XX) usleep(XX * 1000)
#endif
static Fl_Thread t = (Fl_Thread)0;
static volatile bool thread_alive = false;
static bool keep_alive = false;
static void run_once (Fl_Button *, void *);
static void run_many (Fl_Button *, void *);
class UI
{
public:
Fl_Double_Window *window;
Fl_Browser *output;
UI()
{
{
window = new Fl_Double_Window (660, 420, "Thread Test");
window->begin();
Fl_Button *bt = new Fl_Button (445, 370, 190, 30, "Run Once");
bt->labelfont (1);
bt->labelsize (16);
bt->callback ((Fl_Callback *)run_once);
bt = new Fl_Toggle_Button (445, 330, 190, 30, "Run Many");
bt->labelfont (1);
bt->labelsize (16);
bt->callback ((Fl_Callback *)run_many);
output = new Fl_Browser (25, 40, 395, 275);
output->box (FL_BORDER_BOX);
output->textfont (4);
}
}
};
static std::unique_ptr<UI> ui;
static volatile bool in_use = false;
static char text_buffer [128];
static void awake (void *)
{
if (in_use)
{
ui->output->add (text_buffer);
int ln = ui->output->size();
ui->output->bottomline (ln);
in_use = false;
}
}
static void output (const char *pc)
{
if (!in_use)
{
snprintf (text_buffer, 128, "@S14@C92@.%s", pc);
in_use = true;
puts (text_buffer);
Fl::awake (awake, NULL);
}
}
static void output (std::string s)
{
output (s.c_str());
}
static void *thread (void *)
{
while (thread_alive)
{
output ("a");
DELAY (1000);
output ("b");
unsigned temp = 1;
for (int i = 1; i < 1000000000; i++)
{
temp += i;
}
output (std::to_string (temp));
if (!keep_alive)
{
thread_alive = false;
}
else
{
// busy wait for awake to flush the previous message
while (in_use);
}
}
// busy wait for awake to flush the message
while (in_use);
output ("Worker Thread Exit");
t = (Fl_Thread)0;
return NULL;
}
static void run_once (Fl_Button *, void *)
{
if (!t)
{
thread_alive = true;
fl_create_thread (t, thread, NULL);
}
}
static void run_many (Fl_Button *, void *)
{
if (!t)
{
thread_alive = true;
keep_alive = true;
fl_create_thread (t, thread, NULL);
}
else
{
keep_alive = false;
}
}
int main (int argc, char *argv[])
{
ui = std::make_unique<UI>();
Fl::lock();
ui->window->show (argc, argv);
// Only the first of these strings will appear, since the
// worker thread is
for (int i = 0; i < 20; i++)
{
char buf [32];
snprintf (buf, 32, "%d", i);
ui->output->add (buf);
int ln = ui->output->size();
ui->output->bottomline (ln);
}
Fl::run();
// Tell the worker to expire - if it is still alive!
keep_alive = false;
thread_alive = false;
return 0;
}
// end of file