2012-10-19 18 views
5

मान लीजिए कि मेरे पास कक्षा Base और Derived : public Base है। मैंने बूस्ट :: इंटरप्रोसेस लाइब्रेरी का उपयोग करके एक साझा मेमोरी सेगमेंट बनाया है। क्या यह संभव है इस के समान कोड हैं: जैसे बेस के व्युत्पन्न वर्ग के लिए आवश्यक स्थान अज्ञात हैक्या साझा स्मृति में पॉलीमोर्फिक कक्षा को स्टोर करना संभव है?

Base* b = new Derived(); 
write(b); //one app writes 
Base* b2 = read(b); //second app reads 
//b equals b2 (bitwise, not the ptr location) 

समस्याओं मैं यहाँ देख उदाहरण के लिए है (ताकि कितना shmem आवंटित करने के लिए?)

क्यू: अनुप्रयोगों के बीच पॉइंटर्स के माध्यम से वस्तुओं को कैसे पास किया जाए?

उत्तर

10

बस अपनी documentation

विशेष रूप से पढ़ें:

Virtuality मना

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

यह समस्या हल करना बहुत मुश्किल है, क्योंकि प्रत्येक प्रक्रिया को अलग वर्चुअल टेबल पॉइंटर और उस ऑब्जेक्ट की आवश्यकता होती है जिसमें पॉइंटर कई प्रक्रियाओं में साझा किया जाता है। यहां तक ​​कि यदि हम प्रत्येक प्रक्रिया में एक ही पते में मैप किए गए क्षेत्र को मैप करते हैं, तो वर्चुअल तालिका प्रत्येक प्रक्रिया में एक अलग पते में हो सकती है। प्रक्रियाओं के बीच साझा वस्तुओं के लिए वर्चुअल फ़ंक्शंस को सक्षम करने के लिए, गहरे कंपाइलर परिवर्तनों की आवश्यकता होती है और वर्चुअल फ़ंक्शन प्रदर्शन प्रदर्शन को प्रभावित करेंगे। यही कारण है कि Boost.Interprocess में वर्चुअल फ़ंक्शन और प्रक्रियाओं के बीच साझा मैप किए गए क्षेत्रों में आभासी विरासत का समर्थन करने की कोई योजना नहीं है।

+0

महान, मैं वास्तव में क्या उम्मीद। धन्यवाद! – Queequeg

+0

@Queequeg: दिलचस्प बात यह है कि मैंने पॉलीमोर्फिक ऑब्जेक्ट्स के साथ साझा मेमोरी के नामित सेगमेंट का उपयोग देखा है। इस विशेष मामले में एक एकल प्रक्रिया कभी भी सेगमेंट तक पहुंचती है (साथ ही) और साझा मेमोरी सेगमेंट का उपयोग किया जाता है ताकि प्रक्रिया को क्रैश करना चाहिए, इसे फिर से शुरू करने पर इसकी सभी स्थिति वापस मिल सकती है। इसमें सभी आभासी पॉइंटर्स को फिर से लिखना शामिल है, इसलिए यह निश्चित रूप से शामिल है। –

3

मुझे विश्वास है कि आप वस्तुओं के क्रमबद्धीकरण को देख रहे हैं। सी ++ वर्ग में एक और एप्लिकेशन 3. deserialize करने के लिए 1. serialize अपने सी ++ वर्ग 2. भेजने डेटा: http://www.boost.org/doc/libs/1_51_0/libs/serialization/doc/index.html

आप निम्न तरीकों से कर सकते हैं पर एक नज़र डालें।

+1

+1! जैसा कि टोनी होरे ने सीएसपी में कहा था: * संचार करके संवाद न करें, संचार करके साझा करें। * –

+0

क्रमबद्धता के साथ अच्छा विचार, +1 – Queequeg

+0

बेशक आप व्युत्पन्न कक्षा भेज सकते हैं। लेकिन एक "बहुरूपता" के रूप में नहीं। – CashCow

3

साझा स्मृति मूल रूप से केवल पीओडी संरचनाओं (दिल में, उनके पास रचनाकार/प्रति/आदि हो सकती है ...) की अनुमति देता है।

Boost.Interprocess साझा मेमोरी सेगमेंट में ऑफ़सेट के शीर्ष पर पॉइंटर्स सेमेन्टिक्स को अनुकरण करके बार बढ़ाता है।

हालांकि, एक आभासी सूचक शुद्ध डेटा के लिए सूचक नहीं है, यह कोड वर्गों के लिए एक सूचक है, और है कि जहां चीजें जटिल हो क्योंकि कोड वर्गों जरूरी एक से दूसरे प्रक्रिया से एक ही पते पर मैप नहीं कर रहे हैं (भले ही वे एक ही बाइनरी से लॉन्च किए गए हों)।

तो ... नहीं, वर्चुअल पॉइंटर्स-पॉलीमोर्फिक ऑब्जेक्ट्स साझा स्मृति में संग्रहीत नहीं किए जा सकते हैं।


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

तो, बहुरूपता साझा स्मृति के साथ संगत पाने के लिए: हम नहीं जरूरत टेबल/कार्यों के लिए संकेत स्टोर करने के लिए, लेकिन हम अनुक्रमित स्टोर कर सकते हैं।

विचार का उदाहरण, लेकिन शायद परिष्कृत किया जा सकता है।

/// In header 
#include <cassert> 

#include <vector> 

template <class, size_t> class BaseT; 

class Base { 
    template <class, size_t> friend class BaseT; 
public: 

    int get() const; //  -> Implement: 'int getImpl() const' in Derived 

    void set(int i); // = 0 -> Implement: 'void setImpl(int i)' in Derived 

private: 
    struct VTable { 
     typedef int (*Getter)(void const*); 
     typedef void (*Setter)(void*, int); 

     VTable(): _get(0), _set(0) {} 

     Getter _get; 
     Setter _set; 
    }; 

    static std::vector<VTable>& VT(); // defined in .cpp 

    explicit Base(size_t v): _v(v) {} 

    size_t _v; 
}; // class Base 

template <class Derived, size_t Index> 
class BaseT: public Base { 
public: 
    BaseT(): Base(Index) { 
     static bool const _ = Register(); 
     (void)_; 
    } 

    // Provide default implementation of getImpl 
    int getImpl() const { return 0; } 

    // No default implementation setImpl 

private: 
    static int Get(void const* b) { 
     Derived const* d = static_cast<Derived const*>(b); 
     return d->getImpl(); 
    } 

    static void Set(void* b, int i) { 
     Derived* d = static_cast<Derived*>(b); 
     d->setImpl(i); 
    } 

    static bool Register() { 
     typedef Base::VTable VTable; 

     std::vector<VTable>& vt = Base::VT(); 

     if (vt.size() <= Index) { 
      vt.insert(vt.end(), Index - vt.size() + 1, VTable()); 
     } else { 
      assert(vt[Index]._get == 0 && "Already registered VTable!"); 
     } 

     vt[Index]._get = &Get; 
     vt[Index]._set = &Set; 
    } 
}; // class BaseT 

/// In source 
std::vector<VTable>& Base::VT() { 
    static std::vector<VTable> V; 
    return V; 
} // Base::VT 

int Base::get() const { 
    return VT()[_v]._get(this); 
} // Base::get 

void Base::set(int i) { 
    return VT()[_v]._set(this, i); 
} // Base::set 

ठीक है ... मुझे लगता है कि है कि अब आप उपयोग के बारे में संकलक का जादू ...

सराहना करते हैं, यह सौभाग्य से बहुत सरल है:

/// Another header 
#include <Base.h> 

// 4 must be unique within the hierarchy 
class Derived: public BaseT<Derived, 4> { 
    template <class, size_t> friend class BaseT; 
public: 
    Derived(): _i(0) {} 

private: 
    int getImpl() const { return _i; } 

    void setImpl(int i) { _i = i; } 

    int _i; 
}; // class Derived 
ideone पर

कार्रवाई में।

-1
//From the example above , I have removed VTable 
// I also removed static variables as per boost::interprocess 
// static variable don't work with shared memory, and also I did not see 
// any advantage in actually builting a VTable for all derived classes 
#include <vector> 
#include <boost/bind.hpp> 
#include <boost/function.hpp> 

template <class> class BaseT; 

class Base { 
    template <class> friend class BaseT; 
    boost::function< int (void) > _get; 
    boost::function< void (int) > _set; 
public: 

    int get() { 
     return _get(); 
    } //  -> Implement: 'int get() ' in Derived 

    void set(int i) { 
     _set(i); 
    } // = 0 -> Implement: 'void set(int i)' in Derived 
}; // class Base 

template <class Derived> 
class BaseT : public Base { 

public: 
    BaseT() : Base(), impl(static_cast<Derived *> (this)) { 
     Base::_get = boost::bind(&BaseT<Derived>::get, this); 
     Base::_set = boost::bind(&BaseT<Derived>::set, this, _1); 
    } 

    int get() { 
     return impl->get(); 
    } 

    void set(int i) { 
     impl->set(i); 
    } 

private: 
    Derived * impl; 
}; 


//some A implementation of Base 
struct A : BaseT<A> { 

    int get() { 
     return 101; //testing implementation 
    } 

    void set(int i) { 
     ; //implementation goes here 
    } 
}; 

//some B implementation of Base 
struct B : BaseT<B> { 

    int get() { 
     return 102; //testing implementation 
    } 

    void set(int i) { 
     ; //implementation goes here 
    } 
}; 

int main() { 
    BaseT<A> objectA; 
    BaseT<B> objectB; 
    Base *a = &objectA; 
    Base *b = &objectB; 
    std::cout << a->get() << " returned from A class , " 
      << b->get() << " returned from B class " << std::endl; 
    return 0; 
} 
+0

मैं किसी को +10 के साथ देखता हूं कि पॉलिमॉर्फिक कक्षाओं को स्टोर करना संभव नहीं है और किसी ने मुझे वोट दिया है। मैं सुझाव देता हूं कि वोटिंग से पहले इस "संकलन समय और रनटाइम पॉलिमॉर्फिज्म सी ++ में" डाल दिया गया है। हालांकि कैशको को 10 वोट प्राप्त हुए, उनका बयान केवल आभासी तालिकाओं पर लागू होता है - रनटाइम पॉलीमोर्फिक वर्गों के गुण। समुदाय उन पुराने फैशन समाधानों से आगे बढ़ गया, हम पहले ही सी ++ 17 का उपयोग करते हैं। कृपया मूल प्रश्न पढ़ें: "क्या साझा स्मृति में पॉलीमोर्फिक वर्ग को स्टोर करना संभव है?" । यह विशेष रूप से नहीं कहता है कि यह रनटाइम polymorphism या संकलन समय polymorphism है। –

-1
//While redefining I changed semantics of constnance in getter, 
//and had non- const Derived pointer used for both getter and setter. 
//But original simantics can be preserved as following: 

    int get() const { 
     //return impl->get(); 
     //this enforces that get has to be const 
     static_cast<const Derived *> (this)->get() ; 
    } 
+0

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