2015-06-10 26 views
7

मैं एक वास्तविक समय सॉफ्टवेयर बना रहा हूं जहां मेरे पास main() पर मुख्य अनंत लूप हैं और डेटा पढ़ने और संसाधित करने के लिए उपयोग किए जाने वाले धागे हैं।सी ++ std :: स्वतंत्र std :: threads

इनमें से एक समस्या std::vector को थ्रेड चलाने के लिए सिग्नल भेजने और निष्पादन की निगरानी करने के लिए रख रही है।

#include <iostream> 
#include <string> 
#include <vector> 
#include <thread> 
#include <chrono> 

namespace readerThread { 

    void start(int id) 
    { 
     while (1) 
     { 
      std::cout << "Reader " << id << " running..." << std::endl; 
      std::this_thread::sleep_for(std::chrono::milliseconds(1000)); 
     } 
    } 

} 


int main() 
{ 

     int readers[] = { 1, 2, 3 }; 

     std::vector<std::thread> readerThreads; 

     for (int &reader : readers) 
     { 
      std::thread th(readerThread::start, reader); 
      readerThreads.push_back(th); 
     } 

     while(true) 
     { 
      std::cout << "Waiting..." << std::endl; 
      std::this_thread::sleep_for(std::chrono::milliseconds(10000)); 
     } 

     return 0; 
} 

यह संकलन भी नहीं करता है, यह त्रुटि मिल रही:: तो मैं एक साथ इस कोड को

In file included from /usr/local/include/c++/5.1.0/x86_64-unknown-linux-gnu/bits/c++allocator.h:33:0, 
       from /usr/local/include/c++/5.1.0/bits/allocator.h:46, 
       from /usr/local/include/c++/5.1.0/string:41, 
       from /usr/local/include/c++/5.1.0/bits/locale_classes.h:40, 
       from /usr/local/include/c++/5.1.0/bits/ios_base.h:41, 
       from /usr/local/include/c++/5.1.0/ios:42, 
       from /usr/local/include/c++/5.1.0/ostream:38, 
       from /usr/local/include/c++/5.1.0/iostream:39, 
       from main.cpp:1: 
/usr/local/include/c++/5.1.0/ext/new_allocator.h: In instantiation of 'void __gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = std::thread; _Args = {const std::thread&}; _Tp = std::thread]': 
/usr/local/include/c++/5.1.0/bits/alloc_traits.h:256:4: required from 'static std::_Require<std::allocator_traits<_Alloc>::__has_construct<_Tp, _Args ...> > std::allocator_traits<_Alloc>::_S_construct(_Alloc&, _Tp*, _Args&& ...) [with _Tp = std::thread; _Args = {const std::thread&}; _Alloc = std::allocator<std::thread>; std::_Require<std::allocator_traits<_Alloc>::__has_construct<_Tp, _Args ...> > = void]' 
/usr/local/include/c++/5.1.0/bits/alloc_traits.h:402:16: required from 'static decltype (_S_construct(__a, __p, (forward<_Args>)(std::allocator_traits::construct::__args)...)) std::allocator_traits<_Alloc>::construct(_Alloc&, _Tp*, _Args&& ...) [with _Tp = std::thread; _Args = {const std::thread&}; _Alloc = std::allocator<std::thread>; decltype (_S_construct(__a, __p, (forward<_Args>)(std::allocator_traits::construct::__args)...)) = <type error>]' 
/usr/local/include/c++/5.1.0/bits/stl_vector.h:917:30: required from 'void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = std::thread; _Alloc = std::allocator<std::thread>; std::vector<_Tp, _Alloc>::value_type = std::thread]' 
main.cpp:37:30: required from here 
/usr/local/include/c++/5.1.0/ext/new_allocator.h:120:4: error: use of deleted function 'std::thread::thread(const std::thread&)' 
    { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); } 
    ^
In file included from main.cpp:4:0: 
/usr/local/include/c++/5.1.0/thread:126:5: note: declared here 
    thread(const thread&) = delete; 
    ^

धागे areindependent, तो मैं मुख्य कार्यक्रम पर join कॉल करने की आवश्यकता नहीं है और न ही

मेरी कोड क्यों संकलन नहीं करता है: किसी भी धागे पर ...

तो, यहाँ मेरी संदेह कर रहे हैं?

क्या धागे के वेक्टर को स्टोर करने का सही तरीका है?

मदद के लिए धन्यवाद ...

पुनश्च: Original code here:

+0

यदि आप अपने आवेदन को सही तरीके से रोकने की योजना बना रहे हैं, तो आपको थ्रेड ऑब्जेक्ट को नष्ट करने से पहले 'join()' को कॉल करना चाहिए। या ऑब्जेक्ट से अलग थ्रेड के लिए 'detach() 'को कॉल करें। अन्यथा आपको थ्रेड विनाशक में 'समाप्त() 'कॉल मिलेगी। – gomons

+0

गोमन्स, आपका अंक नहीं मिला। शामिल हों() मुख्य थ्रेड निष्पादन को पकड़ लेगा, और यह यहां वांछित नहीं है ... – Mendes

+0

आप 'readerThreads.emplace_back (रीडर थ्रेड :: स्टार्ट, रीडर) का भी उपयोग कर सकते हैं;', क्या गोमन्स का मतलब है कि आपको या तो 'जुड़ना होगा() 'या' डिटेच() 'इसके विनाशक निष्पादन से पहले एक धागा उदाहरण, अन्यथा 'समाप्त()' कहा जाता है। लेकिन आपके धागे हमेशा के लिए दौड़ने के लिए काफी खुश लगते हैं, इसलिए यह ऊपर दिए गए उदाहरण में कोई समस्या नहीं है। – Praetorian

उत्तर

11

आप की तरह

readerThreads.push_back(move(th)); 

यह कुछ का उपयोग करने के th एक rvalue कर देगा, और इस कदम ctor कारण आवश्यकता के नाम से जाना । thread की प्रतिलिपि ctor disabled डिज़ाइन द्वारा थी (एंथनी विलियम्स 'C++ Concurrency In Action देखें)।

+2

हां! अब मुझे याद है कि अन्य रीडिंग्स से .. मदद करने के लिए धन्यवाद ... एक आकर्षण की तरह काम करना ... – Mendes

6
/usr/local/include/c++/5.1.0/ext/new_allocator.h: In instantiation of 'void __gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = std::thread; _Args = {const std::thread&}; _Tp = std::thread]': 
/usr/local/include/c++/5.1.0/bits/alloc_traits.h:256:4: required from 'static std::_Require<std::allocator_traits<_Alloc>::__has_construct<_Tp, _Args ...> > std::allocator_traits<_Alloc>::_S_construct(_Alloc&, _Tp*, _Args&& ...) [with _Tp = std::thread; _Args = {const std::thread&}; _Alloc = std::allocator<std::thread>; std::_Require<std::allocator_traits<_Alloc>::__has_construct<_Tp, _Args ...> > = void]' 
/usr/local/include/c++/5.1.0/bits/alloc_traits.h:402:16: required from 'static decltype (_S_construct(__a, __p, (forward<_Args>)(std::allocator_traits::construct::__args)...)) std::allocator_traits<_Alloc>::construct(_Alloc&, _Tp*, _Args&& ...) [with _Tp = std::thread; _Args = {const std::thread&}; _Alloc = std::allocator<std::thread>; decltype (_S_construct(__a, __p, (forward<_Args>)(std::allocator_traits::construct::__args)...)) = <type error>]' 
/usr/local/include/c++/5.1.0/bits/stl_vector.h:917:30: required from 'void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = std::thread; _Alloc = std::allocator<std::thread>; std::vector<_Tp, _Alloc>::value_type = std::thread]' 
main.cpp:37:30: required from here 
/usr/local/include/c++/5.1.0/ext/new_allocator.h:120:4: error: use of deleted function 'std::thread::thread(const std::thread&)' 
    { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); } 

इसे थोड़ा पीछे छीलने दें।

error: use of deleted function 'std::thread::thread(const std::thread&)' 

आपका कोड ऐसा कुछ कर रहा है जो std::thread पेश करने का प्रयास कर रहा है।

required from 'void std::vector<_Tp, _Alloc>::push_back(const value_type&) 

push_back अपराधी है।

std::thread कॉपी करने योग्य नहीं है - यह मतलब धागे की प्रतिलिपि बनाने के लिए क्या होगा?

std::thread t1([](){}); 
std::thread t2 = t1; 

तो std::thread वस्तुओं के उदाहरण अद्वितीय मालिक होने का इरादा रखते हैं। सरल भ्रम के अलावा, बहुत दर्द होगा।

हालांकि, वे चलने योग्य हैं।

std::thread t1([](){}); 
std::thread t2 = std::move(t1); 

t1 न अब एक वैध धागा वर्णनकर्ता, धागा यह वर्णन किया गया था अब t2 के स्वामित्व में है है।

ऐसी चीजों को कंटेनर में रखने के लिए आप या तो std::move या std::emplace/std::emplace_back का उपयोग कर सकते हैं।

std::vector<std::thread> threads; 
threads.push_back(std::move(std::thread([](){}))); 
threads.emplace_back([](){}); 

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

int main() { 
    std::thread t1([](){ while (true) { std::this_thread::yield(); } }; 
} 

जब मुख्य समाप्त, t1। ~ धागा() कहा जाता है, जो पता लगाता है कि धागा अभी भी जुड़ा हुआ है और शामिल हो गए नहीं, तो इस एक अपवाद बंद दुर्घटना के कारण को जन्म देती है।

आपको या तो join() धागा की आवश्यकता है, इसे चलाने के लिए प्रतीक्षा करने की प्रतीक्षा है, या detach()। यदि आप join() का उपयोग करना चाहते हैं तो आपको थ्रेड को रोकने के लिए कुछ तरीके की आवश्यकता होगी और यदि आप detach() प्रोग्राम थ्रेड के बीच में डेटा लिखने जैसी कुछ चीज़ों से बाहर निकल सकते हैं, तो आप एक गंभीर बग पेश कर सकते हैं।

#include <thread> 
#include <chrono> 
#include <future> 

int main() { 
    std::promise<void> cnx_promise; 
    std::shared_future<void> cnx_future; 

    std::thread t1([cnx_future]() { 
     while (cnx_future.valid()) { 
     std::this_thread::yield(); 
     } 
    }); 

    std::this_thread::sleep_for(std::chrono::seconds(1)); 

    cnx_promise.set_value(); 

    t1.join(); 
} 

यहाँ हम धागा पता कर उसके रुकने का समय है यह बताने के लिए एक वादा उपयोग करें, लेकिन आप शर्त चर, संकेत, आदि इस्तेमाल कर सकते हैं, या यहां तक ​​कि सिर्फ एक सरल std::atomic<bool> ok_to_run { true }; आप गलत के लिए परीक्षण है कि।

1

एक अन्य संस्करण जो काम करता है वह आपकी थ्रेड ऑब्जेक्ट को vector.push_back कॉल में बनाना है। इस मामले में std :: move को कॉल करने की आवश्यकता नहीं है क्योंकि यह पहले से ही एक रावल्यू है (इस प्रकार इसे स्थानांतरित किया जाएगा)।

for (int &reader : readers) 
    readerThreads.push_back(std::thread(readerThread::start, reader)); 
+0

सरल और सबसे अच्छा जवाब। – JulianSoto

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