What an great library! I am trying to extend one of the shared memory examples but I am getting a compilation error. Basically I have added a vector of char_strings to the complex object and added a method to add a string to the vector. If anyone would take a moment to give me suggestion for how to fix this issue or a suggestion for how I should better add strings to this vector I would appreciate your input. The error is: error C2664: 'void boost::container::vector<T,A>::push_back(const boost::interprocess::rv<T> &)' : cannot convert parameter 1 from 'char_string *' to 'const boost::interprocess::rv<T> &' with [T=char_string, A=char_allocator] and[T=boost::container::basic_string<char,std::char_traits<char>,char_allocator>] Reason: cannot convert from 'char_string *' to 'const boost::interprocess::rv<T>' with [T=boost::container::basic_string<char,std::char_traits<char>,char_allocator>] No constructor could take the source type, or constructor overload resolution was ambiguous The code is: #include <boost/interprocess/managed_shared_memory.hpp> #include <boost/interprocess/allocators/allocator.hpp> #include <boost/interprocess/containers/map.hpp> #include <boost/interprocess/containers/vector.hpp> #include <boost/interprocess/containers/string.hpp> using namespace boost::interprocess; //Typedefs of allocators and containers typedef managed_shared_memory::segment_manager segment_manager_t; typedef allocator<void, segment_manager_t> void_allocator; typedef allocator<int, segment_manager_t> int_allocator; typedef vector<int, int_allocator> int_vector; typedef allocator<int_vector, segment_manager_t> int_vector_allocator; typedef vector<int_vector, int_vector_allocator> int_vector_vector; typedef allocator<char, segment_manager_t> char_allocator; typedef basic_string<char, std::char_traits<char>, char_allocator> char_string; typedef vector<char_string, char_allocator> char_string_vector_vector; class complex_data { public: //Obviously making the variables of complex_data public isn't a good idea I am just playing here for the moment int id_; char_string char_string_; char_string_vector_vector char_string_vector_vector_; double price_; //Since void_allocator is convertible to any other allocator<T>, we simplify //the initialization taking just one allocator for all inner containers. complex_data(int id, const char *name, double prce, const void_allocator &void_alloc) : id_(id), char_string_(name, void_alloc), char_string_vector_vector_(void_alloc), price_(prce) {} // add a string --> Error is on the next line void addStringItem(char_string* s){char_string_vector_vector_.push_back(s);} }; int main () { //Remove shared memory on construction and destruction struct shm_remove { shm_remove() { shared_memory_object::remove("MySharedMemory"); } ~shm_remove(){ shared_memory_object::remove("MySharedMemory"); } } remover; //Create shared memory managed_shared_memory segment(create_only,"MySharedMemory", 65536); //An allocator convertible to any allocator<T, segment_manager_t> type void_allocator alloc_inst (segment.get_segment_manager()); //Construct the shared memory map and fill it complex_data *mymap = segment.construct<complex_data>("Complex_Data")(7, "hi", 7.0, alloc_inst); // return 0; }
El 20/07/2011 1:55, Nathan Lewis escribió:
typedef vector<char_string, char_allocator> char_string_vector_vector;
ERROR: you must define a vector with a char_string_allocator, not a char_allocator, since you are storing char_string. Attached a working exmple and differences Best, ion
Thank you for your response. I made the changes and it compiles but now I now notice that the string is not in the vector. It seems that it is somehow allocating outside of the shared memory segment. I don't know if this is an issue since it is using a void allocator. I notice that the size of the vector appears to be correct. Do you have any thoughts on this? Your input is appreciated. Below is the updated code: #include <boost/interprocess/managed_shared_memory.hpp> #include <boost/interprocess/allocators/allocator.hpp> #include <boost/interprocess/containers/map.hpp> #include <boost/interprocess/containers/vector.hpp> #include <boost/interprocess/containers/string.hpp> using namespace boost::interprocess; using std::cout; using std::endl; //Typedefs of allocators and containers typedef managed_shared_memory::segment_manager segment_manager_t; typedef allocator<void, segment_manager_t> void_allocator; typedef allocator<int, segment_manager_t> int_allocator; typedef vector<int, int_allocator> int_vector; typedef allocator<int_vector, segment_manager_t> int_vector_allocator; typedef vector<int_vector, int_vector_allocator> int_vector_vector; typedef allocator<char, segment_manager_t> char_allocator; typedef basic_string<char, std::char_traits<char>, char_allocator> char_string; typedef allocator<char_string, segment_manager_t> char_string_allocator; typedef vector<char_string, char_string_allocator> char_string_vector_vector; typedef char_string_vector_vector::iterator char_string_vector_iterator; class complex_data { public: //Obviously making the variables of complex_data public isn't a good idea I am just playing here for the moment int id_; char_string char_string_; char_string_vector_vector char_string_vector_vector_; double price_; //Since void_allocator is convertible to any other allocator<T>, we simplify //the initialization taking just one allocator for all inner containers. complex_data(int id, const char *name, double prce, const void_allocator &void_alloc) : id_(id), char_string_(name, void_alloc), char_string_vector_vector_(void_alloc), price_(prce) {} // add a string --> Error is on the next line //void addStringItem(char_string* s){char_string_vector_vector_.push_back(*s);} void addStringItem(const char* s) { //Every time you build from a raw string you need an allocator //in the constructor char_allocator alloc(char_string_vector_vector_.get_allocator()); char_string_vector_vector_.push_back(someString/*char_string(s, alloc)*/); } }; int main () { //Remove shared memory on construction and destruction struct shm_remove { shm_remove() { shared_memory_object::remove("MySharedMemory"); } ~shm_remove(){ shared_memory_object::remove("MySharedMemory"); } } remover; //Create shared memory managed_shared_memory segment(create_only,"MySharedMemory", 65536); //An allocator convertible to any allocator<T, segment_manager_t> type void_allocator alloc_inst (segment.get_segment_manager()); char_string tempStr("whatever", alloc_inst); cout << "tempStr = " << tempStr << endl; //Construct the shared memory map and fill it complex_data *mymap = segment.construct<complex_data>("Complex_Data")(7, "hi", 7.0, alloc_inst); mymap->addStringItem("hello"); cout << "Size of char_string_vector_vector = " << mymap->char_string_vector_vector_.size(); char_string_vector_iterator it = mymap->char_string_vector_vector_.begin(); while (it != mymap->char_string_vector_vector_.end()) { cout << "Inserted String is: " << endl; //cout << "Inserted String is: " << it << endl; } //cout << " // return 0; } On 7/20/2011 4:34 PM, Ion Gaztañaga wrote:
El 20/07/2011 1:55, Nathan Lewis escribió:
typedef vector<char_string, char_allocator> char_string_vector_vector;
ERROR: you must define a vector with a char_string_allocator, not a char_allocator, since you are storing char_string. Attached a working exmple and differences
Best,
ion
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
Ion Gaztañaga <igaztanaga <at> gmail.com> writes:
El 20/07/2011 1:55, Nathan Lewis escribió:
typedef vector<char_string, char_allocator> char_string_vector_vector;
ERROR: you must define a vector with a char_string_allocator, not a char_allocator, since you are storing char_string. Attached a working exmple and differences
Best,
ion
Thank you for your response. So I made the changes and started the debugger to see the data in the vector and it turns out it isn't putting the data in the vector. I assume it is creating it on the heap instead even though it appears to me I am using the allocator. I don't know if it is because of the Complex_Data object is constructed with a void allocator or what. Do you have any thoughts on what is going on here? I notice that the size of the vector is increasing when calling the add method but the data is not there #include <boost/interprocess/managed_shared_memory.hpp> #include <boost/interprocess/allocators/allocator.hpp> #include <boost/interprocess/containers/map.hpp> #include <boost/interprocess/containers/vector.hpp> #include <boost/interprocess/containers/string.hpp> using namespace boost::interprocess; using std::cout; using std::endl; //Typedefs of allocators and containers typedef managed_shared_memory::segment_manager segment_manager_t; typedef allocator<void, segment_manager_t> void_allocator; typedef allocator<int, segment_manager_t> int_allocator; typedef vector<int, int_allocator> int_vector; typedef allocator<int_vector, segment_manager_t>int_vector_allocator; typedef vector<int_vector, int_vector_allocator>int_vector_vector; typedef allocator<char, segment_manager_t> char_allocator; typedef basic_string<char, std::char_traits<char>, char_allocator> char_string; typedef allocator<char_string, segment_manager_t> char_string_allocator; typedef vector<char_string, char_string_allocator>char_string_vector_vector; typedef char_string_vector_vector::iterator char_string_vector_iterator; class complex_data { public: //Obviously making the variables of complex_data public isn't a good idea I am just playing here for the moment int id_; char_string char_string_; char_string_vector_vector char_string_vector_vector_; double price_; //Since void_allocator is convertible to any other allocator<T>, we simplify //the initialization taking just one allocator for all inner containers. complex_data(int id, const char *name, double prce, const void_allocator &void_alloc) : id_(id), char_string_(name, void_alloc), char_string_vector_vector_(void_alloc), price_(prce) {} // add a string --> Error is on the next line //void addStringItem(char_string* s) //{char_string_vector_vector_.push_back(*s);} void addStringItem(const char* s) { //Every time you build from a raw string you need an allocator //in the constructor char_allocator alloc(char_string_vector_vector_.get_allocator()); char_string_vector_vector_.push_back(char_string(s, alloc)); } }; int main () { //Remove shared memory on construction and destruction struct shm_remove { shm_remove() { shared_memory_object::remove("MySharedMemory"); } ~shm_remove(){ shared_memory_object::remove("MySharedMemory"); } } remover; //Create shared memory managed_shared_memory segment(create_only,"MySharedMemory", 65536); //An allocator convertible to any allocator<T, segment_manager_t> type void_allocator alloc_inst (segment.get_segment_manager()); char_string tempStr("whatever", alloc_inst); cout << "tempStr = " << tempStr << endl; //Construct the shared memory map and fill it complex_data *mymap = segment.construct<complex_data>("Complex_Data")(7, "hi", 7.0, alloc_inst); mymap->addStringItem("hello"); cout << "Size of char_string_vector_vector = " << mymap->char_string_vector_vector_.size(); char_string_vector_iterator it = mymap->char_string_vector_vector_.begin(); while (it != mymap->char_string_vector_vector_.end()) { cout << "Inserted String is: " << endl; //cout << "Inserted String is: " << it << endl; } //cout << " // return 0; }
El 21/07/2011 19:40, Nathan Lewis escribió:
Ion Gaztañaga<igaztanaga<at> gmail.com> writes:
What does "the data is not there" mean? You can't see it with the debugger because pointers for shared memory are not raw pointers so the debugger can't show values like with heap allocations. Best, Ion
Ion Gaztañaga <igaztanaga <at> gmail.com> writes:
El 21/07/2011 19:40, Nathan Lewis escribió:
Ion Gaztañaga<igaztanaga<at> gmail.com> writes:
What does "the data is not there" mean? You can't see it with the debugger because pointers for shared memory are not raw pointers so the debugger can't show values like with heap allocations.
Best,
Ion _______________________________________________ Boost-users mailing list Boost-users <at> lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
Oh my, Ion I didn't realize that. One reason I was playing with the debugger was because I was having trouble accessing the element in the vector via an iterator. I believe that I've got the iterator set up correctly but can't figure out why I can't print out the elements, what I am doing won't compile. I believe the iterator is a char_string which is just a string that is allocated in the shared memory. What I am trying to do is print it out in the loop below. Ultimately I probably want to copy into regular strings on the other end when in the application on the other end. I am pretty new to template parameters and generic programming. If you don't mind correcting my thinking. Hopefully I'll be able to stop bugging you. I can see my self using this part of boost a fair amount just need to master it better. I've been pointing several other friends the boost interprocess library and they are pretty impressed. Regards, This is the compile error I am getting: error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'char_string_vector_iterator' (or there is no acceptable conversion) ostream(653): could be 'std::basic_ostream<_Elem,_Traits> &std::operator <<<char,std::char_traits<char>>(std::basic_ostream<_Elem,_Traits> &,const char *)' [found using argument-dependent lookup] with[_Elem=char,_Traits=std::char_traits<char>] ... #include <boost/interprocess/managed_shared_memory.hpp> #include <boost/interprocess/allocators/allocator.hpp> #include <boost/interprocess/containers/map.hpp> #include <boost/interprocess/containers/vector.hpp> #include <boost/interprocess/containers/string.hpp> using namespace boost::interprocess; using std::cout; using std::endl; //Typedefs of allocators and containers typedef managed_shared_memory::segment_manager segment_manager_t; typedef allocator<void, segment_manager_t> void_allocator; typedef allocator<int, segment_manager_t> int_allocator; typedef vector<int, int_allocator> int_vector; typedef allocator<int_vector, segment_manager_t> int_vector_allocator; typedef vector<int_vector, int_vector_allocator> int_vector_vector; typedef allocator<char, segment_manager_t> char_allocator; typedef basic_string<char, std::char_traits<char>, char_allocator> char_string; typedef allocator<char_string, segment_manager_t> char_string_allocator; typedef vector<char_string, char_string_allocator> char_string_vector_vector; typedef char_string_vector_vector::iterator char_string_vector_iterator; class complex_data { public: //Obviously making the variables of complex_data public isn't a good idea I am just playing here for the moment int id_; char_string char_string_; char_string_vector_vector char_string_vector_vector_; double price_; //Since void_allocator is convertible to any other allocator<T>, we simplify //the initialization taking just one allocator for all inner containers. complex_data(int id, const char *name, double prce, const void_allocator &void_alloc) : id_(id), char_string_(name, void_alloc), char_string_vector_vector_(void_alloc), price_(prce) {} void addStringItem(const char* s) { //Every time you build from a raw string you need an allocator //in the constructor char_allocator alloc(char_string_vector_vector_.get_allocator()); char_string_vector_vector_.push_back(char_string(s, alloc)); } }; int main () { //Remove shared memory on construction and destruction struct shm_remove { shm_remove() { shared_memory_object::remove("MySharedMemory"); } ~shm_remove(){ shared_memory_object::remove("MySharedMemory"); } } remover; //Create shared memory managed_shared_memory segment(create_only,"MySharedMemory", 65536); //An allocator convertible to any allocator<T, segment_manager_t> type void_allocator alloc_inst (segment.get_segment_manager()); char_string tempStr("whatever", alloc_inst); cout << "tempStr = " << tempStr << endl; //Construct the shared memory map and fill it complex_data *mymap = segment.construct<complex_data>("Complex_Data")(7, "hi", 7.0, alloc_inst); mymap->addStringItem("hello"); mymap->addStringItem("how"); mymap->addStringItem("are"); mymap->addStringItem("you"); cout << "Size of char_string_vector_vector = " << mymap->char_string_vector_vector_.size(); char_string_vector_iterator it = mymap->char_string_vector_vector_.begin(); while (it != mymap->char_string_vector_vector_.end()) { // error is on the line below cout << "Inserted String is: " << it << endl; it++; } // return 0; }
2011/7/22 Nathan Lewis <nathanlewissubscription@gmail.com>
char_string_vector_iterator it = mymap->char_string_vector_vector_.begin(); while (it != mymap->char_string_vector_vector_.end()) { // error is on the line below cout << "Inserted String is: " << it << endl;
cout << "Inserted String is: " << *it << endl; You need the dereference not the iterator itself. HTH
TONGARI <tongari95 <at> gmail.com> writes:
2011/7/22 Nathan Lewis <nathanlewissubscription <at> gmail.com>
char_string_vector_iterator it = mymap->char_string_vector_vector_.begin(); while (it != mymap->char_string_vector_vector_.end()) { // error is on the line below
cout << "Inserted String is: " << it << endl;
cout << "Inserted String is: " << *it << endl; You need the dereference not
the iterator itself.HTH
_______________________________________________ Boost-users mailing list Boost-users <at> lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
If I want to create a new local string out of what was put in shared memory? Thoughts? while (it != mymap->char_string_vector_vector_.end()) { string myNewString(*it); // doesn't compile string myNewString(*it.c_str()); // apparently no equivalent cout << "Inserted String is: " << *it << endl; it++; }
2011/7/22 Nathan Lewis <nathanlewissubscription@gmail.com>
TONGARI <tongari95 <at> gmail.com> writes:
2011/7/22 Nathan Lewis <nathanlewissubscription <at> gmail.com>
char_string_vector_iterator it =
while (it != mymap->char_string_vector_vector_.end()) { // error is on the line below cout << "Inserted String is: " << it << endl;
cout << "Inserted String is: " << *it << endl; You need the dereference not
mymap->char_string_vector_vector_.begin(); the iterator itself.HTH
_______________________________________________ Boost-users mailing list Boost-users <at> lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
If I want to create a new local string out of what was put in shared memory? Thoughts?
while (it != mymap->char_string_vector_vector_.end()) { string myNewString(*it); // doesn't compile string myNewString(*it.c_str()); // apparently no equivalent cout << "Inserted String is: " << *it << endl; it++; }
string myNewString(it->begin(), it->end()); //or string myNewString(it->c_str()); HTH
TONGARI <tongari95 <at> gmail.com> writes:
I hate to continue this, I've been working with this a bit more and am running into another compilation issue that is vague to me. I am now trying to put the object Complex_Data into a vector in shared memory below and it is complaining about the following: error C2679: binary '=' : no operator found which takes a right-hand operand of type 'const complex_data' (or there is no acceptable conversion) 1> c:\code\test.cpp(113): Line 133 is the end of the complex data class (closing bracket) It seems that it is expecting the class to have an assignment operator or copy constructor, I am not sure. I appreciate any help you might have. I am kind of trying to follow the container of container example but instead using a vector. #include <boost/interprocess/managed_shared_memory.hpp> #include <boost/interprocess/allocators/allocator.hpp> #include <boost/interprocess/containers/map.hpp> #include <boost/interprocess/containers/vector.hpp> #include <boost/interprocess/containers/string.hpp> using namespace boost::interprocess; using std::cout; using std::endl; //Typedefs of allocators and containers typedef managed_shared_memory::segment_manager segment_manager_t; typedef allocator<void, segment_manager_t> void_allocator; typedef allocator<int, segment_manager_t> int_allocator; typedef vector<int, int_allocator> int_vector; typedef allocator<int_vector, segment_manager_t>int_vector_allocator; typedef vector<int_vector, int_vector_allocator>int_vector_vector; typedef allocator<char, segment_manager_t> char_allocator; typedef basic_string<char, std::char_traits<char>, char_allocator> char_string; typedef allocator<char_string, segment_manager_t> char_string_allocator; typedef vector<char_string, char_string_allocator>char_string_vector_vector; typedef char_string_vector_vector::iterator char_string_vector_iterator; class complex_data { public: //Obviously making the variables of complex_data public isn't a good idea I am just playing here for the moment int id_; char_string char_string_; char_string_vector_vector char_string_vector_vector_; double price_; //Since void_allocator is convertible to any other allocator<T>, we simplify //the initialization taking just one allocator for all inner containers. complex_data(int id, const char *name, double prce, const void_allocator &void_alloc): id_(id), char_string_(name, void_alloc), char_string_vector_vector_(void_alloc), price_(prce) {} void addStringItem(const char* s) { //Every time you build from a raw string you need an allocator //in the constructor char_allocator alloc(char_string_vector_vector_.get_allocator()); char_string_vector_vector_.push_back(char_string(s, alloc)); } }; typedef allocator<complex_data, segment_manager_t> ShmemExchangeDataAllocator; typedef vector<complex_data, ShmemExchangeDataAllocator> ComplexDataVector; int main () { //Remove shared memory on construction and destruction struct shm_remove { shm_remove() { shared_memory_object::remove("MySharedMemory"); } ~shm_remove(){ shared_memory_object::remove("MySharedMemory"); } } remover; //Create shared memory managed_shared_memory segment(create_only,"MySharedMemory", 65536); //An allocator convertible to any allocator<T, segment_manager_t> type void_allocator alloc_inst(segment.get_segment_manager()); ComplexDataVector* myComplexDataVector = segment.construct<ComplexDataVector>("ComplexDataVector")(alloc_inst); complex_data myItem(7, "hi", 7.0, alloc_inst); myItem.addStringItem("hello"); myItem.addStringItem("how"); myItem.addStringItem("are"); myItem.addStringItem("you"); myComplexDataVector->push_back(myItem); // return 0; }
2011/7/27 Nathan Lewis <nathanlewissubscription@gmail.com>
TONGARI <tongari95 <at> gmail.com> writes:
I hate to continue this, I've been working with this a bit more and am running into another compilation issue that is vague to me. I am now trying to put the object Complex_Data into a vector in shared memory below and it is complaining about the following: error C2679: binary '=' : no operator found which takes a right-hand operand of type 'const complex_data' (or there is no acceptable conversion) 1> c:\code\test.cpp(113):
Line 133 is the end of the complex data class (closing bracket) It seems that it is expecting the class to have an assignment operator or copy constructor, I am not sure. I appreciate any help you might have. I am kind of trying to follow the container of container example but instead using a vector.
Define your complex_data& operator=(complex_data const& other) I have no idea why compiler cannot generate this assignment operator which accepts const&, maybe it's because of the move emulation used by interprocess containers?
TONGARI <tongari95 <at> gmail.com> writes:
Define yourcomplex_data& operator=(complex_data const& other) I have no idea
why compiler cannot generate this assignment operator which accepts const&, maybe it's because of the move emulation used by interprocess containers?
I am wondering if it is because there was internal vectors. So I defined one and tested it in both applications using the shared memory and it seems to work. I defined it as below. Not sure if I really needed to loop over the vector in (rhs) or not was there a cleaner way to do this? It also just felt weird writing one, I am guessing it is really just updating pointers in shared memory? complex_data& operator=(const complex_data &rhs) { this->id_ = rhs.id_; this->char_string_ = rhs.char_string_; this->price_ = rhs.price_; char_string_vector_constiterator it = rhs.char_string_vector_vector_.begin(); while (it != rhs.char_string_vector_vector_.end()) { this->char_string_vector_vector_.push_back(*it); it++; } return(*this); } Also I am now focusing on destructing the object I take out of the vector in the application where I want to read what is put in. I realize that care must be taken when adding/deleting from the vector in two sample applications and think I know what I need to do for that. Also know that deleting from vectors isn't the most efficient way. But as far as the syntax of deleting an object from the vector which both reside in shared memory. I don't believe that pop_back deletes the object that's popped so am looking to firm up for sure how I'd delete one. Looking at the vast examples in the interprocess documentation it appears that one uses segment.destroy for objects that were created in shared memory with segment.construct, such as my vector of complex_data objects; and that for allocations of objects such as in the boost example at the bottom that are created by allocating segment.allocate the object in shared memory one uses segment.deallocate(object) call. However for objects that I've inserted into my vector in the code below, do I also need to call this deallocate method. I've tried it and it doesn't crash. I am looking to get some affirmation on this approach as I don't want to be creating a memory leak in shared memory. Here is the line where I allocated the object and put it in the vector: complex_data myItem(7, "hi", 7.0, alloc_inst); myItem.addStringItem("hello"); myItem.addStringItem("how"); myItem.addStringItem("are"); myItem.addStringItem("you"); myComplexDataVector->push_back(myItem); Here is how I think I should delete: segment.deallocate(&myItem); Below is the complete source example #include <boost/interprocess/managed_shared_memory.hpp> #include <boost/interprocess/allocators/allocator.hpp> #include <boost/interprocess/containers/map.hpp> #include <boost/interprocess/containers/vector.hpp> #include <boost/interprocess/containers/string.hpp> using namespace boost::interprocess; using std::cout; using std::endl; //Typedefs of allocators and containers typedef managed_shared_memory::segment_manager segment_manager_t; typedef allocator<void, segment_manager_t> void_allocator; typedef allocator<int, segment_manager_t> int_allocator; typedef vector<int, int_allocator> int_vector; typedef allocator<int_vector, segment_manager_t>int_vector_allocator; typedef vector<int_vector, int_vector_allocator>int_vector_vector; typedef allocator<char, segment_manager_t> char_allocator; typedef basic_string<char, std::char_traits<char>, char_allocator>char_string; typedef allocator<char_string, segment_manager_t>char_string_allocator; typedef vector<char_string, char_string_allocator>char_string_vector_vector; typedef char_string_vector_vector::iterator char_string_vector_iterator; typedef char_string_vector_vector::const_iterator char_string_vector_constiterator; class complex_data { public: //Obviously making the variables of complex_data public isn't a good idea I am just playing here for the moment int id_; char_string char_string_; char_string_vector_vector char_string_vector_vector_; double price_; //Since void_allocator is convertible to any other allocator<T>, we simplify //the initialization taking just one allocator for all inner containers. complex_data(int id, const char *name, double prce, const void_allocator &void_alloc) : id_(id), char_string_(name, void_alloc), char_string_vector_vector_(void_alloc), price_(prce) {} complex_data& operator=(const complex_data &rhs) { this->id_ = rhs.id_; this->char_string_ = rhs.char_string_; this->price_ = rhs.price_; char_string_vector_constiterator it = rhs.char_string_vector_vector_.begin(); while (it != rhs.char_string_vector_vector_.end()) { this->char_string_vector_vector_.push_back(*it); it++; } return(*this); } void addStringItem(const char* s) { //Every time you build from a raw string you need an allocator //in the constructor char_allocator alloc(char_string_vector_vector_.get_allocator()); char_string_vector_vector_.push_back(char_string(s, alloc)); } }; typedef allocator<complex_data, segment_manager_t> ShmemExchangeDataAllocator; typedef vector<complex_data, ShmemExchangeDataAllocator> ComplexDataVector; int main () { //Remove shared memory on construction and destruction struct shm_remove { shm_remove() { shared_memory_object::remove("MySharedMemory"); } ~shm_remove(){ shared_memory_object::remove("MySharedMemory"); } } remover; //Create shared memory managed_shared_memory segment(create_only,"MySharedMemory", 65536); //An allocator convertible to any allocator<T, segment_manager_t> type void_allocator alloc_inst(segment.get_segment_manager()); ComplexDataVector* myComplexDataVector = segment.construct<ComplexDataVector> ("ComplexDataVector")(alloc_inst); complex_data myItem(7, "hi", 7.0, alloc_inst); myItem.addStringItem("hello"); myItem.addStringItem("how"); myItem.addStringItem("are"); myItem.addStringItem("you"); myComplexDataVector->push_back(myItem); complex_data* myCD = &myComplexDataVector->back(); cout << "Complex Data is: id = " << myCD->id_ << ", char_string_ = " << myCD->char_string_ << ", price = " << myCD->price_ << endl; char_string_vector_iterator it = myCD->char_string_vector_vector_.begin(); while (it != myCD->char_string_vector_vector_.end()) { cout << "Inserted String is: " << *it << endl; it++; //cout << "Something" << endl; } // remove the item from the vector myComplexDataVector->pop_back(); //Deallocate previously allocated memory segment.deallocate(myCD); return 0; } referenced boost example using both allocate and deallocate: int main () { //Remove shared memory on construction and destruction struct shm_remove { shm_remove() { shared_memory_object::remove("MySharedMemory"); } ~shm_remove(){ shared_memory_object::remove("MySharedMemory"); } } remover; //Create shared memory managed_shared_memory segment(create_only, "MySharedMemory", //segment name 65536); //Create linked list with 10 nodes in shared memory offset_ptr<list_node> prev = 0, current, first; int i; for(i = 0; i < 10; ++i, prev = current){ current = static_cast<list_node*>(segment.allocate(sizeof(list_node))); current->value = i; current->next = 0; if(!prev) first = current; else prev->next = current; } //Communicate list to other processes //. . . //When done, destroy list for(current = first; current; /**/){ prev = current; current = current->next; segment.deallocate(prev.get()); } return 0; }
2011/7/28 Nathan Lewis <nathanlewissubscription@gmail.com>
TONGARI <tongari95 <at> gmail.com> writes:
Define yourcomplex_data& operator=(complex_data const& other) I have no
idea why compiler cannot generate this assignment operator which accepts const&, maybe it's because of the move emulation used by interprocess containers?
I am wondering if it is because there was internal vectors.
Not really.
So I defined one and tested it in both applications using the shared memory and it seems to work. I defined it as below. Not sure if I really needed to loop over the vector in (rhs) or not was there a cleaner way to do this?
Normal assignment operator just works. And if you want to push_back a elem into the vector, vector::emplace IMO is the better way to go, and this doesn't require the operator=. e.g. myComplexDataVector->emplace(myComplexDataVector->end(), 7, "hi", 7.0, alloc_inst); [...] Also I am now focusing on destructing the object I take out of the vector in
the application where I want to read what is put in. I realize that care must be taken when adding/deleting from the vector in two sample applications and think I know what I need to do for that. Also know that deleting from vectors isn't the most efficient way. But as far as the syntax of deleting an object from the vector which both reside in shared memory.
I don't believe that pop_back deletes the object that's popped so am looking to firm up for sure how I'd delete one. Looking at the vast examples in the interprocess documentation it appears that one uses segment.destroy for objects that were created in shared memory with segment.construct, such as my vector of complex_data objects; and that for allocations of objects such as in the boost example at the bottom that are created by allocating segment.allocate the object in shared memory one uses segment.deallocate(object) call.
However for objects that I've inserted into my vector in the code below, do I also need to call this deallocate method. I've tried it and it doesn't crash. I am looking to get some affirmation on this approach as I don't want to be creating a memory leak in shared memory.
Generally, you should not deallocate what you didn't allocate by yourself. It's the container's job to deallocate its elems, and it's your job to destruct the container when you don't need it anymore, like: segment.destroy<ComplexDataVector>("ComplexDataVector");
TONGARI <tongari95 <at> gmail.com> writes:
Generally, you should not deallocate what you didn't allocate by yourself.It's
the container's job to deallocate its elems, and it's your job to destruct the container when you don't need it anymore, like: segment.destroy<ComplexDataVector>("ComplexDataVector");
Lots of good learning points I appreciate the learning opportunity. So is what you are explaining is that one would just pop the elements out of the vector and then they would be deleted when this call is made by the resource that "owns" it and is done with it: segment.destroy<ComplexDataVector>("ComplexDataVector"); Or are you explaining that when the pop is called, the internals of the vector implementation invokes the destruction of the object. I so appreciate your responses, it has been tremendously helpful. Working with Boost Interprocess has made me think a lot more about the allocation/deallocation process that tends to get abstracted away but is useful in understanding.
2011/7/28 Nathan Lewis <nathanlewissubscription@gmail.com>
TONGARI <tongari95 <at> gmail.com> writes:
Generally, you should not deallocate what you didn't allocate by
yourself.It's the container's job to deallocate its elems, and it's your job to destruct the container when you don't need it anymore, like: segment.destroy<ComplexDataVector>("ComplexDataVector");
Lots of good learning points I appreciate the learning opportunity. So is what you are explaining is that one would just pop the elements out of the vector and then they would be deleted when this call is made by the resource that "owns" it and is done with it: segment.destroy<ComplexDataVector>("ComplexDataVector");
Or are you explaining that when the pop is called, the internals of the vector implementation invokes the destruction of the object.
Yes. And the allocation/deallocation is performed by the container, say, ComplexDataVector, when it needs to adjust its internal storage. segment.destroy<...>(...) will destruct the found object and deallocate the memory. It's analog of "delete". I so appreciate your responses, it has been tremendously helpful. Working
with Boost Interprocess has made me think a lot more about the allocation/deallocation process that tends to get abstracted away but is useful in understanding.
HTH
participants (4)
-
Ion Gaztañaga
-
Nathan Lewis
-
Nathan Lewis
-
TONGARI