qse/samples/si/thr02.cpp

302 lines
5.9 KiB
C++
Raw Permalink Normal View History

2018-01-26 10:03:58 +00:00
#include <qse/si/Thread.hpp>
2018-01-27 05:58:20 +00:00
#include <qse/si/mtx.h>
2018-01-26 10:03:58 +00:00
#include <qse/si/sio.h>
#include <qse/si/os.h>
2018-01-26 10:03:58 +00:00
#include <qse/cmn/mem.h>
#include <qse/cmn/str.h>
#include <qse/cmn/HeapMmgr.hpp>
2018-01-26 10:03:58 +00:00
#include <locale.h>
#if defined(_WIN32)
# include <windows.h>
#endif
#include <signal.h>
#include <string.h>
static int g_stopreq = 0;
static qse_ntime_t sleep_interval = { 1, 0 };
2018-01-26 10:03:58 +00:00
QSE::HeapMmgr g_heap_mmgr (30000, QSE::Mmgr::getDFL());
2018-01-26 10:03:58 +00:00
class MyThread: public QSE::Thread
{
public:
2018-01-27 05:58:20 +00:00
MyThread(): stopreq(0) {}
2018-01-26 10:03:58 +00:00
int main ()
{
int i = 0;
while (!this->stopreq)
{
2018-01-27 05:58:20 +00:00
qse_printf (QSE_T("m %p -> %d\n"), this, i);
2018-01-26 10:03:58 +00:00
i++;
qse_sleep (&sleep_interval);
2018-01-26 10:03:58 +00:00
}
return i;
}
int stopreq;
};
2018-01-27 16:35:02 +00:00
class Functor
{
public:
int operator() (QSE::Thread* thr)
{
int i = 0;
int* stopreqptr = (int*)thr->getContext();
while (!*stopreqptr)
{
qse_printf (QSE_T("fc %p -> %d\n"), this, i);
i++;
qse_sleep (&sleep_interval);
2018-01-27 16:35:02 +00:00
}
return i;
}
};
class FunctorWithI: public Functor
{
public:
FunctorWithI (int* x) {}
};
static int func_ptr (QSE::Thread* thr)
2018-01-26 10:03:58 +00:00
{
int i = 0;
int* stopreqptr = (int*)thr->getContext();
while (!*stopreqptr)
{
qse_printf (QSE_T("fp %p -> %d\n"), thr, i);
i++;
qse_sleep (&sleep_interval);
}
2018-01-26 10:03:58 +00:00
return i;
}
static int test1 (void)
{
2018-01-27 16:35:02 +00:00
int localstopreq = 0;
2018-01-29 09:25:47 +00:00
#if defined(QSE_LANG_CPP11)
2018-01-27 16:35:02 +00:00
auto lambda = [](QSE::Thread* thr)->int
{
2018-01-27 05:58:20 +00:00
int i = 0;
int* stopreqptr = (int*)thr->getContext();
2018-01-26 10:03:58 +00:00
2018-01-27 05:58:20 +00:00
while (!*stopreqptr)
{
qse_printf (QSE_T("l %p -> %d\n"), thr, i);
i++;
qse_sleep (&sleep_interval);
2018-01-27 05:58:20 +00:00
}
2018-01-26 10:03:58 +00:00
2018-01-27 05:58:20 +00:00
return i;
};
2018-01-26 10:03:58 +00:00
2018-01-27 16:35:02 +00:00
auto lambda_with_capture = [&localstopreq](QSE::Thread* thr)->int
{
2018-01-26 10:03:58 +00:00
int i = 0;
2018-01-27 05:58:20 +00:00
while (!localstopreq)
2018-01-26 10:03:58 +00:00
{
2018-01-27 05:58:20 +00:00
qse_printf (QSE_T("lc %p -> %d\n"), thr, i);
2018-01-26 10:03:58 +00:00
i++;
qse_sleep (&sleep_interval);
2018-01-26 10:03:58 +00:00
}
return i;
};
#endif
2018-01-26 10:03:58 +00:00
MyThread thr1;
thr1.setStackSize (64000);
2018-01-27 05:58:20 +00:00
if (thr1.start(QSE::Thread::SIGNALS_BLOCKED) <= -1)
{
qse_printf (QSE_T("cannot start thread1\n"));
return -1;
}
QSE::ThreadR thr2 (&g_heap_mmgr);
thr2.setStackSize (64000);
thr2.setContext (&localstopreq);
#if defined(QSE_LANG_CPP11)
2018-01-27 05:58:20 +00:00
// the lambda expression with no capture can be passed as a function pointer
// as long as the signature matches QSE::Thread::ThreadRoutine.
if (thr2.start(lambda, QSE::Thread::SIGNALS_BLOCKED) <= -1)
#else
if (thr2.start(func_ptr, QSE::Thread::SIGNALS_BLOCKED) <= -1)
#endif
2018-01-26 10:03:58 +00:00
{
2018-01-27 05:58:20 +00:00
qse_printf (QSE_T("cannot start thread2\n"));
2018-01-26 10:03:58 +00:00
return -1;
}
#if defined(QSE_LANG_CPP11)
2018-01-29 05:02:51 +00:00
QSE::ThreadF<decltype(lambda)> thr3 (lambda);
2018-01-27 16:35:02 +00:00
thr3.setStackSize (64000);
thr3.setContext (&localstopreq);
if (thr3.start(QSE::Thread::SIGNALS_BLOCKED) <= -1)
2018-01-27 05:58:20 +00:00
{
qse_printf (QSE_T("cannot start thread3\n"));
return -1;
}
2018-01-27 16:35:02 +00:00
// turn a lambda with capture to a thread
2018-01-29 05:02:51 +00:00
QSE::ThreadF<decltype(lambda_with_capture)> thr4 (lambda_with_capture);
2018-01-27 16:35:02 +00:00
thr4.setStackSize (64000);
if (thr4.start(QSE::Thread::SIGNALS_BLOCKED) <= -1)
{
qse_printf (QSE_T("cannot start thread4\n"));
return -1;
}
2018-01-29 09:25:47 +00:00
QSE::ThreadL<int(QSE::Thread*)> thr5;
thr5.setStackSize (64000);
if (thr5.start(
([&localstopreq, &thr5](QSE::Thread* thr) {
int i = 0;
while (!localstopreq)
{
qse_printf (QSE_T("tl %p -> %d\n"), thr, i);
i++;
qse_sleep (&sleep_interval);
2018-01-29 09:25:47 +00:00
}
return i;
}),
QSE::Thread::SIGNALS_BLOCKED) <= -1)
{
qse_printf (QSE_T("cannot start thread5\n"));
return -1;
}
#endif
2018-01-27 16:35:02 +00:00
// turn a functor to a thread
2018-01-29 09:25:47 +00:00
QSE::ThreadF<Functor> thr6;
thr6.setStackSize (64000);
thr6.setContext (&localstopreq);
if (thr6.start(QSE::Thread::SIGNALS_BLOCKED) <= -1)
2018-01-27 16:35:02 +00:00
{
2018-01-29 09:25:47 +00:00
qse_printf (QSE_T("cannot start thread6\n"));
2018-01-27 16:35:02 +00:00
return -1;
}
2018-01-27 05:58:20 +00:00
{
int t = 20;
QSE::ThreadFD<FunctorWithI, int*> thr7 (&t);
// just keep this here to see if QSE::ThreadFD<> can be instantiated syntatically
}
2018-01-26 10:03:58 +00:00
while (!g_stopreq)
{
2018-01-27 05:58:20 +00:00
if (thr1.getState() == QSE::Thread::TERMINATED &&
thr2.getState() == QSE::Thread::TERMINATED &&
#if defined(QSE_LANG_CPP11)
2018-01-27 16:35:02 +00:00
thr3.getState() == QSE::Thread::TERMINATED &&
thr4.getState() == QSE::Thread::TERMINATED &&
2018-01-29 09:25:47 +00:00
thr5.getState() == QSE::Thread::TERMINATED &&
#endif
2018-01-29 09:25:47 +00:00
thr6.getState() == QSE::Thread::TERMINATED) break;
qse_sleep (&sleep_interval);
2018-01-26 10:03:58 +00:00
}
if (g_stopreq)
{
2018-01-27 05:58:20 +00:00
localstopreq = 1;
2018-01-27 16:35:02 +00:00
thr1.stopreq = 1;
2018-01-26 10:03:58 +00:00
}
2018-01-27 05:58:20 +00:00
thr1.join ();
thr2.join ();
#if defined(QSE_LANG_CPP11)
2018-01-27 05:58:20 +00:00
thr3.join ();
2018-01-27 16:35:02 +00:00
thr4.join ();
thr5.join ();
2018-01-29 09:25:47 +00:00
#endif
thr6.join ();
2018-01-27 16:35:02 +00:00
2018-01-27 05:58:20 +00:00
qse_printf (QSE_T("thread1 ended with retcode %d\n"), thr1.getReturnCode());
qse_printf (QSE_T("thread2 ended with retcode %d\n"), thr2.getReturnCode());
#if defined(QSE_LANG_CPP11)
2018-01-27 05:58:20 +00:00
qse_printf (QSE_T("thread3 ended with retcode %d\n"), thr3.getReturnCode());
2018-01-27 16:35:02 +00:00
qse_printf (QSE_T("thread4 ended with retcode %d\n"), thr4.getReturnCode());
qse_printf (QSE_T("thread5 ended with retcode %d\n"), thr5.getReturnCode());
2018-01-29 09:25:47 +00:00
#endif
qse_printf (QSE_T("thread6 ended with retcode %d\n"), thr6.getReturnCode());
2018-01-26 10:03:58 +00:00
return 0;
}
static void handle_sigint (int sig, siginfo_t* siginfo, void* ctx)
{
g_stopreq = 1;
}
static void set_signal (int sig, void(*handler)(int, siginfo_t*, void*))
{
struct sigaction sa;
memset (&sa, 0, sizeof(sa));
/*sa.sa_handler = handler;*/
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = handler;
sigemptyset (&sa.sa_mask);
sigaction (sig, &sa, NULL);
}
static void set_signal_to_default (int sig)
{
struct sigaction sa;
memset (&sa, 0, sizeof(sa));
sa.sa_handler = SIG_DFL;
sa.sa_flags = 0;
sigemptyset (&sa.sa_mask);
sigaction (sig, &sa, NULL);
}
int main ()
{
#if defined(_WIN32)
char locale[100];
UINT codepage = GetConsoleOutputCP();
if (codepage == CP_UTF8)
{
/*SetConsoleOutputCP (CP_UTF8);*/
2018-01-26 10:03:58 +00:00
qse_setdflcmgrbyid (QSE_CMGR_UTF8);
}
else
{
qse_mbsxfmt (locale, QSE_COUNTOF(locale), ".%u", (unsigned int)codepage);
2018-01-26 10:03:58 +00:00
setlocale (LC_ALL, locale);
/*qse_setdflcmgrbyid (QSE_CMGR_SLMB);*/
}
#else
setlocale (LC_ALL, "");
/*qse_setdflcmgrbyid (QSE_CMGR_SLMB);*/
#endif
set_signal (SIGINT, handle_sigint);
qse_open_stdsios ();
2018-01-27 05:58:20 +00:00
test1();
2018-01-26 10:03:58 +00:00
qse_close_stdsios ();
set_signal_to_default (SIGINT);
return 0;
}