私は、ブーストの例に基づいて、共有メモリのスレッドセーフ待ち行列クラスを実装しました。シンプルなプロデューサ/コンシューマモデルでは期待通りに動作します。共有メモリにアクセスするときの読み取りアクセス違反
IConcurrentIPCQueue
は、ConcurrentIPCQueue
クラスで実装されているインターフェイスを定義しました。私は別の問題のためのキューにアダプタを実装することができるようにインターフェイスが必要です。
私の最初のバージョンと以下の現在の唯一の違いは以下の通りです:
最初のバージョン:
template <class T> class ConcurrentIPCQueue
は今、私はこのようなインターフェイスを実装すること、情報を追加:
現在のバージョン:
`template <class T> class ConcurrentIPCQueue :public IConcurrentIPCQueue<T>`
は、コンシューマ側の読み取りアクセス違反になります。プロデューサー側では、私は容易にpush_back
とpop_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;
}
は、なぜあなたはあなたの文字列定数は二回定義されていますか?完全な実行可能プログラムを提供できますか? – didierc
これはミニマルモデルを作成するときの間違いでした。私はそれを削除し、main-function()を追加して、プロデューサ()またはコンシューマ( –