2012-12-15 18 views
22

संभव डुप्लिकेट:
C++0x thread interruptionमैं अपने थ्रेड ऑब्जेक्ट का उपयोग कर std :: थ्रेड को मारना चाहता हूं?

मैं को मारने के लिए कोशिश कर रहा हूँ/अपने धागा वस्तु का उपयोग करके एक C++ std :: धागा बंद करो।

हम यह कैसे कर सकते हैं?

+2

संबंधित: http://stackoverflow.com/questions/2790346/c0x-thread-Interruption – zch

उत्तर

22

आप नहीं कर सकते।

std::threads इंटरप्टिबल नहीं हैं। आप boost::thread का उपयोग कर सकते हैं जो इस सुविधा को प्रदान करता है।

बूस्ट इसे "इंटरप्ट पॉइंट" को परिभाषित करके करता है जिस पर धागा समाप्त हो जाता है और इस तरह के बिंदु तक पहुंच जाता है।

फिर भी, अधिकांश समय एक रीडिज़ाइन के बारे में सोचने के बारे में सोचने का सबसे आसान और आसान तरीका हो सकता है जो आप प्राप्त करने की कोशिश कर रहे हैं।

यदि आप अभी भी एंटीनी विलियम्स (बूस्ट थ्रेड के मालिक) पुस्तक "सी ++ कंसुरेंसी इन एक्शन" बुक में इंटरप्टिबल थ्रेड चेकआउट के सी ++ 11 कार्यान्वयन की तलाश में हैं। वह बुनियादी कार्यान्वयन के माध्यम से जाता है कि इस तरह की चीज़ कैसे हासिल की जा सकती है।

std::thread::native_handle आपको प्लेटफ़ॉर्म विशिष्ट अंतर्निहित थ्रेड हैंडल तक पहुंच प्रदान करता है जो बाधा उत्पन्न करने का समर्थन कर सकता है, हालांकि यह दृष्टिकोण आपके कोड को अक्षम नहीं करता है और शायद किसी भी तरह से क्लीनर नहीं बनाता है।

34

@ बांस का जवाब अच्छा है, हालांकि मुझे लगता है कि यह एक मजबूत कथन का हकदार है।

जो भी भाषा आप उपयोग करते हैं, आपका प्रोग्राम संसाधनों को प्राप्त और रिलीज करेगा: मेमोरी, फाइल डिस्क्रिप्टर, ... एक शॉट में निकाले गए सरल कार्यक्रमों के लिए, संसाधनों को लीक करने से कोई फर्क नहीं पड़ता: जब प्रोग्राम स्वचालित ओएस स्वचालित रूप से समाप्त होता है संसाधन वापस ले लो; हालांकि लंबे समय से चलने वाले कार्यक्रमों के लिए संसाधनों को रिसाव नहीं करना है, या कम से कम दोबारा नहीं।

इसलिए, आप शुरू से ही सिखाया गया है चाहिए कि आप सुनिश्चित करने के लिए यह एक बिंदु पर जारी किया गया है होगा जब आप एक संसाधन के अधिग्रहण:,

void foo(int i) { 
    int* array = malloc(sizeof(int) * i); 

    /* do something */ 

    free(array); 
} 

तो अपने आप को सवाल पूछने:

  • जब मैं प्रोग्राम को मारता हूं तो क्या होता है?
  • जब मैं धागे को मारता हूं तो क्या होता है?

ठीक है, के रूप में हम ने कहा, जब एक कार्यक्रम समाप्त होता है ओएस बटोरता संसाधनों वापस, तो यह सोचते हैं (और यह कुछ इस धारणा है) आप एक और सिस्टम पर या कि एक संसाधन प्राप्त नहीं किया था इस प्रणाली अच्छी तरह से है इस तरह के दुरुपयोग के खिलाफ सुरक्षित, कोई नुकसान नहीं, कोई गड़बड़ नहीं है।

हालांकि, जब आप धागे को मारते हैं, तो प्रोग्राम अभी भी चलता है, इस प्रकार ओएस संसाधनों को वापस नहीं इकट्ठा करता है। आप स्मृति को लीक कर चुके हैं, आपने लिखने के लिए एक फाइल लॉक की है कि आप अब अनलॉक नहीं कर सकते हैं ... आप धागे को मार नहीं पाएंगे।

उच्च स्तर की भाषाओं में इसे संभालने का एक तरीका है: अपवाद। चूंकि प्रोग्राम्स को अपवाद सुरक्षित होना चाहिए, जावा (उदाहरण के लिए) इसे रोककर थ्रेड को मार देगा, निष्पादन के बिंदु पर अपवाद फेंक देगा, और धीरे-धीरे ढेर को खोल देगा। हालांकि, सी ++ में अभी तक ऐसी कोई सुविधा नहीं है।

क्या यह असंभव है? नहीं, जाहिर है नहीं। असल में, आप पूरी तरह से बहुत ही विचार का पुन: उपयोग कर सकते हैं:

  • Encapsulate std::thread, interruptible_thread वर्ग भी जब यह शुरू करने व्यवधान झंडा
  • std::thread करने के लिए ध्वज का पता पारित में शामिल होंगे, और एक thread- में संग्रहीत स्थानीय रास्ता
  • साधन जांच अंक के साथ अपने कोड जहां जाँच बाधा झंडा या सेट नहीं है कि क्या है, और यह एक अपवाद

यही कारण है फेंक है जब:

// Synopsis 
class interrupt_thread_exception; 
class interruptible_thread; 
void check_for_interrupt(); 

// Interrupt exception 
class interrupt_thread_exception: public virtual std::exception { 
public: 
    virtual char const* what() const override { return "interrupt"; } 
}; // class interrupt_thread_exception 

// Interruptible thread 
class interruptible_thread { 
public: 
    friend void check_for_interrupt(); 

    template <typename Function, typename... Args> 
    interruptible_thread(Function&& fun, Args&&... args): 
     _thread([](std::atomic_bool& f, Function&& fun, Args&&... args) { 
        _flag_ref = &f; fun(std::forward<Args>(args)...); 
       }, 
       _flag, 
       std::forward<Function>(fun), 
       std::forward<Args>(args)...) 
    {} 

    bool stopping() const { return _flag.load(); } 

    void stop() { _flag.store(true); } 

private: 
    static thread_local std::atomic_bool* _flag_ref = nullptr; 

    std::atomic_bool _flag = false; 
    std::thread _thread; 
}; // class interruptible_thread 

// Interruption checker 
inline void check_for_interrupt() noexcept(false) { 
    if (not interruptible_thread::_flag_ref) { return; } 
    if (not interruptible_thread::_flag_ref->load()) { return; } 

    throw interrupt_thread_exception(); 
} // check_for_interrupt 

अब आप उचित जगहों पर बाधा के लिए चेक के साथ अपने थ्रेडेड कोड को छिड़क सकते हैं।

+5

+1, ** यह ** एक महत्वपूर्ण अवधारणा है। प्रक्रियाओं के लिए थ्रेड एक अलग संसाधन और सुरक्षा डोमेन में हैं। उन्हें 'प्रतिकूल' दृष्टिकोण के बजाय सहकारी की आवश्यकता होती है। कोड को दोबारा दोहराएं ताकि अनुरोध किए जाने पर थ्रेड गहराई से समाप्त हो सकें। –

+1

'शून्य फू (int)' पहले से अपवाद सुरक्षित नहीं है, अगर आपके पास '/ * कुछ करने के बीच में कोई रुकावट जांच है */'यह अभी भी गलत होगा। –

+0

क्या संकेत? आप बाधा पर अपवाद फेंकने के बारे में बात कर रहे हैं, और कुछ प्लेटफॉर्म pthread_cancel के लिए समान करते हैं। यदि कोई अपवाद फेंक दिया जाता है तो यह फ़ंक्शन समाप्त नहीं करता है। –

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