Ich implementiert, basierend auf den Boost-Beispielen, eine ThreadSafe Queue-Klasse im Shared Memory. Es funktioniert wie erwartet für ein einfaches Produzenten/Verbraucher-Modell. Als nächsten Schritt habe ich die Schnittstelle IConcurrentIPCQueue
definiert, die von der Klasse ConcurrentIPCQueue
implementiert wird. Ich brauche die Schnittstelle, damit ich einen Adapter zu der Warteschlange für ein anderes Problem implementieren kann.Lesezugriffsverletzung beim Zugriff auf freigegebenen Speicher
Der einzige Unterschied zwischen meiner ersten Version und dem aktuellen unten ist die folgende:
Erste Version:
template <class T> class ConcurrentIPCQueue
nun die Informationen hinzufügen, dass ich die Schnittstelle so implementieren möchten :
Aktuelle Version:
`template <class T> class ConcurrentIPCQueue :public IConcurrentIPCQueue<T>`
führt zu einer Lesezugriffsverletzung auf der Verbraucherseite. Auf der Herstellerseite kann ich einfach push_back
und pop_front
Daten richtig für sich selbst. Aber komischerweise kann ich nicht auf den Shared Memory zugreifen (obwohl das Paar aus segment.find eine Adresse und 1) korrekt zurückgibt. Die Frage ist also, warum die Version mit der Implementierung der Schnittstelle auf der Verbraucherseite einen Unterschied macht und zu diesem seltsamen Fehler führt. Und wie kann ich es lösen?
das Beispiel kurz zu halten, stelle ich hier ein minimalistisches Modell der Warteschlange:
#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;
}
warum haben Sie Ihre String-Konstanten zweimal definiert? Können Sie ein komplettes ausführbares Programm bereitstellen? – didierc
ok, das war ein Fehler bei der Erstellung dieses minimalistischen Modells. Ich löschte es und fügte eine main-function() hinzu, wo man in der Funktion entweder für den Producer() oder den Consumer() –