2012-01-02 13 views
5

मैं अगर स्थानीय चर आरंभ में विफल रहता है मैं की जरूरत है mainloop में, एक धागा mainloopबहुत लंबे समय तक अवरुद्ध किए बिना pthread_create से प्रारंभिक निकास का पता कैसे लगाएं?

यानी

int run_mainloop; 

void* mainloop(void* param) 
{ 
    // local vars 
    // initialize local vars 

    while(run_mainloop) 
    { 
     // run mainloop 
    } 

    return 0; 
} 

कहा जाता धागा एक समारोह client_open कहा जाता है से शुरू हुआ है, यानी

int client_open() 
{ 
    run_mainloop = 1; 
    return pthread_create(&thread, NULL, mainloop, NULL);  
} 
हालांकि

है जल्दी से बाहर निकलने के तुरंत client_open को सूचित करने के लिए।

pthread_join अनुचित है क्योंकि यह अवरुद्ध होगा और मेरे पास client_open ब्लॉक नहीं हो सकता है। यदि यह लौटने से पहले थोड़े समय का इंतजार करना था तो यह ठीक रहेगा।

मैं इसे pthread_join का उपयोग किए बिना एक अच्छा तरीके से कैसे कर सकता हूं जो ब्लॉक करेगा। मैं रिटर्न कोड प्राप्त करने में सक्षम होना चाहता हूं।

+3

जैसा कि आप लिनक्स का उपयोग कर रहे हैं, आप 'pthread_tryjoin_np' का उपयोग कर सकते हैं - लेकिन 'np' यहां" पोर्टेबल "के लिए खड़ा है! – fge

+0

fge, यह ठीक होगा क्योंकि यह केवल एक लिनक्स कार्यान्वयन है। क्या आप एक उत्तर के रूप में सुझाव देना चाहते हैं और शायद एक विकल्प सुझा सकते हैं? – Matt

उत्तर

4

pthread_tryjoin_np का उपयोग गलत होगा: नए धागे को pthread_create रिटर्न के बीच मनमाने ढंग से देरी हो सकती है, और नया धागा वास्तव में प्रारंभिक कोड निष्पादित करता है।

यदि आप उस देरी के दौरान pthread_tryjoin_np करते हैं, तो आप असफल हो जाएंगे और आप तय करेंगे कि सब कुछ "ठीक है", वास्तव में यह नहीं है।

आप जो चाहते हैं वह एक शर्त है: client_open इस पर प्रतीक्षा करेगा, और mainloop इसे संकेत देगा (प्रारंभिकरण के साथ किया जा रहा है)।

4

आप completion variables के नाम से जाना जाने वाला कुछ उपयोग कर सकते हैं।

एक धागा का उपयोग तब तक कर सकता है जब तक कि नव निर्मित धागे प्रारंभिकरण समाप्त नहीं हो जाता। एकमात्र पकड़ यह है कि प्रारंभिक विफल होने पर भी, नए धागे को हमेशा प्रारंभिक समापन को संकेत देना चाहिए। निम्नलिखित लाइनों के साथ

कुछ (त्रुटि हैंडलिंग स्पष्टता के लिए छोड़े गए):

#include <pthread.h> 

// Completion variable definition:  
typedef struct { 
    pthread_mutex_t mtx; 
    pthread_cond_t cnd; 
    int completed; 
    int return_code; 
} Completion; 

#define COMPLETION_INIT { PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, 0, 0 } 

int completion_wait(Completion* c) { // add timeout if necessary 
    pthread_mutex_lock(&c->mtx); 
    while(!c->completed) 
     pthread_cond_wait(&c->cnd, &c->mtx); 
    int return_code = c->return_code; 
    pthread_mutex_unlock(&c->mtx); 
    return return_code; 
} 

void completion_signal(Completion* c, int return_code) { 
    pthread_mutex_lock(&c->mtx); 
    c->completed = 1; 
    c->return_code = return_code; 
    pthread_cond_signal(&c->cnd); 
    pthread_mutex_unlock(&c->mtx); 
} 

// Usage:  

void* mainloop(void* vc) { 
    int init_success = 0; 
    // initialization 
    // ... 
    init_success = 1; 

init_end: 
    Completion* c = (Completion*)vc; 
    completion_signal(c, init_success); // always signal 
    if(!init_success) 
     return NULL; 

    // start the main loop 
    return NULL; 
} 

int client_open() 
{ 
    int run_mainloop = 1; 
    pthread_t thread; 
    Completion c = COMPLETION_INIT; 
    pthread_create(&thread, NULL, mainloop, &c); 
    pthread_detach(thread); 
    return completion_wait(&c); 
} 
-1

ठीक है, मैं तीन तरीके यह करने के लिए की खोज की।

1) प्रारंभ करने से पहले मेनलोप में चर शुरू करें और पास करें।

2) में शामिल होने के रूप में इसके लिए धागा बनाया जा करने के लिए समय की अनुमति देता है संस्करण इस मामले में और अधिक उपयुक्त है और initialisation किया जाना के लिए लिनक्स विशिष्ट pthread_tryjoin_np() या pthread_timedjoin_np() मैं समय लगता है का उपयोग करें। टाइमआउट को लंबे समय तक नहीं होना चाहिए, इसलिए यह कॉलर को क्लाइंट_ओपेन() को बहुत लंबे समय तक अवरुद्ध नहीं करेगा।

हालांकि, जैसा कि @fge द्वारा इंगित किया गया है वे गैर-पोर्टेबल हैं। हालांकि यह एक समस्या का बहुत अधिक नहीं है, मैंने एक वैकल्पिक तरीके के बारे में सोचा जो यह है।


संपादित करें: नहीं इस तरह के एक अच्छा समाधान है, लेकिन यहां संदर्भ के लिए छोड़ दिया जाए। एक शर्त चर का उपयोग करके खोलने के लिए सिग्नल करना बेहतर होगा कि प्रारंभिकता ठीक थी।

3) जांचें कि run_mainloop गैर-शून्य है, अगर यह है और pthread_create विफल नहीं हुआ है और धागा चल रहा है। यदि यह एक समय के बाद भी शून्य है तो यह शुरू नहीं हुआ है इसलिए हम निकास कोड प्राप्त करने के लिए pthread_join को कॉल करते हैं।

int run_mainloop = 0; 

void* mainloop(void* param) 
{ 
    // init vars 
    // if failure, exit early. 

    // everything from this point on is good. 
    run_mainloop = 1; 
    while (run_mainloop)) 
    { 
     // do styff 
    } 

    return 0; 
} 

int client_open() 
{ 
    void* res; 
    int rc = pthread_create(&g_thread_id, NULL, mainloop, NULL); 
    if (rc != 0) 
     return -1; 

    usleep(100); // wait a little while, kinda dumb but allows time for init 
    if (run_mainloop)) 
     return 0; 

    pthread_join(g_thread_id, &res); 
    return -1; 
} 
+0

आपका तीसरा समाधान दूसरे के बराबर है, और एक ही दौड़ से पीड़ित है: क्या होगा यदि मेनलोप थ्रेड 100 से अधिक माइक्रोसेकंडों में देरी हो? –

+0

तीसरे विकल्प के साथ जाएं हालांकि एक शर्त चर का उपयोग करें जिसे आप हमेशा 'usleep' के बजाय सेट करते हैं। फिर 'client_open' में स्थिति चर सेट करने के लिए प्रतीक्षा करें और फिर जांचें कि' run_mainloop' 1 या 0 है या नहीं। मूल रूप से @EmployedRussian ने क्या सुझाव दिया है। – ChrisWue

+0

असल में, पहला समाधान यह सबसे साफ लगता है कि सभी – fge

संबंधित मुद्दे