Sono un po 'confuso dall'heap e dalla semantica valore-per-riferimento implicita nel mettere una chiave std::string
e un grande valore struct
in un contenitore come boost::interprocess::map
.Come posso restituire un handle opaco (void * o dword) che può essere restituito a un elemento di valore memorizzato in una mappa di boost :: interprocess?
Ecco la mia situazione, e alcuni typedef sto usando:
typedef std::string AreaKeyType;
typedef DATA_AREA_DESC AreaMappedType; // DATA_AREA_DESC is a big struct.
typedef std::pair<const AreaKeyType, AreaMappedType> AreaValueType;
typedef boost::interprocess::allocator<AreaValueType, boost::interprocess::managed_shared_memory::segment_manager> AreaShmemAllocator;
typedef boost::interprocess::map<AreaKeyType, AreaMappedType, std::less<AreaKeyType>, AreaShmemAllocator> AreaMap;
Ecco come sto inserendo AreaValueType (che è un typedef per std :: coppia):
AreaValueType A(areaKey, arearec);
anAreaMap->insert(A);
Credo che il codice precedente copi A che è una coppia std :: pair sul mio locale (memoria non condivisa) in un'area di memoria condivisa. Posso ottenere un handle su quell'area di memoria condivisa all'interno di boost :: interprocess :: map o sono limitato a recuperare tutto il record e conservarlo intero? (In altre parole, posso memorizzare qualcosa come una struttura in una mappa interprocessa boost e quindi aggiornare un singolo byte all'interno di quel record, oppure devo solo aggiornare l'intero record sostituendo tutti i byte in una struttura DATA_AREA_DESC, con completamente nuovo byte)
Alcuni ulteriori chiarimenti:.
ho una pianura vecchio API di esportazione ANSI C DLL che utilizza internamente C++ e boost :: :: interprocess mappa. Si prevede che la funzione crei un elemento nella mappa e quindi restituisca un handle. Come posso inserire qualcosa nella mappa boost :: interprocess :: e quindi restituire un handle a quell'entità, a utenti non C++, preferibilmente cast a
void*
ounsigned long
? Tutto quello che posso sembrare è di recuperare le cose dalla memoria condivisa cercando il valore della chiave std :: string, e scrivere un nuovo record nella memoria. Mi piacerebbe invece essere in grado di mantenere un riferimento all'oggetto di memoria condivisa in giro.Se non riesco a farlo direttamente, come lo farei indirettamente? Suppongo che potrei conservare una memoria non condivisa std :: vector e allocare una memoria non condivisa std :: string che contiene il valore dell'areaKey, che è una std :: string, e quindi fare un cast di
void*
voce di nuovo astd::string
e quindi utilizzarlo per recuperare una registrazione dall'area di memoria condivisa. Tutto sembra più lavoro di quanto dovrebbe essere strettamente necessario per qualcosa di così elementare. Forse boost :: interprocess :: map non è la scelta giusta per le mie esigenze?
Cosa ho provato? Questo, che compila, ma non ho idea se lo sto facendo bene. In qualche modo mi sento brutta all'interno dereferenziare un ::iterator
tornato da find
, e poi subito di prendere il suo indirizzo in questo modo:
void ** handle; // actually a parameter in my api.
*handle = (void*)&(*anAreaMap->find(areaKey));
Aggiornamento Le opere di cui sopra. Il consiglio molto ragionevole nella risposta qui sotto non funziona comunque. Usando boost :: interprocess :: string si verifica un errore completo e totale e si verifica un arresto anomalo in fase di runtime. Usando std :: string, che non ha il diritto di funzionare a meno che gli autori di Boost non codificano in particolare il supporto per std :: string, funziona davvero alla grande.
beh, si potrebbe usare a() invece di find(), quindi non ci sarebbe il dereferenziamento :) – EHuhtala
Penso che tu abbia ragione. –