2015-09-30 5 views
7

के आदेश पर निर्भर सी ++ 14 मानक के अनुसार, गैर स्थिर सदस्य चर क्रम में वे एक कक्षा में घोषित किया गया है में initialised कर रहे हैं। नीचे काट कोड नीचे एक थ्रेड फ़ंक्शन को नियंत्रित करने के लिए इस नियम पर निर्भर करता है।initialisation

class foo 
{ 
    foo(): 
      keep_going{true}, 
      my_thread(&foo::go,this) 
    {} 

     void go() 
     { 
      while(keep_going) 
      check a std::condition_variable and do some work; 
     } 
     bool keep_going; 
     std::thread my_thread; 
} 

ध्यान दें कि keep_going धागा वस्तु से पहले घोषित किया जाता है और समय धागा जाने समारोह में प्रवेश करती है द्वारा true सेट किया जाना चाहिए। यह ठीक है और ठीक काम करता प्रतीत होता है।

हालांकि, इस बहु कोड है और यह तो मैं दो प्रश्न हैं पागल होने के लिए भुगतान करता है:

1 इसे इस तरह initialisation के आदेश पर भरोसा करने के लिए सुरक्षित है? मेरा असली ऑब्जेक्ट प्रोसेसिंग थ्रेड के बिना समझ में नहीं आता है इसलिए मैं इसे कन्स्ट्रक्टर में सेट करना चाहता हूं।

2 यह जब यह initialisation के आदेश की तरह अपेक्षाकृत अस्पष्ट बातों पर निर्भर करता है दूसरों के लिए कोड देने के लिए असुरक्षित है?

+0

प्रारंभिकरण का क्रम अस्पष्ट नहीं है, यह अच्छी तरह परिभाषित है और इस कोड के साथ कुछ भी गलत नहीं है। – Salgar

+0

1) हाँ प्रारंभिकरण का क्रम चश्मा का हिस्सा है, 2) हां - स्पष्ट दस्तावेज – BeyelerStudios

+0

में मदद कर सकता है मैं केवल एक अच्छी टिप्पणी समझाऊंगा। उद्धरण का पालन करें 'हमेशा अपने कोड मैन्टैनर जैसे कोड एक धारावाहिक हत्यारा है जो जानता है कि आप कहां रहते हैं' –

उत्तर

5
  1. मानक के अनुसार सुरक्षित है।

  2. अत्यंत असुरक्षित। कुछ लोगों को इसके बारे में पता है, और आपकी हेडर फ़ाइल को बनाए रखने वाला कोई व्यक्ति सदस्यों को विनाशकारी परिणामों के साथ पुन: व्यवस्थित कर सकता है।

मैं इस पर भरोसा नहीं करता।

+0

मैंने इसे हेडर फ़ाइल में कुछ ब्लॉक कैप चेतावनियों के साथ रखा है। –

2

मैं कोड भी एक बंदर को स्पष्ट करने के लिए कोड के पुनर्लेखन के लिए करना चाहते हैं।

एक अन्य संभावित समस्या यहाँ हो सकता है जब वर्ग foo आधार वर्ग है। धागा गैर पूरी तरह से निर्मित वस्तु पर शुरू होगा। क्या होगा यदि व्युत्पन्न वर्ग का निर्माता विफल हो जाए? इस मामले में यह start() विधि के लिए कन्स्ट्रक्टर के थ्रेड निष्पादन को बेहतर ढंग से ले जाना बेहतर है।

4

हालांकि मानक द्वारा यह सुरक्षित है, मैं इसके साथ नहीं जाऊंगा।

उपाख्यान: मैंने विजुअल स्टूडियो 2013 का उपयोग कर विंडोज ओएस पर एक अनुकूलित थ्रेडपूल लिखा था। मैंने धागा पूल वैश्विक घोषित किया। मानक मानक द्वारा, मुख्य वस्तुएं वापस लौटने के बाद नष्ट हो जाती हैं। थ्रेड पूल विनाशक ने प्रत्येक थ्रेड को join करने की कोशिश की, लेकिन हां! एक मृत-ताला (आप यहां इस समस्या के बारे में पढ़ सकते हैं: std::thread::join() hangs if called after main() exits when using VS2012 RC)। मानक राज्य स्पष्ट रूप से बताते हैं कि यदि कोई धागा शामिल हो जाता है, तो इसमें शामिल होने में कोई समस्या नहीं है, लेकिन जैसा कि आप देख सकते हैं, यह पूरी तरह लागू नहीं हुआ था।

मैं आपको यह असंबंधित मुद्दा क्यों बता रहा हूं? क्योंकि यहां तक ​​कि कंपाइलर्स और प्लेटफार्मों में कुछ कीड़े हैं। पहले कुछ प्रासंगिक-सहायक संकलक संस्करणों में सूक्ष्म चीजें 100% सही ढंग से लागू नहीं हो सकती हैं।

यही कारण है कि मैं इस विचार से नहीं जाऊंगा। एक काम के आसपास के रूप में, मैं std::unique_ptr में लिपटे धागे की घोषणा करता हूं और इसे कन्स्ट्रक्टर बॉडी में प्रारंभ करता हूं। इस तरह keep_going से पहले इसे शुरू करने का कोई मौका नहीं है।

foo(): 
    keep_going{true} 
    { my_thread = std::make_unique<std::thread>(&foo::go,this); } 
संबंधित मुद्दे