2012-10-27 20 views
7

में std :: thread के साथ परमाणुओं का उपयोग करना मेरे पास एक धागा है जिसे मैं एक लूप में बैठना चाहता हूं जब तक कि मैं प्रोग्राम से बाहर निकलने के लिए तैयार न हो, जिस बिंदु पर मैं इसे लूप से बाहर करना चाहता हूं और बाहर निकलें ताकि मैं std::thread::join पर कॉल कर सकूं। सी ++ 03 के दिनों में, मैं बाहर निकलने के लिए धागे को बताने के लिए बस एक लॉक द्वारा संरक्षित बूल का उपयोग करता हूं। इस बार मैंने सोचा कि मैं नई परमाणु पुस्तकालय (विशेष रूप से std::atomic_bool) का लाभ उठाऊंगा, लेकिन मुझे परेशानी हो रही है।सी ++ 11

#include <atomic> 
#include <thread> 
#include <cstdio> 

using namespace std; 

void setBool(atomic_bool& ab) 
{ 
    ab = true; 
} 

int main() 
{ 
    atomic_bool b; 
    b = false; 
    thread t(setBool, b); 
    t.join(); 
    printf("Atomic bool value: %d\n", b.load()); 
    return 0; 
} 

thread t की घोषणा this कुरूपता बाहर थूक जब मैं संकलन करने का प्रयास करें: नीचे अपने परीक्षण मामला है। त्रुटि के मध्य भाग हो रहा है:

प्रकार के गैर-स्थिरांक संदर्भ की अवैध प्रारंभ 'std :: atomic_bool &' प्रकार 'std :: atomic_bool'

क्यों की एक rvalue से क्या मुझे atomic_bool का संदर्भ नहीं मिल सकता है? इसके बजाय मुझे क्या करना चाहिए?

+0

@ निकोलबोलस कैसे? धागे के बीच डेटा साझा करने के लिए एक मानक तरीका तक पहुंचने से पहले एक म्यूटेक्स के साथ एक चर को लॉक नहीं कर रहा है? –

+0

ओह, ठीक है। कभी नहीं ... –

उत्तर

13

आपको स्पष्ट रूप से अपने धागे को रेफरी करना होगा। std::ref का उपयोग std::reference_wrapper बनाएगा जो कॉपी करने योग्य है और आपके फ़ंक्शन को रेफरी करेगा।

thread t(setBool, std::ref(b)); 

अन्यथा यह अपने परमाणु, जो uncopyable है नकल करने की कोशिश करेंगे।

+0

यह एक प्रतिलिपि का प्रयास क्यों करता है? एक संदर्भ तर्क के लिए परिवर्तनीय नाम नहीं दे रहा है पारंपरिक रूप से संदर्भ द्वारा उस चर को पारित करता है? –

+4

@ slavik262 हाँ, यह सच है। धागा कन्स्ट्रक्टर ऐसा करता है, क्योंकि आप एक फ़ंक्शन का आह्वान कर रहे हैं, जिससे आप यह नहीं जानते कि यह कब निष्पादित होगा, यदि आपने कोई संदर्भ पारित किया है, तो संदर्भ अमान्य हो सकता है, इस प्रकार यह आपके तर्कों को सुरक्षित रूप से स्टोर करने के लिए कॉपी करेगा। यदि आप स्पष्ट रूप से एक रेफ-रैपर का उपयोग करते हैं, तो यह सुनिश्चित करना आपका काम है कि ऑब्जेक्ट थ्रेड को पार कर जाएगा। – inf

+0

स्पष्टीकरण के लिए धन्यवाद! –

4

बांस के रूप में समझाया गया है, तो आपको std::ref के साथ ऑब्जेक्ट्स को लपेटना होगा यदि आप वास्तव में उन्हें std::thread के चर-तर्क कन्स्ट्रक्टर के माध्यम से संदर्भित करना चाहते हैं। (यह std::async पर लागू होता है।) इस counterintuitive व्यवहार से बचने के लिए, आप एक लैम्ब्डा का उपयोग कर सकते हैं, जो ठीक वैसे ही व्यवहार करता है जैसा आप उम्मीद करेंगे। बस धागा बनाने के लिए इस का उपयोग करें:

thread t([&]{ setBool(b); }); 

lambdas के साथ, रेफरी/cref बकवास के लिए कोई जरूरत नहीं है जब आप संदर्भ द्वारा तर्क पास करना चाहते हैं।

+0

धन्यवाद!मैं लैम्बदास के बारे में अच्छी तरह से जानता हूं (वे बहुत ही अच्छे हैं) - मैं सिर्फ सी ++ 11 जादू की मात्रा को कम करना चाहता था, जिसका उपयोग मैं अपने परीक्षण मामले के लिए इस मुद्दे को अलग करने के लिए कर रहा था। –

0

मैं बस के साथ-साथ इस में भाग गया, मुझे लगता है कि आप भी तो जैसे परमाणु को पता-एक पास करके अपनी समस्या का समाधान कर सकते हैं:

std::atomic<bool> b{false}; 
std::thread t(setBool, &b); 

जहाँ आपके समारोह परमाणु करने के लिए एक सूचक लेता है:

void setBool(std::atomic<bool>* ab) 

मुझे यकीन नहीं है कि स्वीकार्य अभ्यास क्या है, मुझे लगता है कि आप इस तरह परमाणु को एक शून्य सूचक पास कर सकते हैं लेकिन मुझे यकीन नहीं है कि आप क्यों चाहते हैं।