아래 코드는 Fl::awake(callback)
을 사용하는 비교적 간단한 FLTK 1.3 응용 프로그램의 예입니다. 이 코드는 FLTK의 테스트 디렉토리에 있습니다. 소스를 가져 오면 다양한 예제를 찾을 수 있습니다. 우리에게 코드를주지 않았지만 Fl::lock()
및 나중에 Fl::unlock()
을 스레드에 호출하지 않았다고 가정합니다. 해당 섹션 외부 위젯에 액세스하지 말아야 때문에
가 실제로 잠금을 호출하고 난 메인 스레드의 외부 위젯에 액세스하지 않기 때문에 잠금이 해제되지 않습니다
#if HAVE_PTHREAD || defined(WIN32)
# include <FL/Fl.H>
# include <FL/Fl_Double_Window.H>
# include <FL/Fl_Browser.H>
# include <FL/Fl_Value_Output.H>
# include <FL/fl_ask.H>
# include "threads.h"
# include <stdio.h>
# include <math.h>
Fl_Thread prime_thread;
Fl_Browser *browser1, *browser2;
Fl_Value_Output *value1, *value2;
int start2 = 3;
void magic_number_cb(void *p)
{
Fl_Value_Output *w = (Fl_Value_Output*)p;
w->labelcolor(FL_RED);
w->redraw_label();
}
void* prime_func(void* p)
{
Fl_Browser* browser = (Fl_Browser*) p;
Fl_Value_Output *value;
int n;
int step;
char proud = 0;
if (browser == browser2) {
n = start2;
start2 += 2;
step = 12;
value = value2;
} else {
n = 3;
step = 2;
value = value1;
}
// very simple prime number calculator !
//
// The return at the end of this function can never be reached and thus
// will generate a warning with some compilers, however we need to have
// a return statement or other compilers will complain there is no return
// statement. To avoid warnings on all compilers, we fool the smart ones
// into beleiving that there is a chance that we reach the end by testing
// n>=0, knowing that logically, n will never be negative in this context.
if (n>=0) for (;;) {
int pp;
int hn = (int)sqrt((double)n);
for (pp=3; pp<=hn; pp+=2) if (n%pp == 0) break;
if (pp >= hn) {
char s[128];
sprintf(s, "%d", n);
// Obtain a lock before we access the browser widget...
Fl::lock();
browser->add(s);
browser->bottomline(browser->size());
if (n > value->value()) value->value(n);
n += step;
// Release the lock...
Fl::unlock();
// Send a message to the main thread, at which point it will
// process any pending redraws for our browser widget. The
// message we pass here isn't used for anything, so we could also
// just pass NULL.
Fl::awake(p);
if (n>10000 && !proud) {
proud = 1;
Fl::awake(magic_number_cb, value);
}
} else {
// This should not be necessary since "n" and "step" are local variables,
// however it appears that at least MacOS X has some threading issues
// that cause semi-random corruption of the (stack) variables.
Fl::lock();
n += step;
Fl::unlock();
}
}
return 0L;
}
int main(int argc, char **argv)
{
Fl_Double_Window* w = new Fl_Double_Window(200, 200, "Single Thread");
browser1 = new Fl_Browser(0, 0, 200, 175);
w->resizable(browser1);
value1 = new Fl_Value_Output(100, 175, 200, 25, "Max Prime:");
w->end();
w->show(argc, argv);
w = new Fl_Double_Window(200, 200, "Six Threads");
browser2 = new Fl_Browser(0, 0, 200, 175);
w->resizable(browser2);
value2 = new Fl_Value_Output(100, 175, 200, 25, "Max Prime:");
w->end();
w->show();
browser1->add("Prime numbers:");
browser2->add("Prime numbers:");
// Enable multi-thread support by locking from the main
// thread. Fl::wait() and Fl::run() call Fl::unlock() and
// Fl::lock() as needed to release control to the child threads
// when it is safe to do so...
Fl::lock();
// Start threads...
// One thread displaying in one browser
fl_create_thread(prime_thread, prime_func, browser1);
// Several threads displaying in another browser
fl_create_thread(prime_thread, prime_func, browser2);
fl_create_thread(prime_thread, prime_func, browser2);
fl_create_thread(prime_thread, prime_func, browser2);
fl_create_thread(prime_thread, prime_func, browser2);
fl_create_thread(prime_thread, prime_func, browser2);
fl_create_thread(prime_thread, prime_func, browser2);
Fl::run();
return 0;
}
#else
# include <FL/fl_ask.H>
int main() {
fl_alert("Sorry, threading not supported on this platform!");
}
#endif // HAVE_PTHREAD || WIN32
를 포함 ... 필수적이다. 신호 메커니즘으로 깨어났습니다. 메인의 잠금 호출은 올바른 방향으로 나를 가리켜 주신 덕분이었습니다. –
참고 :이 코드는 백그라운드에서 "처리"스레드를 실행하면서 GUI가 여전히 응답하도록하지만이 구현으로 인해 응답이없는 GUI에서 처리 스레드가 멈추게 할 수 있습니다. 예를 들어, 창의 크기를 조정하고 크기를 조정하는 동안 마우스를 끌면 GUI 이벤트 작성을 중지 할 때까지 소수의 계산이 중지됩니다. Fl :: awake()를 호출해도 주 스레드가 awake() 이벤트를 알 수 있도록 잠금/잠금 해제가 여전히 필요하므로 문제를 피할 수 없습니다. 따라서 "처리"스레드를 GUI에서 제외 시키려면 FLTK 호출을 수행 할 수 없습니다. – cape1232
약간의 관련이 없지만 추가하겠습니다 : ** 주 함수에서'Fl :: lock()'을 호출하는 것이 매우 중요합니다. ** 그 호출없이 프로그램을 작성하려고했는데, 투쟁. – bcdan