5

में एक सी ++ 11 कंडीशन वैरिएबल का उपयोग करके मैं एक साधारण वीएस2012 कंसोल एप्लिकेशन में भरोसेमंद कोड प्राप्त नहीं कर सकता जो एक निर्माता और उपभोक्ता है जो सी ++ 11 कंडीशन वैरिएबल का उपयोग करता है।वीएस2012

condition_variable:: मैं (एक अधिक जटिल कार्यक्रम के लिए आधार के रूप में उपयोग करने के लिए) एक छोटे से विश्वसनीय प्रोग्राम कोड मैं इन वेबसाइटों पर इकट्ठे हुए हैं से विधि या शायद wait_until विधि wait_for 3 तर्क का उपयोग करता है के उत्पादन में लक्ष्य कर रहा हूँ wait_for , wait_until

मैं नीचे दिए गए भविष्य के साथ 3 तर्क प्रतीक्षा_for का उपयोग करना चाहता हूं सिवाय इसके कि इसे बाद में मेरे लिए सबसे उपयोगी होने के लिए कक्षा सदस्य चर का उपयोग करने की आवश्यकता होगी। मुझे "उल्लंघन उल्लंघन लेखन स्थान 0x_ _" या "एक अमान्य पैरामीटर किसी सेवा या फ़ंक्शन में पास किया गया था" केवल एक मिनट चलने के बाद त्रुटियों के रूप में।

steady_clock और 2 तर्क wait_until 3 तर्क wait_for को प्रतिस्थापित करने के लिए पर्याप्त होगा? मैंने सफलता के बिना भी कोशिश की है।

क्या कोई दिखा सकता है कि बिना किसी बग या अजीब व्यवहार के बिना अनिश्चित काल तक चलाने के लिए नीचे कोड कैसे प्राप्त किया जा सकता है, जिसमें डेलाइट बचत समय या इंटरनेट समय सिंक्रनाइज़ेशन से दीवार घड़ी के समय में परिवर्तन शामिल हैं?

विश्वसनीय नमूना कोड का एक लिंक उतना ही उपयोगी हो सकता है।

// ConditionVariable.cpp : Defines the entry point for the console application. 
// 

#include "stdafx.h" 

#include <condition_variable> 
#include <mutex> 
#include <thread> 
#include <iostream> 
#include <queue> 
#include <chrono> 
#include <atomic> 

#define TEST1 

std::atomic<int> 
//int 
    qcount = 0; //= ATOMIC_VAR_INIT(0); 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    std::queue<int> produced_nums; 
    std::mutex m; 
    std::condition_variable cond_var; 
    bool notified = false; 
    unsigned int count = 0; 

    std::thread producer([&]() { 
     int i = 0; 
     while (1) { 
      std::this_thread::sleep_for(std::chrono::microseconds(1500)); 
      std::unique_lock<std::mutex> lock(m); 
      produced_nums.push(i); 
      notified = true; 
      qcount = produced_nums.size(); 
      cond_var.notify_one(); 
      i++; 
     } 
     cond_var.notify_one(); 
    }); 

    std::thread consumer([&]() { 
     std::unique_lock<std::mutex> lock(m); 
     while (1) { 
#ifdef TEST1 
      // Version 1 
      if (cond_var.wait_for(
       lock, 
       std::chrono::microseconds(1000), 
       [&]()->bool { return qcount != 0; })) 
      { 
       if ((count++ % 1000) == 0) 
        std::cout << "consuming " << produced_nums.front () << '\n'; 
       produced_nums.pop(); 
       qcount = produced_nums.size(); 
       notified = false; 
      } 
#else 
      // Version 2 
      std::chrono::steady_clock::time_point timeout1 = 
       std::chrono::steady_clock::now() + 
       //std::chrono::system_clock::now() + 
       std::chrono::milliseconds(1); 

      while (qcount == 0)//(!notified) 
      { 
       if (cond_var.wait_until(lock, timeout1) == std::cv_status::timeout) 
        break; 
      } 

      if (qcount > 0) 
      { 
       if ((count++ % 1000) == 0) 
       std::cout << "consuming " << produced_nums.front() << '\n'; 
       produced_nums.pop(); 
       qcount = produced_nums.size(); 
       notified = false; 
      } 
#endif 
     } 
    }); 

    while (1); 
    return 0; 
} 

विजुअल स्टूडियो डेस्कटॉप एक्सप्रेस में 1 महत्वपूर्ण अपडेट था जो इसे स्थापित किया गया था और विंडोज अपडेट में कोई अन्य महत्वपूर्ण अपडेट नहीं है। मैं विंडोज 7 32-बिट का उपयोग कर रहा हूँ।

उत्तर

1

सबसे पहले, condition_variable रों का उपयोग करते समय मैं व्यक्तिगत रूप से सी # से AutoResetEvent जैसे कुछ आवरण वर्गों पसंद करते हैं:

struct AutoResetEvent 
{ 
    typedef std::unique_lock<std::mutex> Lock; 

    AutoResetEvent(bool state = false) : 
     state(state) 
    { } 

    void Set() 
    { 
     auto lock = AcquireLock(); 
     state = true; 
     variable.notify_one(); 
    } 

    void Reset() 
    { 
     auto lock = AcquireLock(); 
     state = false; 
    } 

    void Wait(Lock& lock) 
    { 
     variable.wait(lock, [this]() { return this->state; }); 
     state = false; 
    } 

    void Wait() 
    { 
     auto lock = AcquireLock(); 
     Wait(lock); 
    } 

    Lock AcquireLock() 
    { 
     return Lock(mutex); 
    } 
private: 

    bool state; 
    std::condition_variable variable; 
    std::mutex mutex; 
}; 

इस रूप में सी # प्रकार समान व्यवहार नहीं हो सकता है या के रूप में यह होना चाहिए नहीं के रूप में कुशल हो सकता है लेकिन यह मेरे लिए चीजें हो जाती है।

दूसरा, जब मुझे एक उत्पादक/उपभोग करने वाली मुहावरे को लागू करने की आवश्यकता होती है तो मैं एक समवर्ती कतार कार्यान्वयन (उदाहरण के लिए tbb queue) का उपयोग करने की कोशिश करता हूं या खुद के लिए एक लिखता हूं। लेकिन आपको Active Object Pattern का उपयोग कर चीजों को सही बनाने पर भी विचार करना चाहिए। लेकिन सरल समाधान के लिए हम इस का उपयोग कर सकते हैं:

template<typename T> 
struct ProductionQueue 
{ 
    ProductionQueue() 
    { } 

    void Enqueue(const T& value) 
    { 
     { 
      auto lock = event.AcquireLock(); 
      q.push(value); 
     } 
     event.Set(); 
    } 

    std::size_t GetCount() 
    { 
     auto lock = event.AcquireLock(); 

     return q.size(); 
    } 

    T Dequeue() 
    { 
     auto lock = event.AcquireLock(); 
     event.Wait(lock); 

     T value = q.front(); 
     q.pop(); 

     return value; 
    } 

private: 
    AutoResetEvent event; 
    std::queue<T> q; 
}; 

इस वर्ग के कुछ अपवाद सुरक्षा के मुद्दों और छूट जाए तरीकों पर स्थिरांक सत्ता है, लेकिन जैसे मैंने कहा, एक सरल समाधान के लिए इस फिट चाहिए।

तो एक परिणाम के रूप में अपने संशोधित कोड इस तरह दिखता है:

int main(int argc, char* argv[]) 
{ 
    ProductionQueue<int> produced_nums; 
    unsigned int count = 0; 

    std::thread producer([&]() { 
     int i = 0; 
     while (1) { 
      std::this_thread::sleep_for(std::chrono::microseconds(1500)); 
      produced_nums.Enqueue(i); 
      qcount = produced_nums.GetCount(); 
      i++; 
     } 
    }); 

    std::thread consumer([&]() { 
     while (1) { 
      int item = produced_nums.Dequeue(); 
      { 
       if ((count++ % 1000) == 0) 
        std::cout << "consuming " << item << '\n'; 
       qcount = produced_nums.GetCount(); 
      } 
     } 
    }); 

    producer.join(); 
    consumer.join(); 

    return 0; 
} 
+0

आपका कोड 'wait_for' या' wait_until' का उपयोग नहीं करता है और इसलिए ओ पी की समस्या का समाधान नहीं होता। –

4

दुख की बात है, तो यह वास्तव condition_variable की VS2012 के कार्यान्वयन में एक बग है, और दुविधा में समझौता नहीं किया जाएगा, आपको अपग्रेड करना होगा। वीएस2013 को रिलीज होने पर।

देखें:

http://connect.microsoft.com/VisualStudio/feedback/details/762560

+0

क्या यह किसी भी बहुप्रचारित एप्लिकेशन/लाइब्रेरी के लिए बनाम2012 बेकार (बदतर अभी तक हानिकारक) नहीं है?मैं माइक्रोसॉफ्ट द्वारा बहुत निराश होगा अगर वे जो एकमात्र समाधान दे रहे हैं वह सिर्फ अपने उत्पाद का उपयोग नहीं करना है (इसके बजाय बूस्ट कंडीशन_विएरीबल इत्यादि का उपयोग करें)। दुर्भाग्यवश हमारे पास बनाम2012 पर एक बड़ा से बड़ा कोडबेस है और मैं हाल ही में बूस्ट लोगों की बजाय std :: condition_variable, std :: mutex आदि में कनवर्ट करने की योजना बना रहा था। तो यह मेरी योजनाओं का अंत है। वास्तव में – Mert

+0

। एमएस को अपने सॉफ्टवेयर के पुराने संस्करणों पर रखने के लिए कोई प्रोत्साहन नहीं है। जब मैं कुछ साल पहले इसी तरह की स्थिति में था, तो हमें विकल्पों का उपयोग करने के लिए मजबूर होना पड़ा। – brendanw

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