2017-07-05 47 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 –