2013-04-24 7 views
11

मेरे पास ScopedLock कक्षा है जो दायरे से बाहर होने पर स्वचालित रूप से लॉक को रिलीज़ करने में मदद कर सकती है। हालांकि, समस्या यह है: कभी कभी टीम के सदस्यों को, इस तरह केसी ++ अज्ञात ऑब्जेक्ट्स से बचने के लिए कैसे करें

{ 
    ScopedLock(mutex); // anonymous 
    xxx; 
} 

के रूप में ऊपर कोड गलत है क्योंकि ScopedLock वस्तु का निर्माण किया और तुरंत विलुप्त अमान्य लॉक-कोड लिखने तो यह उम्मीद क्षेत्र लॉक करने के लिए (विफल रहता है xxx)। मैं चाहता हूं कि संकलक इस तरह के कोड को संकलित करने का प्रयास करते समय त्रुटि दें। क्या यह किया जा सकता है?

मैंने g++ चेतावनी विकल्प खोजे हैं, लेकिन सही खोजने में विफल रहे हैं।

+1

मुझे नहीं लगता कि आप इसे मना कर सकते हैं (या यहां तक ​​कि एक कंपाइलर डायग्नोस्टिक उत्पन्न भी कर सकते हैं)। एक और अधिक कुशल (और संतोषजनक, शायद) समाधान आपके सहकर्मियों को तब तक थप्पड़ मारना होगा जब तक कि वे इसे करने से रोकते हैं। ;) – syam

+3

बीटीडब्ल्यू, वास्तविक नाम * अस्थायी वस्तुओं * नहीं * अज्ञात वस्तुओं * है। – syam

+0

दुर्भाग्य से, ऐसा लगता है कि http://lists.cs.uiuc.edu/pipermail/cfe-dev/2010- दिसम्बर/012755.html इसे कभी भी क्लैंग में नहीं बनाया गया। –

उत्तर

2

इससे बचने के लिए, एक मैक्रो जो आप के लिए यह करता है, हमेशा लॉकर के लिए एक ही नाम का उपयोग परिचय एक विकल्प, जावा का synchronize ब्लॉक मैक्रो निर्माण का उपयोग करके अनुकरण किया जा सकता है: फॉर-लूप में हमेशा एक बार चल रहा है, मैं फॉर-लूप के प्रारंभिक विवरण में ऐसे लॉकर को तुरंत चालू करता हूं, इसलिए यह डी हो जाता है फॉर-लूप छोड़ते समय फंस गया।

हालांकि, इसमें कुछ नुकसान हैं, break कथन का अप्रत्याशित व्यवहार एक उदाहरण है। यह "हैक" here पेश किया गया है।


बेशक, उपरोक्त विधियों में से कोई भी पूरी तरह से अपने उदाहरण की तरह आकस्मिक कोड से बचें। लेकिन यदि आप दो मैक्रोज़ में से किसी एक का उपयोग करके लॉकिंग म्यूटेक्स लिखने के लिए उपयोग किया जाता है, तो यह कम होने की संभावना कम होगी। चूंकि लॉकर क्लास का नाम मैक्रो परिभाषा को छोड़कर कोड में कभी नहीं दिखाई देगा, तो आप अवैध कोड करने से बचने के लिए वर्जन कंट्रोल सिस्टम में एक प्रतिबद्ध हुक भी पेश कर सकते हैं।

+0

असल में, लूप के लिए इस दुरुपयोग को नए श्रेणी-आधारित लूप (http://stackoverflow.com/a/9657748/46642) –

+0

के साथ उन समस्याओं के बिना किया जा सकता है ठीक है, लेकिन फिर आपको 'LOCK' का उपयोग करना याद रखना होगा 'ScopedLock' के बजाय। मुझे नहीं लगता कि आपने वास्तव में कुछ हल किया है। –

+0

+1, दिलचस्प 'सिंक्रनाइज़' चाल। लेकिन नुकसान और नए गैर-मानक अर्थशास्त्र के कारण यह परिचय देता है कि मैं इसके उपयोग की अनुशंसा नहीं करता। 'LOCK' मैक्रो के रूप में, सामान्य रूप से दृश्यों के पीछे स्थानीय चर उत्पन्न करते समय इसे संभावित नाम संघर्ष को कम करने के लिए फ़ाइल नाम और रेखा के आधार पर एक पहचानकर्ता नाम बनाना चाहिए (अभी उस के लिए प्रीप्रोसेसर वाक्यविन्यास याद नहीं किया जा सकता है)। – syam

1

AFAIK जीसीसी में ऐसा कोई ध्वज नहीं है। एक स्थिर विश्लेषक आपकी आवश्यकताओं के अनुरूप बेहतर हो सकता है।

#define LOCK(mutex) ScopedLock _lock(mutex) 

तो इस तरह इसका इस्तेमाल:

{ 
    LOCK(mutex); 
    xxx; 
} 

रूप

4

नहीं, दुर्भाग्यवश , as I explored in a blog post last year ऐसा करने का कोई तरीका नहीं है।

इसे में, मैं यह निष्कर्ष निकाला:

मुझे लगता है कि कहानी का नैतिक जब scoped_lock s का उपयोग करके याद करने के लिए इस कहानी है।


आप मैक्रो का उपयोग करने के लिए अपनी टीम में सभी प्रोग्रामर के लिए मजबूर करने की कोशिश कर सकते हैं या एक सीमा के लिए चाल है, लेकिन फिर अगर आप की गारंटी दे सकें कि हर मामले में तो आप को पकड़ने की गारंटी दे सकते हो जाएगा हर मामले में यह बग भी।

आप प्रोग्रामेटिक रूप से पर जाने के लिए इस तरह की विशिष्ट गलती को पकड़ने के लिए एक रास्ता तलाश रहे हैं, और कोई भी नहीं है।

0

मैक्रो

#define CON2(x,y) x##y 
#define CON(x,y) CON2(x,y) 
#define LOCK(x) ScopedLock CON(unique_,__COUNTER__)(mutex) 

उपयोग

{ 
    LOCK(mutex); 
    //do stuff 
} 

इस मैक्रो ताले के लिए अद्वितीय नामों उत्पन्न होगा साथ बदलें, भीतरी कार्यक्षेत्रों में अन्य mutexes के lockeng की इजाजत दी

+0

यह "एक चर नाम जोड़ें" से अधिक उपयोगी नहीं है। यह बग पकड़ने का कोई तरीका नहीं पेश करता है। –

+0

@LightnessRacesinOrbit यदि वे इसके बजाय मैक्रो का उपयोग करेंगे, तो वे वैरिएबल नाम गायब नहीं होंगे =) – kassak

+1

और यदि वे चर नाम को याद नहीं करते हैं, तो वे चर नाम नहीं खोलेंगे। मुद्दा यह है कि आपको दोनों मामलों में कुछ करना याद रखना होगा। सवाल प्रोग्रामेटिक रूप से बग का पता लगाने के बारे में है। –

4

मैं एक दिलचस्प चाल देखा है एक कोडबेस में, लेकिन यह केवल तभी काम करता है जब आपका scoped_lock प्रकार टेम्पलेट नहीं है (std :: scoped_lock है)।

#define scoped_lock(x) static_assert(false, "you forgot the variable name") 

आप वर्ग को सही ढंग से उपयोग करते हैं, आप

scoped_lock lock(mutex); 

और के बाद से scoped_lock पहचानकर्ता एक खुला कोष्ठक के बाद नहीं है, मैक्रो ट्रिगर नहीं करेगा और कोड यह के रूप में रहेगा है है। आप लिखते हैं तो \

scoped_lock(mutex); 

मैक्रो ट्रिगर किया जाएगा और कोड

static_assert(false, "you forgot the variable name"); 

इस के साथ प्रतिस्थापित किया जाएगा सूचनात्मक संदेश उत्पन्न होगा।

आप एक योग्य नाम

threads::scoped_lock(mutext); 

का उपयोग करते हैं तो परिणाम अभी भी संकलन नहीं होगा, लेकिन संदेश के रूप में अच्छा नहीं होगा।

बेशक

, अगर अपने लॉक एक टेम्पलेट है, बुरा कोड

scoped_lock<mutex_type>(mutex); 

जो मैक्रो ट्रिगर नहीं करेगा है।

+0

मुझे नहीं पता था कि ब्रांड्स के बिना मैक्रो नाम लिखना भी संभव है और यह अभी भी मान्य है (और विस्तारित नहीं है)। यह एक अच्छा है। +1 – leemes

+0

अन्य नुकसान जो मैं सोच सकता हूं: Typedefs विफल हो जाएंगे जब तक कि इसके साथ एक नया मैक्रो भी पेश नहीं किया जाता है। साथ ही, जब आप इस तरह के मैक्रो वाले वर्ग से उत्तराधिकारी होते हैं, तो आपको पहले टाइपिफ़ का उपयोग करना होगा (यदि आप नहीं करते हैं, तो AFAIK आप म्यूटेक्स के साथ सुपर कन्स्ट्रक्टर को तर्क के रूप में नहीं बुला सकते हैं) साथ ही उप के लिए कक्षा फिर से विफल रहता है। दोनों मामलों में (typedef + sub class), आप निश्चित रूप से एक और मैक्रो लिख सकते हैं और फिर से सुरक्षित हैं, लेकिन हमेशा के रूप में: आपको इसे पहले स्थान पर याद रखना होगा। – leemes

+0

मुझे इस प्रश्न के दिनों में 'std :: scoped_lock' के बारे में पता नहीं था? – Walter

2

आप एक ही नाम के साथ एक वर्ग और हटाए गए फ़ंक्शन का उपयोग कर सकते हैं। दुर्भाग्य से इस प्रकार से पहले "कक्षा" कीवर्ड जोड़ने की आवश्यकता है।

class Guard 
{ 
public: 
    explicit Guard(void) 
    { 
    } 
}; 

static void Guard(void) = delete; 

int main() 
{ 
    // Guard(); // Won't compile 
    // Guard g; // Won't compile 
    class Guard g; 
} 
संबंधित मुद्दे