2017-07-05 244 views
1

當讀訪問衝突予實現,基於增壓實例中,線程隊列級在共享存儲器中。它按照預期爲一個簡單的生產者/消費者模型運作。訪問共享存儲器

作爲下一個步驟,我定義其由ConcurrentIPCQueue類實現的接口IConcurrentIPCQueue。我需要這個接口,以便我可以在隊列中實現一個適配器來解決另一個問題。

我的第一個版本,低於當前的唯一區別是:

第一個版本:

template <class T> class ConcurrentIPCQueue 

現在添加的信息,我想實現這樣的接口:

當前版本:

`template <class T> class ConcurrentIPCQueue :public IConcurrentIPCQueue<T>` 

導致讀取訪問衝突在消費者一方。在生產者方面,我可以很容易地自行準確地獲得push_backpop_front數據。但奇怪的是,在消費者方面,我無法訪問共享內存(儘管來自segment.find的對正確返回地址和1)。 所以問題是,爲什麼實現接口的版本在消費者方面有所不同,並導致這個奇怪的錯誤。我該如何解決它?

爲了使這個示例總之,我在這裏排隊的簡約模型:

#include <boost/interprocess/allocators/allocator.hpp> 
#include <boost/interprocess/containers/deque.hpp> 
#include <boost/interprocess/managed_shared_memory.hpp> 
#include <boost/interprocess/sync/interprocess_condition.hpp> 
#include <boost/interprocess/sync/interprocess_mutex.hpp> 
#include <boost/thread/lock_guard.hpp> 
#include <sstream> 

namespace boost_ipc = boost::interprocess; 
static char const *SHMEMNAME= "SHMEM"; 
static char const *SHQUEUENAME= "MYQUEUE"; 

template <class T> class IConcurrentIPCQueue 
{ 
public: 
    virtual void push_back(T const & data) = 0; 
    virtual bool pop_front(T & data) = 0; 
virtual unsigned int size() = 0; 
}; 

template <class T> class ConcurrentIPCQueue :public IConcurrentIPCQueue<T> 
{ 
public: 
    // allocator for allocating memory from the shared memory 
    typedef boost_ipc::allocator<T, boost_ipc::managed_shared_memory::segment_manager> ShmemAlloc; 
    typedef boost_ipc::interprocess_mutex IPC_Mutex; 
    typedef boost_ipc::interprocess_condition IPC_Cond; 
    typedef boost::lock_guard<IPC_Mutex> LockGuard; 

    ConcurrentIPCQueue(ShmemAlloc salloc) : mQueue_(salloc) { } 

    void push_back(T const & data) 
    { 
     { 
      LockGuard lock(mMutex_); 
      mQueue_.push_back(data); 
     } 
     mWait_.notify_one(); 
    } 

    bool pop_front(T & data) 
    { 
     LockGuard lock(mMutex_); 

     if (mQueue_.empty()) 
      return false; 

     data = mQueue_.front(); // return reference to first element 
     mQueue_.pop_front(); // remove the first element 

     return true; 
    } 

unsigned int size() 
{ 
    LockGuard lock(mMutex_); 
    return mQueue_.size(); 
} 

private: 
    boost_ipc::deque<T, ShmemAlloc> mQueue_; 
    IPC_Mutex mMutex_; 
    IPC_Cond mWait_; 
}; 

typedef ConcurrentIPCQueue<char> myqueue; 

void consumer() 
{ 
    boost_ipc::managed_shared_memory openedSegment(boost_ipc::open_only, SHMEMNAME); 

    myqueue*openedQueue = openedSegment.find<myqueue>(SHQUEUENAME).first; 
    char tmp; 

    while (openedQueue->pop_front(tmp)) { 
     std::cout << "Received " << tmp << "\n"; 
    } 
} 

void producer() { 
    boost_ipc::shared_memory_object::remove(SHMEMNAME); 

    boost_ipc::managed_shared_memory mysegment(boost_ipc::create_only, SHMEMNAME, 131072); 

    myqueue::ShmemAlloc alloc(mysegment.get_segment_manager()); 
    myqueue*myQueue = mysegment.construct<myqueue>(SHQUEUENAME)(alloc); 
char mychar='A'; 

    for (int i = 0; i < 10; ++i) 
     myQueue->push_back(mychar); 

    while (myQueue->size() > 0) 
     continue; 
} 

int main() 
{ 
    //producer(); // delete comment for creating producer process 
    consumer(); 
    return 0; 
} 
+0

爲什麼你有你的字符串常量定義了兩次?你能提供一個完整的可運行程序嗎? – didierc

+0

好吧,創建這個簡約模型時這是一個錯誤。我刪除了它,並添加了一個主函數(),其中必須在函數中爲生產者()或消費者() –

回答

1

UPDATE:

我可以MSVC15.3重現它和Boost 1.64。

原來,vtable指針是個問題:它們在每個進程中是不同的,只要你有運行時多態類型(std::is_polymorphic<T>),就會導致未定義行爲。

原來的文件禁止它明確:Is it possible to store polymorphic class in shared memory?

+0

發表評論,這很奇怪,它適用於你。爲什麼當我從界面繼承時,甚至當沒有時,它甚至會有所作爲。我用VS手動增加堆棧和堆大小(Windows上的初始虛擬內存大小),增加了代碼中的「保留」大小,但它仍然無效(除非我不從界面繼承)。也可能是另一個問題呢? –

+0

請確保您的代碼示例演示了此問題。現在我甚至不知道你的意思是「我沒有從界面繼承」。 – sehe

+0

我試圖解釋我的問題好,我希望現在是udnerstandable –