2009-04-23 17 views
6

मुझे प्रक्रियाओं (संभवतः भविष्य में अधिक जटिल वस्तुओं) के बीच तारों का एक ढेर साझा करने की आवश्यकता है। मैंने बूस्ट :: इंटरप्रोसेस का उपयोग करने का निर्णय लिया है लेकिन मैं इसे काम नहीं कर सकता। मुझे यकीन है कि ऐसा इसलिए है क्योंकि मैं कुछ समझ नहीं रहा हूं। मैंने उनके उदाहरण का पालन किया, लेकिन अगर मैं उस लाइब्रेरी का उपयोग करने के अनुभव वाले किसी व्यक्ति को अपना कोड देख सकता हूं और मुझे बता सकता है कि क्या गलत है, तो मैं वास्तव में इसकी सराहना करता हूं। समस्या यह है कि ऐसा लगता है लेकिन कुछ पुनरावृत्तियों के बाद मुझे पाठक प्रक्रिया और कभी-कभी लेखक प्रक्रिया पर सभी प्रकार के अपवाद मिलते हैं। यहाँ मेरी कार्यान्वयन का एक सरलीकृत संस्करण है:बूस्ट, साझा मेमोरी और वेक्टर

using namespace boost::interprocess; 
class SharedMemoryWrapper 
{ 
public: 
    SharedMemoryWrapper(const std::string & name, bool server) : 
     m_name(name), 
     m_server(server) 
    { 
     if (server) 
     { 
      named_mutex::remove("named_mutex"); 
      shared_memory_object::remove(m_name.c_str()); 
      m_segment = new managed_shared_memory (create_only,name.c_str(),65536);   
      m_stackAllocator = new StringStackAllocator(m_segment->get_segment_manager()); 
      m_stack = m_segment->construct<StringStack>("MyStack")(*m_stackAllocator); 
     } 
     else 
     { 
      m_segment = new managed_shared_memory(open_only ,name.c_str()); 
      m_stack = m_segment->find<StringStack>("MyStack").first; 
     } 
     m_mutex = new named_mutex(open_or_create, "named_mutex"); 
    } 

    ~SharedMemoryWrapper() 
    { 
     if (m_server) 
     { 
      named_mutex::remove("named_mutex"); 
      m_segment->destroy<StringStack>("MyStack"); 
      delete m_stackAllocator; 
      shared_memory_object::remove(m_name.c_str()); 
     } 
     delete m_mutex; 
     delete m_segment; 
    } 

    void push(const std::string & in) 
    { 
     scoped_lock<named_mutex> lock(*m_mutex); 
     boost::interprocess::string inStr(in.c_str()); 
     m_stack->push_back(inStr); 
    } 
    std::string pop() 
    { 
     scoped_lock<named_mutex> lock(*m_mutex); 
     std::string result = ""; 
     if (m_stack->size() > 0) 
     { 
      result = std::string(m_stack->begin()->c_str()); 
      m_stack->erase(m_stack->begin()); 
     } 
     return result; 
    } 
private: 
    typedef boost::interprocess::allocator<boost::interprocess::string, boost::interprocess::managed_shared_memory::segment_manager> StringStackAllocator; 
    typedef boost::interprocess::vector<boost::interprocess::string, StringStackAllocator> StringStack; 
    bool m_server; 
    std::string m_name; 
    boost::interprocess::managed_shared_memory * m_segment; 
    StringStackAllocator * m_stackAllocator; 
    StringStack * m_stack; 
    boost::interprocess::named_mutex * m_mutex; 
}; 

संपादित named_mutex उपयोग करने के लिए संपादित। मूल कोड interprocess_mutex का उपयोग कर रहा था जो गलत है, लेकिन यह समस्या नहीं थी।

EDIT2 मुझे यह भी ध्यान रखना चाहिए कि चीजें एक बिंदु तक काम करती हैं। लेखक प्रक्रिया पाठक ब्रेक से पहले कई छोटे तारों (या एक बहुत बड़ी स्ट्रिंग) को धक्का दे सकती है। पाठक इस तरह से टूट जाता है कि लाइन m_stack-> प्रारंभ() एक वैध स्ट्रिंग का संदर्भ नहीं देता है। यह कचरा है। और फिर आगे निष्पादन एक अपवाद फेंकता है।

EDIT3 मैंने std :: string के बजाय boost :: interprocess :: string का उपयोग करने के लिए कक्षा को संशोधित किया है। फिर भी पाठक अमान्य स्मृति पते के साथ विफल रहता है। यहां पाठक/लेखक

//reader process 
SharedMemoryWrapper mem("MyMemory", true); 
std::string myString; 
int x = 5; 
do 
{ 
    myString = mem.pop(); 
    if (myString != "") 
    { 
     std::cout << myString << std::endl; 
    } 
} while (1); //while (myString != ""); 

//writer 
SharedMemoryWrapper mem("MyMemory", false); 
for (int i = 0; i < 1000000000; i++) 
{ 
    std::stringstream ss; 
    ss << i; //causes failure after few thousand iterations 
    //ss << "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" << i; //causes immediate failure 
    mem.push(ss.str()); 
} 
return 0; 
+0

मुझे पिछले पोस्टर के लिए बहुत खेद है। मैंने गलती से "हटाएं" पर क्लिक किया और इस सटीक प्रश्न के मूल पोस्ट को मिटा दिया। – Budric

+1

क्या आप मिटा नहीं सकते? या क्या यह केवल उत्तर के लिए काम करता है? –

+0

क्या मुझे आपकी इनलाइन विधियों के आकार पर गड़बड़ करने की अनुमति है? या क्या यह मुझे सी ++ नोब के रूप में चिह्नित करता है? –

उत्तर

4

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

दूसरी बात जो संदिग्ध प्रतीत होती है वह साझा स्मृति के लिए 65k ब्लॉक का आवंटन है, और उसके बाद आपके टेस्ट कोड में, 1000000000 तक लूपिंग, प्रत्येक स्ट्रिंग पर आपके स्ट्रैक पर स्ट्रिंग को दबाकर।

एक आधुनिक पीसी के साथ 1000 माइक्रोसॉन्ड प्रति 1000 निर्देश निष्पादित करने में सक्षम है, और विंडोज़ जैसे ऑपरेटिंग सिस्टम अभी भी 15 मिलीसेकंड में निष्पादन क्वांटा को बाहर कर रहे हैं। भाग, उस ढेर में अतिप्रवाह होने में लंबा समय नहीं लगेगा। यह मेरा पहला अनुमान होगा कि चीजें क्यों खराब हैं।

पीएस मैं अपने नाम को ठीक करने से वापस लौटा, जो मेरी वास्तविक पहचान जैसा दिखता है। फिर विडंबना ने हिट किया कि आपके प्रश्न का मेरा जवाब ब्राउज़र पेज के ऊपरी बाएं कोने से चेहरे पर दोनों को देख रहा है! (यह निश्चित रूप से, मान लीजिए कि मैं सही था, जो अक्सर इस बिज़ में मामला नहीं है।)

+0

मैंने साझा साझा स्मृति को छोड़ दिया है और इसके बजाय Poco :: SharedMemory का उपयोग किया है जो इस प्रयास के बिना काम करता है। परीक्षण कोड कभी भी कई पुनरावृत्तियों तक नहीं पहुंचा।इसके अलावा पाठक को स्मृति मुक्त करने के ढेर से चीजों को पॉप करना चाहिए। – Budric

+0

वह हिस्सा है जिसका मैं पालन नहीं कर सका - मुझे किसी थ्रेड के लिए किसी विशेष स्थान या विधि को किसी अन्य पर नियंत्रण प्राप्त करने के लिए नहीं दिख रहा है - इसलिए मुझे लगता है कि आप एक पर, और फिर दूसरा, राउंड-रॉबिन चला रहे थे। चूंकि विंडोज़ समय के विशाल हिस्सों को देता है, यह 15 मिलीसेकंड ऊपर होने से पहले बफर भर देगा। C++ में IOStreams को अक्सर भी buffered किया जाता है, इसलिए आउटपुट की उपस्थिति या सीमा भ्रामक हो सकती है। मेरे सिद्धांत की जांच करने का तरीका बफर के प्रत्येक तरफ "गार्ड जोन" रखना है और ओवर-लेखन की तलाश करना है। - लेकिन आपने योजनाओं को बदलने के लिए सही विकल्प चुना है। –

-3

शायद साझा स्मृति आपकी समस्या के साथ शुरू करने के लिए सही डिज़ाइन नहीं है। हालांकि हम नहीं जानते, क्योंकि हम नहीं जानते कि आप पहले स्थान पर क्या हासिल करने का प्रयास करते हैं।

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