c++ library Ist es möglich, std:: vector in Shared Memory zu platzieren?



c++ vector (4)

Sie müssen Ihren eigenen Allokator implementieren, um dies zu erreichen. Der Zuordner ist ein std::vector<> Template-Parameter.

Ich würde std :: vector in Shared Memory mit CreateFileMapping () Windows-API-Funktion erstellen. Ich weiß, wie man gemeinsam genutzten Speicher erstellt und verwaltet, aber wie man std :: vector an feste Adresse im Speicher setzt? Ich kann Boost oder andere Bibliotheken in meinem Fall nicht verwenden, ich benutze CBuilder ++ 2010. Eine Variante, die ich denke, ist möglicherweise zu verwenden

std::vector<int> myVec; 
myVec *mv;
mv = shared_memory_addr ?

Aber wie erkenne ich die tatsächliche Größe von Vektoren, um die Größe des Speichers zu ändern?


Answer #1

Verwenden Sie placement new, um einen Vektor im Shared Memory zu erstellen. Sie benötigen außerdem einen Zuordner für den Vektor, damit er den gemeinsamen Speicher für seinen Elementspeicher verwenden kann. Wenn der Vektor nur int speichert und Sie den Shared-Memory-Bereich in jedem Prozess auf die gleiche virtuelle Adresse setzen können, könnte dies funktionieren.


Answer #2

Eigentlich müssen Sie beides tun : Verwenden Sie placement new, um die std::vector Instanz im Shared Memory zu erstellen, und verwenden Sie einen benutzerdefinierten Zuordner, um den Vektor dazu zu bringen, seine Daten ebenfalls im Shared Memory zu platzieren.

Denken Sie daran, dass Sie jeden Zugriff auf den Vektor synchronisieren müssen (außer wenn Sie nur Lesezugriff benötigen) - std::vector ist im Allgemeinen nicht threadsicher und deklariert keine seiner Member als volatile , was den gleichzeitigen Zugriff volatile macht der Umfang des Compilers - wie es in einem Shared-Memory-Bereich passiert - ist extrem gefährlich.

... schließlich würde ich es nicht tun . Shared Memory ist ein sehr kniffliges, sehr kniffliges Konzept, es passt nicht gut zu Datencontainern wie std::vector in einer Sprache, die (wie cpp03) keine guten integrierten Lösungen für die Parallelität bietet Probleme und das ist nicht bewusst, dass so etwas wie Shared Memory existiert.

... es könnte sogar undefiniertes Verhalten auslösen: Während std::vector Allgemeinen seinen allocator , um Speicher für seine Elemente zu holen, ist es (soweit ich weiß) erlaubt, weiteren Speicher zuzuweisen (dh für interne Zwecke, was auch immer das sein mag) ) malloc oder jede andere Zuweisungsstrategie verwenden (ich denke, die std::vector Implementierung von Microsoft macht das in Debug-Builds) ... diese Zeiger wären nur für eine Seite der Speicherzuordnung gültig.

Um den std::vector zu vermeiden, würde ich einfach genügend Speicher im abgebildeten Bereich im Voraus zuweisen und einen einfachen Zähler verwenden, um die Anzahl der gültigen Elemente beizubehalten. Das sollte sicher sein.


Answer #3

Sie könnten Shared Memory verwenden, der auf eine feste Adresse abgebildet wird, dh die Adresse wäre in jedem Prozess gleich, so dass rohe Zeiger verwendet werden können.

Wenn Sie also Folgendes tun, können Sie (mehrere) Bereiche mit gemeinsam genutztem Speicher haben:

#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/allocators/allocator.hpp>

struct MySegment {
    static const size_t alloc_size = 1048576;
    static const void *getAddr() { return (void *)0x400000000LL; }
    static const char *getSegmentName() { return "MySegment"; }
};

template <typename MemorySegment>
class SharedMemory {
public:
    typedef boost::interprocess::fixed_managed_shared_memory shared_memory_t;
    typedef shared_memory_t::segment_manager segment_manager_t;

    static shared_memory_t *getSegment() {
        if (!segment) {
            assert(MemorySegment::getAddr() != 0 && "want a fixed address for all processes");
            segment = new boost::interprocess::managed_shared_memory(
                    boost::interprocess::open_or_create,
                    MemorySegment::getSegmentName(),
                    MemorySegment::alloc_size,
                    MemorySegment::getAddr());
        }
        return segment;
    }
    static segment_manager_t *getSegmentManager() {
        return getSegment()->get_segment_manager(); }

private:
    static boost::interprocess::managed_shared_memory *segment;
};
template <typename MemorySegment>
typename SharedMemory<MemorySegment>::shared_memory_t *SharedMemory<MemorySegment>::segment = NULL;


template <class MemorySegment, class T>
class SharedMemoryAllocator {
public:
    typedef boost::interprocess::allocator<T, typename SharedMemory<MemorySegment>::segment_manager_t> InterprocessAllocator;

    // Delegate all calls to an instance of InterprocessAllocator,
    pointer allocate(size_type n, const void *hint = 0) { return TempAllocator().allocate(n, hint); }
    void deallocate(const pointer &p, size_type n) { return TempAllocator().deallocate(p, n); }
    size_type max_size() const { return TempAllocator().max_size(); }
    void construct(const pointer &ptr, const_reference v) { return TempAllocator().construct(ptr, v); }
    void destroy(const pointer &ptr) { return TempAllocator().destroy(ptr); }

    typedef typename InterprocessAllocator::value_type value_type;
    typedef typename InterprocessAllocator::pointer pointer;
    typedef typename InterprocessAllocator::reference reference;
    typedef typename InterprocessAllocator::const_pointer const_pointer;
    typedef typename InterprocessAllocator::const_reference const_reference;
    typedef typename InterprocessAllocator::size_type size_type;
    typedef typename InterprocessAllocator::difference_type difference_type;

    SharedMemoryAllocator() {}
    template <class U> SharedMemoryAllocator(const SharedMemoryAllocator<MemorySegment, U> &u) {}

    template <typename OtherT> struct rebind { typedef SharedMemoryAllocator<MemorySegment, OtherT> other; };

private:
    static InterprocessAllocator TempAllocator() {
        return InterprocessAllocator(SharedMemory<MemorySegment>::getSegmentManager());
    }
};

Dann könnten Sie verwenden:

       std::vector<int, SharedMemoryAllocator<MySegment, int> vec;

und die Elemente des Vektors würden in einen gemeinsamen Speicher gebracht werden (natürlich muss auch vec dort zugewiesen werden).





stl