#include #include #include #include #include #include #include #include #if defined(_WIN32) # include #endif #include #include static int g_stopreq = 0; static qse_ntime_t sleep_interval = { 1, 0 }; QSE::HeapMmgr g_heap_mmgr (30000, QSE::Mmgr::getDFL()); class MyThread: public QSE::Thread { public: MyThread(): stopreq(0) {} int main () { int i = 0; while (!this->stopreq) { qse_printf (QSE_T("m %p -> %d\n"), this, i); i++; qse_sleep (&sleep_interval); } return i; } int stopreq; }; 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); } return i; } }; class FunctorWithI: public Functor { public: FunctorWithI (int* x) {} }; static int func_ptr (QSE::Thread* thr) { 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); } return i; } static int test1 (void) { int localstopreq = 0; #if defined(QSE_LANG_CPP11) auto lambda = [](QSE::Thread* thr)->int { int i = 0; int* stopreqptr = (int*)thr->getContext(); while (!*stopreqptr) { qse_printf (QSE_T("l %p -> %d\n"), thr, i); i++; qse_sleep (&sleep_interval); } return i; }; auto lambda_with_capture = [&localstopreq](QSE::Thread* thr)->int { int i = 0; while (!localstopreq) { qse_printf (QSE_T("lc %p -> %d\n"), thr, i); i++; qse_sleep (&sleep_interval); } return i; }; #endif MyThread thr1; thr1.setStackSize (64000); 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) // 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 { qse_printf (QSE_T("cannot start thread2\n")); return -1; } #if defined(QSE_LANG_CPP11) QSE::ThreadF thr3 (lambda); thr3.setStackSize (64000); thr3.setContext (&localstopreq); if (thr3.start(QSE::Thread::SIGNALS_BLOCKED) <= -1) { qse_printf (QSE_T("cannot start thread3\n")); return -1; } // turn a lambda with capture to a thread QSE::ThreadF thr4 (lambda_with_capture); thr4.setStackSize (64000); if (thr4.start(QSE::Thread::SIGNALS_BLOCKED) <= -1) { qse_printf (QSE_T("cannot start thread4\n")); return -1; } QSE::ThreadL 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); } return i; }), QSE::Thread::SIGNALS_BLOCKED) <= -1) { qse_printf (QSE_T("cannot start thread5\n")); return -1; } #endif // turn a functor to a thread QSE::ThreadF thr6; thr6.setStackSize (64000); thr6.setContext (&localstopreq); if (thr6.start(QSE::Thread::SIGNALS_BLOCKED) <= -1) { qse_printf (QSE_T("cannot start thread6\n")); return -1; } { int t = 20; QSE::ThreadFD thr7 (&t); // just keep this here to see if QSE::ThreadFD<> can be instantiated syntatically } while (!g_stopreq) { if (thr1.getState() == QSE::Thread::TERMINATED && thr2.getState() == QSE::Thread::TERMINATED && #if defined(QSE_LANG_CPP11) thr3.getState() == QSE::Thread::TERMINATED && thr4.getState() == QSE::Thread::TERMINATED && thr5.getState() == QSE::Thread::TERMINATED && #endif thr6.getState() == QSE::Thread::TERMINATED) break; qse_sleep (&sleep_interval); } if (g_stopreq) { localstopreq = 1; thr1.stopreq = 1; } thr1.join (); thr2.join (); #if defined(QSE_LANG_CPP11) thr3.join (); thr4.join (); thr5.join (); #endif thr6.join (); 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) qse_printf (QSE_T("thread3 ended with retcode %d\n"), thr3.getReturnCode()); qse_printf (QSE_T("thread4 ended with retcode %d\n"), thr4.getReturnCode()); qse_printf (QSE_T("thread5 ended with retcode %d\n"), thr5.getReturnCode()); #endif qse_printf (QSE_T("thread6 ended with retcode %d\n"), thr6.getReturnCode()); 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);*/ qse_setdflcmgrbyid (QSE_CMGR_UTF8); } else { qse_mbsxfmt (locale, QSE_COUNTOF(locale), ".%u", (unsigned int)codepage); 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 (); test1(); qse_close_stdsios (); set_signal_to_default (SIGINT); return 0; }