2011-11-09 3 views
1

FLTK 프로그램의 주 루프에서 함수를 호출하기 위해 Fl :: awake (콜백) 함수를 사용하고 싶습니다. 나는 F1 :: awake를 자식 스레드에서 호출하고 있는데, 성공 (1)을 리턴하지만, 함수는 결코 호출되지 않는다. 나는 Fl :: wait()를 메인 쓰레드의 루프에서 호출한다. 이 문제를 해결할 수있는 방법이 있습니까?FLTK 라이브러리에서 Fl :: awake를 사용하는 방법

답변

0

아래 코드는 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 
+0

를 포함 ... 필수적이다. 신호 메커니즘으로 깨어났습니다. 메인의 잠금 호출은 올바른 방향으로 나를 가리켜 주신 덕분이었습니다. –

+0

참고 :이 코드는 백그라운드에서 "처리"스레드를 실행하면서 GUI가 여전히 응답하도록하지만이 구현으로 인해 응답이없는 GUI에서 처리 스레드가 멈추게 할 수 있습니다. 예를 들어, 창의 크기를 조정하고 크기를 조정하는 동안 마우스를 끌면 GUI 이벤트 작성을 중지 할 때까지 소수의 계산이 중지됩니다. Fl :: awake()를 호출해도 주 스레드가 awake() 이벤트를 알 수 있도록 잠금/잠금 해제가 여전히 필요하므로 문제를 피할 수 없습니다. 따라서 "처리"스레드를 GUI에서 제외 시키려면 FLTK 호출을 수행 할 수 없습니다. – cape1232

+0

약간의 관련이 없지만 추가하겠습니다 : ** 주 함수에서'Fl :: lock()'을 호출하는 것이 매우 중요합니다. ** 그 호출없이 프로그램을 작성하려고했는데, 투쟁. – bcdan

관련 문제