2013-04-04 8 views
6

मेरे पास एक साधारण बुलियन मूल्य है जिसे मुझे परीक्षण और थ्रेड-सुरक्षित तरीके से सेट करने की आवश्यकता है। यदि एक धागा पहले से ही काम कर रहा है, तो मैं दूसरे धागे से बाहर निकलना चाहता हूं। अगर मैं std::atomic_flag सही ढंग से समझता हूं, तो यह ठीक काम करना चाहिए।सी ++ 11 std :: atomic_flag, क्या मैं इसे सही तरीके से उपयोग कर रहा हूं?

// myclass.cpp 
#using <atomic> 

namespace // anonymous namespace 
{ 
    std::atomic_flag _my_flag = ATOMIC_FLAG_INIT; 
} // ns 

myclass::do_something() 
{ 
    if (!::_my_flag.test_and_set())) 
    { 
     // do my stuff here; handle errors and clear flag when done 
     try 
     { 
      // do my stuff here 
     } 
     catch (...) 
     { 
      // handle exception 
     } 

     ::_my_flag.clear(); // clear my flag, we're done doing stuff 
    } 
    // else, we're already doing something in another thread, let's exit 
} // do_something 

अपडेट:: नीचे दिए गए सुझावों के आधार पर अपडेट कोड, एक सभ्य बनाने हालांकि, मुझे विश्वास है मैं std::atomic_flag सही ढंग से समझ :) मैं, इस spinlock उदाहरण के लिए बचाने के लिए कई सरल उदाहरण ऑनलाइन खोजने के लिए नहीं कर पा रहे नहीं कर रहा हूँ std::atomic_flag के उचित उपयोग के लिए टेम्पलेट। सबको शुक्रीया!

+0

क्या यह कोड काम नहीं करता है? –

+0

@ ब्रेंडन लोंग - मैंने अभी तक इसका पूरी तरह से परीक्षण नहीं किया है; बस यह सुनिश्चित करना चाहते हैं कि मैं आगे बढ़ने से पहले अवधारणा प्राप्त करूं ... 'मेरे सामान' भाग मेरे मामले में काफी व्यापक होगा। हालांकि मुझे पता है कि यदि आवश्यक हो तो मैं आसानी से इस कोड को संशोधित कर सकता हूं ... – Tom

+0

आपके प्रश्न में कोई प्रश्न-चिह्न नहीं है। – inf

उत्तर

5

atomic_flag वास्तव में निम्न स्तर का निर्माण है जिसका व्यापक रूप से उपयोग नहीं किया जाना है। उस ने कहा, मुझे विश्वास है कि आप असाधारण मामलों में ध्वज को साफ़ करने के अलावा, जैसा कि आप चाहते हैं, उपयोग के रूप में उपयोग करते हैं। यदि std::exception से मिलान किए गए एक से अधिक अपवाद होता है तो ध्वज साफ़ नहीं होता है।

आम तौर पर इस प्रकार की चीज़ के लिए आरएआईआई का उपयोग किया जाना चाहिए। 'आर' आम तौर पर 'संसाधन' के लिए खड़ा है, लेकिन मुझे इसके बजाय 'जिम्मेदारी' के जॉन कालब के usage पसंद हैं। ध्वज स्थापित करने के बाद ध्वज को साफ़ करने की ज़िम्मेदारी है, इसलिए आपको यह सुनिश्चित करने के लिए आरएआईआई का उपयोग करना चाहिए कि जिम्मेदारी पूरी की जाती है। यदि असाधारण मामलों में आपको जो कुछ करने की ज़रूरत है, वह इस तरह से किया जा सकता है तो try/catch जोड़ी गायब हो जाती है।

if (!std::atomic_flag_test_and_set(&::_my_flag)) 
{ 
    flag_clearer x(&::_my_flag); 

    // do my stuff here 
} 

लेकिन अगर आप एक flag_clearer प्रकार अपने आप को लिखने के लिए जरूरत नहीं है। इसके बजाय आप आसानी से म्यूटेक्स और लॉक_गार्ड जैसे उच्च स्तरीय संरचनाओं का उपयोग कर सकते हैं:

namespace 
{ 
    std::mutex my_flag; 
} 

myclass::do_something() 
{ 
    if (my_flag.try_lock()) 
    { 
     std::lock_guard<std::mutex> x(my_flag, std::adopt_lock); 
     // do my stuff here 
    } 
    // else, we're already doing something in another thread, let's exit 
} 
+1

धन्यवाद बम्स। आरएआईआईआई बिंदु अच्छी तरह से लिया गया है। और आप सही हैं, मैं अपने अपवाद हैंडलिंग पर गड़बड़ कर दिया। यदि मैं अभी भी सादगी कारणों के लिए flag_clearer का उपयोग करना टालना चाहता था, तो क्या मैं 'कैच (...)' के साथ 'कैच (std :: अपवाद और ई) 'को प्रतिस्थापित कर सकता हूं और इसे अच्छा कह सकता हूं? बीटीडब्लू मैं शायद आपके कोड को प्रतिस्थापित करने के लिए जा रहा हूं, अगर आपने इसे कम गूढ़ बना दिया है :) मुझे अपने ऐप में इस सेक्शन के प्रदर्शन की हर आखिरी बूंद को निचोड़ने की आवश्यकता नहीं है। धन्यवाद – Tom

+1

@ टॉम हां, '...' पकड़ने से यह सुनिश्चित होगा कि क्लीन-अप कोड चलता है। – bames53

+0

फॉलो अप के लिए धन्यवाद, मैं संशोधित कोड के साथ अपनी पोस्ट अपडेट करूँगा ... और फिर अपने असली कोड को अपने म्यूटेक्स उदाहरण के साथ प्रतिस्थापित करें :) धन्यवाद! – Tom

1

हां, यह if ब्लॉक के अंदर कोड को छोड़ देगा यदि कुछ अन्य धागे पहले से ही ध्वज सेट कर चुके हैं और किसी ने इसे साफ़ नहीं किया है। यदि कोई अन्य कोड ध्वज के साथ गड़बड़ नहीं करता है, तो इसका मतलब है कि कुछ थ्रेड वर्तमान में उस ब्लॉक को निष्पादित कर रहा है।

परमाणु झंडे बहुत कम स्तर हैं, हालांकि; इसके बजाय atomic_bool का उपयोग करने पर विचार करें। इसके अलावा, चूंकि यह सी ++ है, इसलिए आप सेट और स्पष्ट के लिए सदस्य फ़ंक्शंस का उपयोग कर सकते हैं।

संपादित करें:

नहीं, atomic_bool आसानी से आप क्या चाहते हैं नहीं करता है। atomic_flag के साथ चिपकाएं ...

+0

पीट, पुष्टि के लिए धन्यवाद। मैं इसके बजाय सदस्य कार्यों का उपयोग करूंगा, मुझे लगता है कि वे अधिक पठनीय हैं। एक बार फिर धन्यवाद! – Tom

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