क्या C ++ [बंद] में उत्पादन के लिए तैयार लॉक-फ्री कतार या हैश कार्यान्वयन है


80

मैं C ++ में एक लॉक-फ्री कतार के लिए काफी कुछ कर रहा हूं। मुझे कुछ कोड और कुछ परीक्षण मिले - लेकिन कुछ भी नहीं जिसे मैं संकलित करने में सक्षम था। लॉक-फ्री हैश का भी स्वागत किया जाएगा।

सारांश: अभी तक मेरे पास कोई सकारात्मक जवाब नहीं है। कोई "प्रोडक्शन रेडी" लाइब्रेरी नहीं है, और आश्चर्यजनक रूप से कोई भी विद्यमान पुस्तकालय एसटीएल कंटेनरों के एपीआई का अनुपालन नहीं करता है।


4
विजुअल स्टूडियो 2010 में <concurrent_queue.h>
रिक


2
ध्यान दें कि, उत्सुकता से, "लॉक-फ़्री" शब्द का मतलब जरूरी नहीं है कि कोई लॉक नहीं है। एक परिभाषा के लिए en.wikipedia.org/wiki/Non-blocking_algorithm देखें ।
क्रिस्टोफर जॉनसन

8
वाह एक सवाल है कि मल्टीथ्रेडेड प्रोग्रामिंग में एक सामान्य अभी तक कठिन समस्या को कैसे हल किया जाए जिसमें कई समाधान हैं, बहुत चर्चा उत्पन्न की, और एक टन तक की कमाई की ... फिर 9 साल बाद आप इसे ऑफ-टॉपिक के रूप में बंद कर देते हैं। StackOverflow, NathanOliver, सर E_net4 द समझदार डाउनवॉटर, जीन-फ्रांकोइस फेबरे, मचाविटी, और gre_gor / s
muusbolla

1
मैं कहूंगा कि प्रश्न को बंद करने वाले लोग शायद इसे नहीं समझते हैं।
Derf Skren

जवाबों:


40

1.53 तक, बूस्ट लॉक फ्री डेटा संरचनाओं का एक सेट प्रदान करता है , जिसमें कतार, ढेर और एकल-निर्माता / एकल-उपभोक्ता कतार (यानी रिंग बफ़र्स) शामिल हैं।


बढ़ावा देना :: lockfree :: कतार केवल POD प्रकारों के साथ काम करता है और ज्यादातर बार यह काफी उपयोगी नहीं होता है। मुझे यकीन है कि अगर अधिक लचीली संरचना प्रदान करने का कोई तरीका था, तो इसे बढ़ावा मिलेगा।
रहमान

1
@ इधर उधर की समस्या कहाँ है? यदि आप कुछ और पास करना चाहते हैं, विशेष रूप से अपारदर्शी के साथ ऑब्जेक्ट्स संभवतः साइड इफेक्ट्स को रोकते हैं, तो आप लॉक फ्री डिज़ाइन के पूरे उद्देश्य को नहीं समझ पाए हैं।
इचथियो

क्यों बढ़ावा एक मुक्त सूची के आधार पर दोनों को लॉक-फ्री कतार और स्टैक प्रदान करता है। लेकिन वे लॉक-फ्री लिंक्ड सूची प्रदान नहीं कर रहे हैं?
जिंग

25

शुरुआती बिंदु या तो एक निर्माता और उपभोक्ता या कई लोगों के लिए हर्ब सटर के DDJ लेख होंगे । कोड वह देता है (प्रत्येक लेख के दूसरे पृष्ठ पर शुरू होने वाली लाइन) C ++ 0x शैली के परमाणु <T> टेम्पलेट प्रकार का उपयोग करता है; जो आप बूस्ट इंटरप्रोसेस लाइब्रेरी का उपयोग करके नकल कर सकते हैं।

बूस्ट कोड को इंटरप्रोसेस लाइब्रेरी की गहराई में दफन किया गया है, लेकिन उपयुक्त हेडर फाइल (atomic.hpp) के माध्यम से पढ़े जाने वाले सिस्टम के लिए आवश्यक तुलना-और-स्वैप ऑपरेशन के लिए कार्यान्वयन को देखो ध्वनि से परिचित हूं।


1
स्टीव, मुझे बूस्ट के परमाणु कार्यान्वयन में भी दिलचस्पी है, लेकिन वे इंटरप्रोसेस के विवरण में निवास करते हैं / और दस्तावेज नहीं हैं। क्या वे किसी भी तरह से सुरक्षित हैं? धन्यवाद!
किम ग्रासमैन

मैं हर्ब सटर के लेखों को अच्छी तरह से जानता हूं - आपको स्रोत कहां से मिले हैं? वे डीडीजे द्वारा प्रकाशित नहीं हैं और न ही अपनी साइट पर (या शायद मैं अंधा हूं?)।
RED सॉफ्ट ADAIR

1
कोड उन लेखों में इन-लाइन उनके संबंधित दूसरे पृष्ठों पर शुरू होता है।
स्टीव गिलहम

3
यदि आप कई प्रीड्यूसर या उपभोक्ताओं के लिए सही मायने में लॉक-फ्री कोड चाहते हैं, तो मैं बाहर हूं। सटर के कई-उत्पादक कतार उदाहरण लॉक मुक्त नहीं है - उत्पादकों को अनुक्रमित करने के लिए एक ताला है, और उपभोक्ताओं को अनुक्रमित करने के लिए एक ताला है। यदि आप एक पा सकते हैं, तो मुझे इसमें भी दिलचस्पी होगी।
स्टीव गिलहम

1
एक बढ़ावा है: tim.klingt.org/git?p=boost_lockfree.git पर लॉकफ्री प्रोजेक्ट ; कि आप देख सकते हैं। इसका एक लक्ष्य परमाणु अस्मिताओं का एक गैर :: विवरण :: संस्करण प्रदान करना है।
sstock

17

हाँ!

मैंने एक लॉक-फ्री कतार लिखी । इसमें ™ विशेषताएं हैं:

  • पूरी तरह से प्रतीक्षा-मुक्त (कोई कैस लूप नहीं)
  • सुपर फास्ट (प्रति सेकंड एक सौ मिलियन से अधिक / डेक्यू ऑपरेशन)
  • C ++ 11 चाल शब्दार्थ का उपयोग करता है
  • जरूरत के अनुसार बढ़ता है (लेकिन केवल अगर आप इसे चाहते हैं)
  • तत्वों के लिए लॉक-फ्री मेमोरी प्रबंधन करता है (पूर्व-आवंटित सन्निहित ब्लॉकों का उपयोग करके)
  • स्टैंड-अलोन (दो हेडर प्लस एक लाइसेंस और रीडमी)
  • MSVC2010 +, इंटेल ICC 13, और GCC 4.7.2 के तहत संकलन (और किसी भी C ++ 11 पूरी तरह से अनुपालन कंपाइलर के तहत काम करना चाहिए)

यह GitHub पर सरलीकृत बीएसडी लाइसेंस के तहत उपलब्ध है (इसे कांटा करने के लिए स्वतंत्र महसूस करें!)।

कैविट्स:

  • केवल एकल-उत्पादक एकल-उपभोक्ता वास्तुकला (यानी दो धागे)
  • पूरी तरह से x86 (-64) पर परीक्षण किया गया है, और एआरएम, पावरपीसी और अन्य सीपीयू पर काम करना चाहिए, जहां देशी आकार के पूर्णांक और सूचक भार संरेखित होते हैं और स्टोर स्वाभाविक रूप से परमाणु होते हैं, लेकिन गैर- x86 सीपीयू पर क्षेत्र परीक्षण नहीं किया गया है (यदि कोई है) इस पर एक परीक्षण करने के लिए मुझे पता है)
  • यदि कोई पेटेंट का उल्लंघन किया जाता है, तो इसका कोई मतलब नहीं है (अपने जोखिम पर उपयोग, आदि)। ध्यान दें कि मैंने खुद को डिजाइन किया और इसे खरोंच से लागू किया।

2
बहुत अच्छा लगता है, लेकिन कई निर्माताओं और / या कई उपभोक्ताओं को वास्तविक मल्टी थ्रेडिंग का लाभ उठाने की आवश्यकता होती है।
RED सॉफ्ट ADAIR

2
@ आरईडी: आवेदन पर निर्भर करता है। सिंगल-प्रोड्यूसर / -संसर की मुझे जरूरत थी, इसलिए यह सब मैंने बनाया; ;-)
कैमरून

@Cameron: बढ़िया सामग्री! क्या आपने फेसबुक के मूर्खतापूर्ण निर्मातासुमेर क्यू के खिलाफ अपनी कतार को चिह्नित किया है ? मैंने इसे आपके बेंचमार्क कोड का उपयोग करके किया है और यह आपके RWQ और दिमित्री के SPSC दोनों को नाटकीय रूप से बेहतर प्रदर्शन देता है। मैं 3.06 गीगाहर्ट्ज़ कोर 2 डुओ (टी 9900) के साथ ओएस एक्स 10.8.3 पर हूं और -ओ 3 के साथ क्लैंग का उपयोग करके कोड संकलित किया। मैंने ऐसा इसलिए किया क्योंकि मैं वर्तमान में अपनी एक परियोजना के लिए एक एकल-निर्माता / एकल-उपभोक्ता कतार देख रहा हूं और मैंने आपका एक उम्मीदवार माना :)
एंड्रे नेव्स

@ एंड्रे: मैंने अभी चेक किया है :-) फेसबुक की मूर्खता एक खाली कतार से हटने पर, और एक ही धागे पर एक गैर-खाली कतार से हटने पर थोड़ी धीमी होने पर मेरी तुलना में थोड़ी तेज है। अन्य सभी ऑपरेशन लगभग एक ही गति हैं (यह एक VM पर g ++ -O3 के साथ था)। मूर्खतापूर्ण कतार के लिए आप किस आकार का उपयोग कर रहे हैं? (मैंने MAX का उपयोग किया।) मेरा और दिमित्री दोनों आवश्यकतानुसार बढ़ते हैं, जबकि मूर्खतापूर्ण एक निश्चित होता है - और निश्चित रूप से, सबसे तेज़ एन्क्यू ऑपरेशन तब होता है जब कोई जगह नहीं होती है और यह बस विफल हो जाता है। कोड को देखते हुए, मूर्खतापूर्ण विचार मेरे जैसे ही विचारों का उपयोग करते हुए प्रतीत होते हैं, लेकिन w / o resizeability।
कैमरन

@ एंड्रे: ओह, एक और बात जिसका मैं उल्लेख करना भूल गया - मेरे बेंचमार्क कोड के साथ, "रॉ खाली निकालें" बेंचमार्क अब तक सबसे अधिक पुनरावृत्तियों करता है (क्योंकि यह इतना सरल है, यह एक औसत दर्जे का परिणाम प्राप्त करने के लिए अधिक लेता है), जो झुकता है अंतिम रूप से "औसत ऑप्स / एस" संख्या को प्रभावित करने के लिए। गुणक (और फ्लैट समय मान) आम तौर पर अधिक उपयोगी होते हैं। वैसे भी, इन गति पर, ये सभी कतारें काफी तेज होंगी यदि वे वास्तव में मेरे मूक सिंथेटिक बेंचमार्क की तुलना में कुछ मांस के लिए उपयोग की जा रही हैं;;
कैमरून

15

लगता है कि फेसबुक की Folly C ++ 11 पर आधारित मुक्त डेटा संरचनाएं है <atomic>:

मैं यह कहने की हिम्मत करूंगा कि ये वर्तमान में उत्पादन में उपयोग किए जाते हैं, इसलिए मुझे लगता है कि वे सुरक्षित रूप से अन्य परियोजनाओं में इस्तेमाल किया जा सकता है।

चियर्स!


उनकी एक एमपीएमसी कतार भी है उनका दावा है कि "वैकल्पिक रूप से अवरुद्ध है।" ऐसा प्रतीत होता है कि यह उनके नियमित प्रलेखन का हिस्सा नहीं है, अगर इसका इस्तेमाल करने की सलाह दी जाती है तो अनिश्चित।
जंगी शाकलेफोर्ड

11

ऐसा एक पुस्तकालय है, लेकिन यह सी में है।

C ++ में लपेटना सीधा होना चाहिए।

http://www.liblfds.org


10

दिए गए अधिकांश उत्तरों की जाँच करने के बाद, मैं केवल यह बता सकता हूँ:

जवाब है नहीं

ऐसी कोई चीज सही नहीं है जिसका इस्तेमाल सही तरीके से किया जा सके।


4
100% सही है। मैं comp.programming.threads न्यूज़ग्रुप की मदद से एक ही परिणाम पर आया था। एक कारण यह है कि लॉक फ्री डेटा संरचनाओं का क्षेत्र एक पेटेंट खान क्षेत्र है। इसलिए इन्टेल जैसे व्यावसायिक परिवाद भी इससे बच रहे हैं।
लोथर

यह C है, C ++ नहीं है। कृपया मतदान से पहले प्रश्न पढ़ें।
लाल सॉफ्ट ADAIR

क्षमा याचना। मैं ध्यान देता हूं कि एसओ मुझे अपना वोट नहीं देने देगा क्योंकि ऐसा लगता है कि वोट बहुत पुराना है। मुझे लगता है कि एसओ डेवलपर्स को ऐसा करने की अधिक आवश्यकता है - वे अनपेक्षित व्यवहारों की बढ़ती संख्या को जोड़ते हुए प्रतीत होते हैं।

3
क्यों इस जवाब को इतने उभार मिल रहे हैं। प्रश्न को आसानी से संपादित किया जा सकता है। या यह एक टिप्पणी में हो सकता है।
उपयोगकर्ता


6

निकटतम चीज़ जो मुझे पता है, वह है विंडोज इंटरलॉक की गई सिंगली लिंक्ड लिस्ट । बेशक, यह केवल विंडोज है।


वाह - ऐसा लगता है। मुझे इसे जांचने के लिए कुछ समय चाहिए (मैं वर्तमान में ऐसा नहीं कर सकता) लेकिन मैं आपके पास वापस आ जाऊंगा।
RED सॉफ्ट एडएयर

Interlocked Singly Linked List एक अद्भुत उपकरण है लेकिन दुख की बात है कि यह FIFO नहीं है।
एलिया_बाहू

यह एक उचित सूची नहीं है, जैसा कि मुझे याद है। आप मनमाने तत्वों को उजागर नहीं कर सकते; केवल एक चीज जिससे आप पूरी सूची को हटा सकते हैं। शायद तब से यह आगे बढ़ रहा है ...

5

यदि आपके पास मल्टीपल-प्रोड्यूसर / सिंगल-कंज्यूमर क्यू / एफआईएफओ है, तो आप एसएलआईएसटीटी या एक ट्रिवियल फ्री फ्री एलआईएफओ स्टैक का उपयोग करके आसानी से एक लॉकफ्री बना सकते हैं। आपके पास जो कुछ भी है वह उपभोक्ता के लिए एक दूसरा "निजी" स्टैक है (जो कि सादगी के लिए SLIST के रूप में भी किया जा सकता है या आपके द्वारा चुने गए किसी भी अन्य स्टैक मॉडल के लिए)। उपभोक्ता निजी स्टैक से आइटम निकालता है। जब भी निजी LIFO एक्सहेडस्टेड होता है, तो आप साझा समवर्ती SLIST को पॉप ऑफ करने के बजाय फ्लश करते हैं (संपूर्ण SLIST चेन को हथियाने) और फिर फ्लश की गई सूची को निजी स्टैक पर आइटम पुश करने के लिए चलते हैं।

यह एकल-उत्पादक / एकल-उपभोक्ता के लिए और कई-उत्पादक / एकल-उपभोक्ता के लिए काम करता है।

हालांकि, यह कई-उपभोक्ता मामलों (एकल-निर्माता या कई-उत्पादकों के साथ) के लिए काम नहीं करता है।

इसके अलावा, जहां तक ​​हैश टेबल जाते हैं, वे "स्ट्रिपिंग" के लिए एक आदर्श उम्मीदवार हैं जो कैश के प्रति सेगमेंट वाले लॉक को हैश में विभाजित कर रहा है। यह कैसे जावा समवर्ती पुस्तकालय करता है (32-धारियों का उपयोग करके)। यदि आपके पास लाइट-वेट रीडर-राइटर लॉक है, तो हैश टेबल समवर्ती रीडिंग के लिए समवर्ती रूप से एक्सेस किया जा सकता है और आप केवल तब स्टाल करेंगे जब लेखन प्रतियोगिता धारियों पर हो रहा हो (और संभवतः यदि आप हैश टेबल बढ़ने की अनुमति देते हैं)।

यदि आप अपना स्वयं का रोल करते हैं, तो अपने सभी हैक्स को एक-दूसरे के बगल में रखने के बजाय हैश प्रविष्टियों के साथ अपने ताले को इंटरलेय करना सुनिश्चित करें ताकि आपके पास झूठी साझा करने की संभावना कम हो।


आपके उत्तर के लिए धन्यवाद। मैं C ++ में "प्रोडक्शन रेडी" समाधान / टेम्पलेट की तलाश कर रहा हूं। मैं अपना खुद का रोल नहीं करना चाहता। क्या आप इस तरह के कार्यान्वयन को जानते हैं?
लाल शीत ऋतु ADAIR

4

मुझे इस पर थोड़ी देर हो सकती है।

समाधानों की अनुपस्थिति (सवाल पूछा गया था) मुख्य रूप से C ++ में महत्वपूर्ण मुद्दे (C ++ 0x / 11 से पहले) के कारण हैं: C ++ के पास कोई समवर्ती मेमोरी मॉडल नहीं है।

अब, std :: atomic का उपयोग करके, आप मेमोरी ऑर्डरिंग मुद्दों को नियंत्रित कर सकते हैं और उचित तुलना-और-स्वैप ऑपरेशन कर सकते हैं। मैंने स्वयं को जल्दी मुक्त और ABA समस्याओं से बचने के लिए C ++ 11 और Micheal's Hazard Pointers (IEEE TPDS 2004) का उपयोग करके माइकल और स्कॉट की लॉक-फ्री कतार (PODC96) का कार्यान्वयन स्वयं लिखा है। यह ठीक काम कर रहा है लेकिन यह एक त्वरित और गंदा कार्यान्वयन है और मैं वास्तविक प्रदर्शन से संतुष्ट नहीं हूं। कोड बिटबकेट पर उपलब्ध है: LockFreeExperiment

डबल-पॉइंट CAS (लेकिन 64 बिट संस्करण केवल c86xchg16b का उपयोग करके x86-64 पर संभव होगा) के बिना लॉक-फ्री कतार को लागू करना संभव है, मैं इस बारे में एक ब्लॉग पोस्ट (कतार के लिए बिना कोड वाला) कर रहा हूं : X86 / x86-64 (LSE ब्लॉग) के लिए जेनेरिक डबल-शब्द की तुलना करें और स्वैप करें

मेरे अपने बेंचमार्क ने मुझे दिखाया कि डबल-लॉक कतार (मिचेल और स्कॉट 1996 के पेपर में भी) और साथ ही लॉक-फ्री एक भी करता है (मैं पर्याप्त विवाद तक नहीं पहुंचा हूं, ताकि लॉक किए गए डेटा संरचनाओं में प्रदर्शन के मुद्दे हों, लेकिन मेरी बेंच के लिए बहुत हल्का है अब) और इंटेल के टीबीबी से समवर्ती कतार अपेक्षाकृत छोटी संख्या (ऑपरेटिंग सिस्टम के आधार पर, फ्रीबीएसडी 9 के तहत सबसे कम बाध्य है) के लिए और भी बेहतर (दो बार तेज) लगता है, यह संख्या अब तक 8 थ्रेड है। धागे के 4 ht- कोर के साथ i7, और इस तरह 8 तार्किक सीपीयू) और बहुत ही अजीब व्यवहार (सेकंड से घंटे तक मेरे सरल बेंचमार्क चाल का निष्पादन समय है!)

एसटीएल शैली के बाद लॉक-फ्री कतारों के बारे में एक और सीमाएं: लॉक-फ्री कतार पर पुनरावृत्त होने का कोई मतलब नहीं है।


3

और फिर इंटेल थ्रेडिंग बिल्डिंग ब्लॉक आए। और एक समय के लिए, यह अच्छा था।

पुनश्च: आप समवर्ती_संग्रह और समवर्ती_शाह_पाम की तलाश कर रहे हैं


6
वे लॉक-फ़्री नहीं हैं। सॉफ्टवेयर
।intel.com/en-us/forums/intel-threading-building-blocks/…

1
मुझे पता है, लॉक-फ्री की सख्त समझ के लिए, लेकिन मुझे लगा कि इससे ओपी को अपनी समस्या में मदद मिल सकती है, क्योंकि लॉक-फ्री चीज सिर्फ एक कार्यान्वयन विवरण है। मुझे लगा कि वह ऐसे संग्रह की तलाश में हैं जो समवर्ती पहुंच के साथ अच्छी तरह से काम करते हैं।
एडुआर्ड ए।

लॉक-फ्री चीज़ सिर्फ एक इंप्लीमेंटेशन डिटेल नहीं है। यह पूरी तरह से एक अलग जानवर है।
अरुणमोझी

1

मेरी जानकारी के अनुसार, अभी तक सार्वजनिक रूप से ऐसी कोई चीज उपलब्ध नहीं है। एक समस्या को हल करने के लिए एक कार्यान्वयनकर्ता की जरूरत है कि आपको एक लॉक-फ्री मेमोरी एलोकेटर की आवश्यकता है, जो मौजूद है, हालांकि मुझे लिंक अभी नहीं मिल सकता है।


मेरे लिए कोई मतलब नहीं है कि मेमोरी एलोकेटर क्यों उपलब्ध है। बस आंतरिक बिंदुओं के साथ डेटास्ट्रक्चर का उपयोग करें (आप अच्छे पुराने तरीके जानते हैं जब तक कि कंटेनरों के साथ पागल हो गए और सरल हैशटेबल्स को भी लागू करने के लिए कौशल खो दिया)।
लोथार

1

निम्नलिखित समवर्ती ताला मुक्त कतार पर हर्ब सटर के लेख से है http://www.drdobbs.com/parallel/writing-a-generalized-concurrent-queue/211601363?pgno=1 । मैंने कंपाइलर रीग्रॉडिंग सामान जैसे कुछ बदलाव किए हैं। इस कोड को संकलित करने के लिए GCC v4.4 + की आवश्यकता है।

#include <atomic>
#include <iostream>
using namespace std;

//compile with g++ setting -std=c++0x

#define CACHE_LINE_SIZE 64

template <typename T>
struct LowLockQueue {
private:
    struct Node {
    Node( T* val ) : value(val), next(nullptr) { }
    T* value;
    atomic<Node*> next;
    char pad[CACHE_LINE_SIZE - sizeof(T*)- sizeof(atomic<Node*>)];
    };
    char pad0[CACHE_LINE_SIZE];

// for one consumer at a time
    Node* first;

    char pad1[CACHE_LINE_SIZE
          - sizeof(Node*)];

// shared among consumers
    atomic<bool> consumerLock;

    char pad2[CACHE_LINE_SIZE
          - sizeof(atomic<bool>)];

// for one producer at a time
    Node* last;

    char pad3[CACHE_LINE_SIZE
          - sizeof(Node*)];

// shared among producers
    atomic<bool> producerLock;

    char pad4[CACHE_LINE_SIZE
          - sizeof(atomic<bool>)];

public:
    LowLockQueue() {
    first = last = new Node( nullptr );
    producerLock = consumerLock = false;
    }
    ~LowLockQueue() {
    while( first != nullptr ) {      // release the list
        Node* tmp = first;
        first = tmp->next;
        delete tmp->value;       // no-op if null
        delete tmp;
    }
    }

    void Produce( const T& t ) {
    Node* tmp = new Node( new T(t) );
    asm volatile("" ::: "memory");                            // prevent compiler reordering
    while( producerLock.exchange(true) )
        { }   // acquire exclusivity
    last->next = tmp;         // publish to consumers
    last = tmp;             // swing last forward
    producerLock = false;       // release exclusivity
    }

    bool Consume( T& result ) {
    while( consumerLock.exchange(true) )
        { }    // acquire exclusivity
    Node* theFirst = first;
    Node* theNext = first-> next;
    if( theNext != nullptr ) {   // if queue is nonempty
        T* val = theNext->value;    // take it out
        asm volatile("" ::: "memory");                            // prevent compiler reordering
        theNext->value = nullptr;  // of the Node
        first = theNext;          // swing first forward
        consumerLock = false;             // release exclusivity
        result = *val;    // now copy it back
        delete val;       // clean up the value
        delete theFirst;      // and the old dummy
        return true;      // and report success
    }
    consumerLock = false;   // release exclusivity
    return false;                  // report queue was empty
    }
};

int main(int argc, char* argv[])
{
    //Instead of this Mambo Jambo one can use pthreads in Linux to test comprehensively
LowLockQueue<int> Q;
Q.Produce(2);
Q.Produce(6);

int a;
Q.Consume(a);
cout<< a << endl;
Q.Consume(a);
cout<< a << endl;

return 0;
}

4
यह लॉक फ्री नहीं है। यकीन है कि यह ओएस द्वारा प्रदान किए गए एक लॉक का उपयोग नहीं करता है, लेकिन जिस तरह से यह (उदाहरण के लिए) "परमाणु <बूल> कंज्यूमरलॉक" पर घूमता है वह निश्चित रूप से लॉकिंग व्यवहार है। यदि एक धागा दुर्घटनाग्रस्त हो जाता है, तो यह उन तालों में से एक को पकड़ लेता है, और कोई काम नहीं हो सकता। यहां तक ​​कि हर्ब खुद भी ऐसा कहती है (मुझे लगता है कि उस लेख के पेज 4 पर)।
बजे जेम्स कैकसी


0

मैंने 2010 में कुछ बिंदु पर यह लिखा था, मुझे यकीन है कि विभिन्न संदर्भों से मदद मिलेगी। यह मल्टी-प्रोड्यूसर सिंगल कंज्यूमर है।

template <typename T>
class MPSCLockFreeQueue 
{
private:
    struct Node 
    {
        Node( T val ) : value(val), next(NULL) { }
        T value;
        Node* next;
    };
    Node * Head;               
    __declspec(align(4)) Node * InsertionPoint;  //__declspec(align(4)) forces 32bit alignment this must be changed for 64bit when appropriate.

public:
    MPSCLockFreeQueue() 
    {
        InsertionPoint = new Node( T() );
        Head = InsertionPoint;
    }
    ~MPSCLockFreeQueue() 
    {
        // release the list
        T result;
        while( Consume(result) ) 
        {   
            //The list should be cleaned up before the destructor is called as there is no way to know whether or not to delete the value.
            //So we just do our best.
        }
    }

    void Produce( const T& t ) 
    {
        Node * node = new Node(t);
        Node * oldInsertionPoint = (Node *) InterLockedxChange((volatile void **)&InsertionPoint,node);
        oldInsertionPoint->next = node;
    }

    bool Consume( T& result ) 
    {
        if (Head->next)
        {
            Node * oldHead = Head;
            Head = Head->next;
            delete oldHead;
            result = Head->value;
            return true;
        }       
        return false;               // else report empty
    }

};
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.