diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 index ed2d7da..0f9bd77 100644 --- a/doc/Jamfile.v2 +++ b/doc/Jamfile.v2 @@ -1,6 +1,6 @@ # Boost.Interprocess library documentation Jamfile --------------------------------- # -# Copyright Ion Gaztañaga 2005-2006. Use, modification and +# Copyright Ion Gaztañaga 2005-2007. Use, modification and # distribution is subject to the Boost Software License, Version # 1.0. (See accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) @@ -27,19 +27,11 @@ doxygen interprocess_doxygen EXTRACT_ALL=NO HIDE_UNDOC_MEMBERS=YES EXTRACT_PRIVATE=NO - ENABLE_PREPROCESSING=NO - MACRO_EXPANSION=YES +# ENABLE_PREPROCESSING=NO +# MACRO_EXPANSION=YES EXPAND_ONLY_PREDEF=YES - SEARCH_INCLUDES=YES - INCLUDE_PATH=$(BOOST_ROOT) -# EXTRACT_ALL=NO -# HIDE_SCOPE_NAMES=YES -# HIDE_UNDOC_MEMBERS=YES -# EXTRACT_PRIVATE=NO -# ENABLE_PREPROCESSING=YES -# MACRO_EXPANSION=YES -# EXPAND_ONLY_PREDEF=YES -# SEARCH_INCLUDES=YES +# SEARCH_INCLUDES=YES +# INCLUDE_PATH=$(BOOST_ROOT) ; xml interprocess_xml : interprocess.qbk ; diff --git a/doc/code/Attic/doc_anonymous_conditionA.cpp b/doc/code/Attic/doc_anonymous_conditionA.cpp deleted file mode 100644 index aba35bb..0000000 --- a/doc/code/Attic/doc_anonymous_conditionA.cpp +++ /dev/null @@ -1,66 +0,0 @@ - #include - #include - #include - #include - #include - #include "doc_anonymous_condition_shared_data.hpp" - - using namespace boost::interprocess; - - int main () - { - try{ - //Erase previous shared memory - shared_memory_object::remove("shared_memory"); - - //Create a shared memory object. - shared_memory_object shm - (create_only //only create - ,"shared_memory" //name - ,read_write //read-write mode - ); - - //Set size - shm.truncate(sizeof(trace_queue)); - - //Map the whole shared memory in this process - mapped_region region - (shm //What to map - ,read_write //Map it as read-write - ); - - //Get the address of the mapped region - void * addr = region.get_address(); - - //Construct the shared structure in memory - trace_queue * data = new (addr) trace_queue; - - const int NumMsg = 100; - - for(int i = 0; i < NumMsg; ++i){ - scoped_lock lock(data->mutex); - if(data->message_in){ - data->cond_full.wait(lock); - } - if(i == (NumMsg-1)) - std::sprintf(data->items, "%s", "last message"); - else - std::sprintf(data->items, "%s_%d", "my_trace", i); - - //Notify to the other process that there is a message - data->cond_empty.notify_one(); - - //Mark message buffer as full - data->message_in = true; - } - } - catch(interprocess_exception &ex){ - std::cout << ex.what() << std::endl; - return 1; - } - - //Erase shared memory - shared_memory_object::remove("shared_memory"); - - return 0; - } diff --git a/doc/code/Attic/doc_anonymous_conditionB.cpp b/doc/code/Attic/doc_anonymous_conditionB.cpp deleted file mode 100644 index a943c67..0000000 --- a/doc/code/Attic/doc_anonymous_conditionB.cpp +++ /dev/null @@ -1,64 +0,0 @@ - #include - #include - #include - #include - #include - #include "doc_anonymous_condition_shared_data.hpp" - - using namespace boost::interprocess; - - int main () - { - try{ - //Erase previous shared memory - shared_memory_object::remove("shared_memory"); - - //Create a shared memory object. - shared_memory_object shm - (open_only //only create - ,"shared_memory" //name - ,read_write //read-write mode - ); - - //Map the whole shared memory in this process - mapped_region region - (shm //What to map - ,read_write //Map it as read-write - ); - - //Get the address of the mapped region - void * addr = region.get_address(); - - //Obtain a pointer to the shared structure - trace_queue * data = static_cast(addr); - - //Print messages until the other process marks the end - bool end_loop = false; - do{ - scoped_lock lock(data->mutex); - if(!data->message_in){ - data->cond_empty.wait(lock); - } - if(std::strcmp(data->items, "last message") == 0){ - end_loop = true; - } - else{ - //Print the message - std::cout << data->items << std::endl; - //Notify the other process that the buffer is empty - data->message_in = false; - data->cond_full.notify_one(); - } - } - while(!end_loop); - } - catch(interprocess_exception &ex){ - std::cout << ex.what() << std::endl; - return 1; - } - - //Erase shared memory - shared_memory_object::remove("shared_memory"); - - return 0; - } diff --git a/doc/code/Attic/doc_anonymous_condition_shared_data.hpp b/doc/code/Attic/doc_anonymous_condition_shared_data.hpp deleted file mode 100644 index d61934f..0000000 --- a/doc/code/Attic/doc_anonymous_condition_shared_data.hpp +++ /dev/null @@ -1,26 +0,0 @@ - #include - #include - - struct trace_queue - { - enum { LineSize = 100 }; - - trace_queue() - : message_in(false) - {} - - //Mutex to protect access to the queue - boost::interprocess::interprocess_mutex mutex; - - //Condition to wait when the queue is empty - boost::interprocess::interprocess_condition cond_empty; - - //Condition to wait when the queue is full - boost::interprocess::interprocess_condition cond_full; - - //Items to fill - char items[LineSize]; - - //Is there any message - bool message_in; - }; diff --git a/doc/code/Attic/doc_anonymous_mutexA.cpp b/doc/code/Attic/doc_anonymous_mutexA.cpp deleted file mode 100644 index 5cb33a9..0000000 --- a/doc/code/Attic/doc_anonymous_mutexA.cpp +++ /dev/null @@ -1,65 +0,0 @@ - #include - #include - #include - #include "doc_anonymous_mutex_shared_data.hpp" - #include - #include - - using namespace boost::interprocess; - - int main () - { - try{ - //Erase previous shared memory - shared_memory_object::remove("shared_memory"); - - //Create a shared memory object. - shared_memory_object shm - (create_only //only create - ,"shared_memory" //name - ,read_write //read-write mode - ); - - //Set size - shm.truncate(sizeof(shared_memory_log)); - - //Map the whole shared memory in this process - mapped_region region - (shm //What to map - ,read_write //Map it as read-write - ); - - //Get the address of the mapped region - void * addr = region.get_address(); - - //Construct the shared structure in memory - shared_memory_log * data = new (addr) shared_memory_log; - - //Write some logs - for(int i = 0; i < shared_memory_log::NumItems; ++i){ - //Lock the mutex - scoped_lock lock(data->mutex); - std::sprintf(data->items[(data->current_line++) % shared_memory_log::NumItems] - ,"%s_%d", "process_a", i); - if(i == (shared_memory_log::NumItems-1)) - data->end_a = true; - //Mutex is released here - } - - //Wait until the other process ends - while(1){ - scoped_lock lock(data->mutex); - if(data->end_b) - break; - } - } - catch(interprocess_exception &ex){ - std::cout << ex.what() << std::endl; - return 1; - } - - //Erase shared memory - shared_memory_object::remove("shared_memory"); - - return 0; - } diff --git a/doc/code/Attic/doc_anonymous_mutexB.cpp b/doc/code/Attic/doc_anonymous_mutexB.cpp deleted file mode 100644 index 8b5c150..0000000 --- a/doc/code/Attic/doc_anonymous_mutexB.cpp +++ /dev/null @@ -1,56 +0,0 @@ - #include - #include - #include - #include "doc_anonymous_mutex_shared_data.hpp" - #include - #include - - using namespace boost::interprocess; - - int main () - { - try{ - //Open the shared memory object. - shared_memory_object shm - (open_only //only create - ,"shared_memory" //name - ,read_write //read-write mode - ); - - //Map the whole shared memory in this process - mapped_region region - (shm //What to map - ,read_write //Map it as read-write - ); - - //Get the address of the mapped region - void * addr = region.get_address(); - - //Construct the shared structure in memory - shared_memory_log * data = static_cast(addr); - - //Write some logs - for(int i = 0; i < 100; ++i){ - //Lock the mutex - scoped_lock lock(data->mutex); - std::sprintf(data->items[(data->current_line++) % shared_memory_log::NumItems] - ,"%s_%d", "process_a", i); - if(i == (shared_memory_log::NumItems-1)) - data->end_b = true; - //Mutex is released here - } - - //Wait until the other process ends - while(1){ - scoped_lock lock(data->mutex); - if(data->end_a) - break; - } - } - catch(interprocess_exception &ex){ - std::cout << ex.what() << std::endl; - return 1; - } - - return 0; - } diff --git a/doc/code/Attic/doc_anonymous_mutex_shared_data.hpp b/doc/code/Attic/doc_anonymous_mutex_shared_data.hpp deleted file mode 100644 index 3bee481..0000000 --- a/doc/code/Attic/doc_anonymous_mutex_shared_data.hpp +++ /dev/null @@ -1,22 +0,0 @@ - #include - - struct shared_memory_log - { - enum { NumItems = 100 }; - enum { LineSize = 100 }; - - shared_memory_log() - : current_line(0) - , end_a(false) - , end_b(false) - {} - - //Mutex to protect access to the queue - boost::interprocess::interprocess_mutex mutex; - - //Items to fill - char items[NumItems][LineSize]; - int current_line; - bool end_a; - bool end_b; - }; diff --git a/doc/code/Attic/doc_anonymous_semaphoreA.cpp b/doc/code/Attic/doc_anonymous_semaphoreA.cpp deleted file mode 100644 index 5cc178b..0000000 --- a/doc/code/Attic/doc_anonymous_semaphoreA.cpp +++ /dev/null @@ -1,56 +0,0 @@ - #include - #include - #include - #include "doc_anonymous_semaphore_shared_data.hpp" - - using namespace boost::interprocess; - - int main () - { - try{ - //Erase previous shared memory - shared_memory_object::remove("shared_memory"); - - //Create a shared memory object. - shared_memory_object shm - (create_only //only create - ,"shared_memory" //name - ,read_write //read-write mode - ); - - //Set size - shm.truncate(sizeof(shared_memory_buffer)); - - //Map the whole shared memory in this process - mapped_region region - (shm //What to map - ,read_write //Map it as read-write - ); - - //Get the address of the mapped region - void * addr = region.get_address(); - - //Construct the shared structure in memory - shared_memory_buffer * data = new (addr) shared_memory_buffer; - - const int NumMsg = 100; - - //Insert data in the array - for(int i = 0; i < NumMsg; ++i){ - data->nempty.wait(); - data->mutex.wait(); - data->items[i % shared_memory_buffer::NumItems] = i; - data->mutex.post(); - data->nstored.post(); - } - } - catch(interprocess_exception &ex){ - std::cout << ex.what() << std::endl; - return 1; - } - - //Erase shared memory - shared_memory_object::remove("shared_memory"); - - return 0; - } diff --git a/doc/code/Attic/doc_anonymous_semaphoreB.cpp b/doc/code/Attic/doc_anonymous_semaphoreB.cpp deleted file mode 100644 index e53e238..0000000 --- a/doc/code/Attic/doc_anonymous_semaphoreB.cpp +++ /dev/null @@ -1,52 +0,0 @@ - #include - #include - #include - #include "doc_anonymous_semaphore_shared_data.hpp" - - using namespace boost::interprocess; - - int main () - { - try{ - //Create a shared memory object. - shared_memory_object shm - (open_only //only create - ,"shared_memory" //name - ,read_write //read-write mode - ); - - //Map the whole shared memory in this process - mapped_region region - (shm //What to map - ,read_write //Map it as read-write - ); - - //Get the address of the mapped region - void * addr = region.get_address(); - - //Obtain the shared structure - shared_memory_buffer * data = static_cast(addr); - - const int NumMsg = 100; - - int extracted_data [NumMsg]; - - //Extract the data - for(int i = 0; i < NumMsg; ++i){ - data->nstored.wait(); - data->mutex.wait(); - extracted_data[i] = data->items[i % shared_memory_buffer::NumItems]; - data->mutex.post(); - data->nempty.post(); - } - } - catch(interprocess_exception &ex){ - std::cout << ex.what() << std::endl; - return 1; - } - - //Erase shared memory - shared_memory_object::remove("shared_memory"); - - return 0; - } diff --git a/doc/code/Attic/doc_anonymous_semaphore_shared_data.hpp b/doc/code/Attic/doc_anonymous_semaphore_shared_data.hpp deleted file mode 100644 index e1fcd3b..0000000 --- a/doc/code/Attic/doc_anonymous_semaphore_shared_data.hpp +++ /dev/null @@ -1,17 +0,0 @@ - #include - - struct shared_memory_buffer - { - enum { NumItems = 10 }; - - shared_memory_buffer() - : mutex(1), nempty(NumItems), nstored(0) - {} - - //Semaphores to protect and synchronize access - boost::interprocess::interprocess_semaphore - mutex, nempty, nstored; - - //Items to fill - int items[NumItems]; - }; diff --git a/doc/code/Attic/doc_anonymous_upgradable_mutexA.cpp b/doc/code/Attic/doc_anonymous_upgradable_mutexA.cpp deleted file mode 100644 index 57df06d..0000000 --- a/doc/code/Attic/doc_anonymous_upgradable_mutexA.cpp +++ /dev/null @@ -1,65 +0,0 @@ - #include - #include - #include - #include "doc_upgradable_mutex_shared_data.hpp" - #include - #include - - using namespace boost::interprocess; - - int main () - { - try{ - //Erase previous shared memory - shared_memory_object::remove("shared_memory"); - - //Create a shared memory object. - shared_memory_object shm - (create_only //only create - ,"shared_memory" //name - ,read_write //read-write mode - ); - - //Set size - shm.truncate(sizeof(shared_data)); - - //Map the whole shared memory in this process - mapped_region region - (shm //What to map - ,read_write //Map it as read-write - ); - - //Get the address of the mapped region - void * addr = region.get_address(); - - //Construct the shared structure in memory - shared_data * data = new (addr) shared_data; - - //Write some logs - for(int i = 0; i < shared_data::NumItems; ++i){ - //Lock the upgradable_mutex - scoped_lock lock(data->upgradable_mutex); - std::sprintf(data->items[(data->current_line++) % shared_data::NumItems] - ,"%s_%d", "process_a", i); - if(i == (shared_data::NumItems-1)) - data->end_a = true; - //Mutex is released here - } - - //Wait until the other process ends - while(1){ - scoped_lock lock(data->upgradable_mutex); - if(data->end_b) - break; - } - } - catch(interprocess_exception &ex){ - std::cout << ex.what() << std::endl; - return 1; - } - - //Erase shared memory - shared_memory_object::remove("shared_memory"); - - return 0; - } diff --git a/doc/code/Attic/doc_anonymous_upgradable_mutexB.cpp b/doc/code/Attic/doc_anonymous_upgradable_mutexB.cpp deleted file mode 100644 index 7eb945c..0000000 --- a/doc/code/Attic/doc_anonymous_upgradable_mutexB.cpp +++ /dev/null @@ -1,56 +0,0 @@ - #include - #include - #include - #include "doc_upgradable_mutex_shared_data.hpp" - #include - #include - - using namespace boost::interprocess; - - int main () - { - try{ - //Open the shared memory object. - shared_memory_object shm - (open_only //only create - ,"shared_memory" //name - ,read_write //read-write mode - ); - - //Map the whole shared memory in this process - mapped_region region - (shm //What to map - ,read_write //Map it as read-write - ); - - //Get the address of the mapped region - void * addr = region.get_address(); - - //Construct the shared structure in memory - shared_data * data = static_cast(addr); - - //Write some logs - for(int i = 0; i < 100; ++i){ - //Lock the upgradable_mutex - scoped_lock lock(data->upgradable_mutex); - std::sprintf(data->items[(data->current_line++) % shared_data::NumItems] - ,"%s_%d", "process_a", i); - if(i == (shared_data::NumItems-1)) - data->end_b = true; - //Mutex is released here - } - - //Wait until the other process ends - while(1){ - scoped_lock lock(data->upgradable_mutex); - if(data->end_a) - break; - } - } - catch(interprocess_exception &ex){ - std::cout << ex.what() << std::endl; - return 1; - } - - return 0; - } diff --git a/doc/code/Attic/doc_intrusive.cpp b/doc/code/Attic/doc_intrusive.cpp deleted file mode 100644 index 6ee2902..0000000 --- a/doc/code/Attic/doc_intrusive.cpp +++ /dev/null @@ -1,89 +0,0 @@ - #include - #include - - #include - #include - - using namespace boost::interprocess; - - namespace N { - - //A class that has an internal reference count - class reference_counted_class - { - private: - //Non-copyable - reference_counted_class(const reference_counted_class &); - //Non-assignable - reference_counted_class & operator=(const reference_counted_class &); - //A typedef to save typing - typedef managed_shared_memory::segment_manager segment_manager; - //This is the reference count - unsigned int m_use_count; - //The segment manager allows deletion from shared memory segment - offset_ptr mp_segment_manager; - - public: - //Constructor - reference_counted_class(segment_manager *s_mngr) - : m_use_count(0), mp_segment_manager(s_mngr){} - //Destructor - ~reference_counted_class(){} - - public: - //Returns the reference count - unsigned int use_count() const - { return m_use_count; } - //Adds a reference - inline friend void intrusive_ptr_add_ref(reference_counted_class * p) - { ++p->m_use_count; } - //Releases a reference - inline friend void intrusive_ptr_release(reference_counted_class * p) - { if(--p->m_use_count == 0) p->mp_segment_manager->destroy_ptr(p); } - }; - - } //namespace N { - - //A class that has an intrusive pointer to reference_counted_class - class intrusive_ptr_owner - { - typedef intrusive_ptr > intrusive_ptr_t; - intrusive_ptr_t m_intrusive_ptr; - - public: - //Takes a pointer to the reference counted class - intrusive_ptr_owner(N::reference_counted_class *ptr) - : m_intrusive_ptr(ptr){} - }; - - int main () - { - shared_memory_object::remove("my_shmem"); - //Create shared memory - managed_shared_memory shmem(create_only, "my_shmem", 10000); - //Create the unique reference counted object in shared memory - N::reference_counted_class *ref_counted = - shmem.construct - ("ref_counted")(shmem.get_segment_manager()); - //Create an array of ten intrusive pointer owners in shared memory - intrusive_ptr_owner *intrusive_owner_array = - shmem.construct - (anonymous_instance)[10](ref_counted); - //Now test that reference count is ten - if(ref_counted->use_count() != 10) - return 1; - - //Now destroy the array of intrusive pointer owners - //This should destroy every intrusive_ptr and because of - //that reference_counted_class will be destroyed - shmem.destroy_ptr(intrusive_owner_array); - - //Now the reference counted object should have been destroyed - if(shmem.find("ref_counted").first) - return 1; - //Success! - return 0; - } - - #include diff --git a/doc/code/Attic/doc_ipc_messageA.cpp b/doc/code/Attic/doc_ipc_messageA.cpp deleted file mode 100644 index 6e9dc8a..0000000 --- a/doc/code/Attic/doc_ipc_messageA.cpp +++ /dev/null @@ -1,39 +0,0 @@ - #include - #include - - #include - - int main () - { - using namespace boost::interprocess; - - //An special shared memory from which we are - //able to allocate raw memory buffers. - //First remove any old shared memory of the same name, create - //the shared memory segment and initialize needed resources - shared_memory_object::remove("MySharedMemory"); - managed_shared_memory segment - (create_only, - "MySharedMemory", //segment name - 65536); //segment size in bytes - - //Allocate a portion of the segment - void * shptr = segment.allocate(1024/*bytes to allocate*/); - - //An handle from the base address can identify any byte of the shared - //memory segment even if it is mapped in different base addresses - managed_shared_memory::handle_t handle = segment.get_handle_from_address(shptr); - (void)handle; - // Copy message to buffer - // . . . - // Send handle to other process - // . . . - // Wait response from other process - // . . . - - //Deallocate the portion previously allocated - segment.deallocate(shptr); - return 0; - } - - #include diff --git a/doc/code/Attic/doc_ipc_messageB.cpp b/doc/code/Attic/doc_ipc_messageB.cpp deleted file mode 100644 index 7ab3d13..0000000 --- a/doc/code/Attic/doc_ipc_messageB.cpp +++ /dev/null @@ -1,31 +0,0 @@ - #include - #include - - #include - - int main () - { - using namespace boost::interprocess; - - //An special shared memory from which we are - //able to allocate raw memory buffers. - //Connect to the already created shared memory segment - //and initialize needed resources - managed_shared_memory segment(open_only, "MySharedMemory"); //segment name - - //An handle from the base address can identify any byte of the shared - //memory segment even if it is mapped in different base addresses - managed_shared_memory::handle_t handle = 0; - - //Wait handle msg from the other process and put it in - //"handle" local variable - //Get buffer local address from handle - void *msg = segment.get_address_from_handle(handle); - (void)msg; - //Do anything with msg - //. . . - //Send ack to sender process - return 0; - } - - #include diff --git a/doc/code/Attic/doc_managed_heap_memory.cpp b/doc/code/Attic/doc_managed_heap_memory.cpp deleted file mode 100644 index 0d9ebeb..0000000 --- a/doc/code/Attic/doc_managed_heap_memory.cpp +++ /dev/null @@ -1,66 +0,0 @@ - #include - #include - - #include - #include - #include - #include - - using namespace boost::interprocess; - typedef list > - MyList; - - int main () - { - //We will create a buffer of 1000 bytes to store a list - managed_heap_memory heap_memory(1000); - - MyList * mylist = heap_memory.construct("MyList") - (heap_memory.get_segment_manager()); - - //Obtain handle, that identifies the list in the buffer - managed_heap_memory::handle_t list_handle = heap_memory.get_handle_from_address(mylist); - - //Fill list until there is no more memory in the buffer - try{ - while(1) { - mylist->insert(mylist->begin(), 0); - } - } - catch(const bad_alloc &){ - //memory is full - } - //Let's obtain the size of the list - std::size_t old_size = mylist->size(); - - //To make the list bigger, let's increase the heap buffer - //in 1000 bytes more. - heap_memory.grow(1000); - - //If memory has been reallocated, the old pointer is invalid, so - //use previously obtained handle to find the new pointer. - mylist = static_cast - (heap_memory.get_address_from_handle(list_handle)); - - //Fill list until there is no more memory in the buffer - try{ - while(1) { - mylist->insert(mylist->begin(), 0); - } - } - catch(const bad_alloc &){ - //memory is full - } - - //Let's obtain the new size of the list - std::size_t new_size = mylist->size(); - - assert(new_size > old_size); - - //Destroy list - heap_memory.destroy_ptr(mylist); - - return 0; - } - - #include diff --git a/doc/code/Attic/doc_message_queueA.cpp b/doc/code/Attic/doc_message_queueA.cpp deleted file mode 100644 index 1e4c30e..0000000 --- a/doc/code/Attic/doc_message_queueA.cpp +++ /dev/null @@ -1,32 +0,0 @@ - #include - #include - #include - - using namespace boost::interprocess; - - int main () - { - try{ - //Erase previous message queue - message_queue::remove("message_queue"); - - //Create a message_queue. - message_queue mq - (create_only //only create - ,"message_queue" //name - ,100 //max message number - ,sizeof(int) //max message size - ); - - //Send 100 numbers - for(int i = 0; i < 100; ++i){ - mq.send(&i, sizeof(i), 0); - } - } - catch(interprocess_exception &ex){ - std::cout << ex.what() << std::endl; - return 1; - } - - return 0; - } diff --git a/doc/code/Attic/doc_message_queueB.cpp b/doc/code/Attic/doc_message_queueB.cpp deleted file mode 100644 index 989f341..0000000 --- a/doc/code/Attic/doc_message_queueB.cpp +++ /dev/null @@ -1,33 +0,0 @@ - #include - #include - #include - - using namespace boost::interprocess; - - int main () - { - try{ - //Open a message queue. - message_queue mq - (open_only //only create - ,"message_queue" //name - ); - - unsigned int priority; - unsigned int recvd_size; - - //Receive 100 numbers - for(int i = 0; i < 100; ++i){ - int number; - mq.receive(&number, sizeof(number), recvd_size, priority); - if(number != i || recvd_size != sizeof(number)) - return 1; - } - } - catch(interprocess_exception &ex){ - std::cout << ex.what() << std::endl; - return 1; - } - - return 0; - } diff --git a/doc/code/Attic/doc_named_allocA.cpp b/doc/code/Attic/doc_named_allocA.cpp deleted file mode 100644 index 309c65d..0000000 --- a/doc/code/Attic/doc_named_allocA.cpp +++ /dev/null @@ -1,37 +0,0 @@ - #include - #include - - #include - #include - - int main () - { - using namespace boost::interprocess; - typedef std::pair MyType; - - //An special shared memory where we can - //construct objects associated with a name. - //First remove any old shared memory of the same name, create - //the shared memory segment and initialize needed resources - shared_memory_object::remove("MySharedMemory"); - managed_shared_memory segment( - create_only, - "MySharedMemory", //segment name - 65536); //segment size in bytes - - //Create an object of MyType initialized to {0.0, 0} - MyType *instance = segment.construct - ("MyType instance") /*name of the object*/ - (0.0 /*ctor first argument*/, - 0 /*ctor second argument*/); - - //Create an array of 10 elements of MyType initialized to {0.0, 0} - MyType *array = segment.construct - ("MyType array") /*name of the object*/ - [10] /*number of elements*/ - (0.0 /*ctor first argument*/, - 0 /*ctor second argument*/); - return 0; - } - - #include diff --git a/doc/code/Attic/doc_named_allocB.cpp b/doc/code/Attic/doc_named_allocB.cpp deleted file mode 100644 index f063dbc..0000000 --- a/doc/code/Attic/doc_named_allocB.cpp +++ /dev/null @@ -1,49 +0,0 @@ - #include - #include - - #include - #include - #include - #include - - int main () - { - using namespace boost::interprocess; - typedef std::pair MyType; - - //An special shared memory where we can - //construct objects associated with a name. - //Connect to the already created shared memory segment - //and initialize needed resources - managed_shared_memory segment( - open_only, - "MySharedMemory"); - - //Find the array and object - std::pair res; - res = segment.find ("MyType array"); - - std::size_t array_len = res.second; - //Length should be 10 - assert(array_len == 10); - - //Find the array and the object - res = segment.find ("MyType instance"); - - std::size_t len = res.second; - - //Length should be 1 - assert(len == 1); - - //Use data - // . . . - - //We're done, delete array from memory - segment.destroy("MyType array"); - - //We're done, delete object from memory - segment.destroy("MyType instance"); - return 0; - } - - #include diff --git a/doc/code/Attic/doc_named_conditionA.cpp b/doc/code/Attic/doc_named_conditionA.cpp deleted file mode 100644 index aba35bb..0000000 --- a/doc/code/Attic/doc_named_conditionA.cpp +++ /dev/null @@ -1,66 +0,0 @@ - #include - #include - #include - #include - #include - #include "doc_anonymous_condition_shared_data.hpp" - - using namespace boost::interprocess; - - int main () - { - try{ - //Erase previous shared memory - shared_memory_object::remove("shared_memory"); - - //Create a shared memory object. - shared_memory_object shm - (create_only //only create - ,"shared_memory" //name - ,read_write //read-write mode - ); - - //Set size - shm.truncate(sizeof(trace_queue)); - - //Map the whole shared memory in this process - mapped_region region - (shm //What to map - ,read_write //Map it as read-write - ); - - //Get the address of the mapped region - void * addr = region.get_address(); - - //Construct the shared structure in memory - trace_queue * data = new (addr) trace_queue; - - const int NumMsg = 100; - - for(int i = 0; i < NumMsg; ++i){ - scoped_lock lock(data->mutex); - if(data->message_in){ - data->cond_full.wait(lock); - } - if(i == (NumMsg-1)) - std::sprintf(data->items, "%s", "last message"); - else - std::sprintf(data->items, "%s_%d", "my_trace", i); - - //Notify to the other process that there is a message - data->cond_empty.notify_one(); - - //Mark message buffer as full - data->message_in = true; - } - } - catch(interprocess_exception &ex){ - std::cout << ex.what() << std::endl; - return 1; - } - - //Erase shared memory - shared_memory_object::remove("shared_memory"); - - return 0; - } diff --git a/doc/code/Attic/doc_named_conditionB.cpp b/doc/code/Attic/doc_named_conditionB.cpp deleted file mode 100644 index a943c67..0000000 --- a/doc/code/Attic/doc_named_conditionB.cpp +++ /dev/null @@ -1,64 +0,0 @@ - #include - #include - #include - #include - #include - #include "doc_anonymous_condition_shared_data.hpp" - - using namespace boost::interprocess; - - int main () - { - try{ - //Erase previous shared memory - shared_memory_object::remove("shared_memory"); - - //Create a shared memory object. - shared_memory_object shm - (open_only //only create - ,"shared_memory" //name - ,read_write //read-write mode - ); - - //Map the whole shared memory in this process - mapped_region region - (shm //What to map - ,read_write //Map it as read-write - ); - - //Get the address of the mapped region - void * addr = region.get_address(); - - //Obtain a pointer to the shared structure - trace_queue * data = static_cast(addr); - - //Print messages until the other process marks the end - bool end_loop = false; - do{ - scoped_lock lock(data->mutex); - if(!data->message_in){ - data->cond_empty.wait(lock); - } - if(std::strcmp(data->items, "last message") == 0){ - end_loop = true; - } - else{ - //Print the message - std::cout << data->items << std::endl; - //Notify the other process that the buffer is empty - data->message_in = false; - data->cond_full.notify_one(); - } - } - while(!end_loop); - } - catch(interprocess_exception &ex){ - std::cout << ex.what() << std::endl; - return 1; - } - - //Erase shared memory - shared_memory_object::remove("shared_memory"); - - return 0; - } diff --git a/doc/code/Attic/doc_named_mutex.cpp b/doc/code/Attic/doc_named_mutex.cpp deleted file mode 100644 index 999088d..0000000 --- a/doc/code/Attic/doc_named_mutex.cpp +++ /dev/null @@ -1,32 +0,0 @@ - #include - #include - #include - - int main () - { - using namespace boost::interprocess; - try{ - - //Open or create the named mutex - named_mutex mutex(open_or_create, "cout_named_mutex"); - - std::ofstream file("file_name"); - - for(int i = 0; i < 10; ++i){ - - //Do some operations... - - //Write to file atomically - scoped_lock lock(mutex); - file << "Process name, "; - file << "This is iteration #" << i; - file << std::endl; - } - } - catch(interprocess_exception &ex){ - std::cout << ex.what() << std::endl; - return 1; - } - - return 0; - } diff --git a/doc/code/Attic/doc_offset_ptr.cpp b/doc/code/Attic/doc_offset_ptr.cpp deleted file mode 100644 index a548d75..0000000 --- a/doc/code/Attic/doc_offset_ptr.cpp +++ /dev/null @@ -1,53 +0,0 @@ - #include - #include - - #include - #include - - using namespace boost::interprocess; - - //Shared memory linked list node - struct list_node - { - offset_ptr next; - int value; - }; - - int main () - { - //Destroy any previous shared memory with the name to be used. - //Create an special shared memory from which we can - //allocate buffers of raw memory. - shared_memory_object::remove("MySharedMemory"); - managed_shared_memory segment( - create_only, - "MySharedMemory",//segment name - 65536); //segment size in bytes - - //Create linked list with 10 nodes in shared memory - offset_ptr prev = 0, current, first; - - int i; - for(i = 0; i < 10; ++i, prev = current){ - current = static_cast(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; - } - - #include diff --git a/doc/code/Attic/doc_shared_memory.cpp b/doc/code/Attic/doc_shared_memory.cpp deleted file mode 100644 index a830dbf..0000000 --- a/doc/code/Attic/doc_shared_memory.cpp +++ /dev/null @@ -1,43 +0,0 @@ - #include - #include - #include - #include - - int main () - { - using namespace boost::interprocess; - try{ - //Erase previous shared memory - shared_memory_object::remove("shared_memory"); - - //Create a shared memory object. - shared_memory_object shm - (create_only //only create - ,"shared_memory" //name - ,read_write //read-write mode - ); - - //Set size - shm.truncate(1000); - - //Map the whole shared memory in this process - mapped_region region - (shm //What to map - ,read_write //Map it as read-write - ); - - //Get the address of the mapped region - void * addr = region.get_address(); - std::size_t size = region.get_size(); - - //Write all the memory to 1 - std::memset(addr, 1, size); - - } - catch(interprocess_exception &ex){ - std::cout << ex.what() << std::endl; - return 1; - } - - return 0; - } diff --git a/doc/code/Attic/doc_shared_memory2.cpp b/doc/code/Attic/doc_shared_memory2.cpp deleted file mode 100644 index f997cc3..0000000 --- a/doc/code/Attic/doc_shared_memory2.cpp +++ /dev/null @@ -1,44 +0,0 @@ - #include - #include - #include - #include - - int main () - { - using namespace boost::interprocess; - try{ - //Open already created shared memory object. - shared_memory_object shm - (open_only //only create - ,"shared_memory" //name - ,read_only //read-write mode - ); - - //Map the whole shared memory in this process - mapped_region region - (shm //What to map - ,read_only //Map it as read-write - ); - - //Get the address of the mapped region - void * addr = region.get_address(); - std::size_t size = region.get_size(); - - //Check that memory was initialized to 1 - const char *mem = static_cast(addr); - for(std::size_t i = 0; i < size; ++i){ - if(*mem++ != 1){ - std::cout << "Error checking memory!" << std::endl; - return 1; - } - } - - std::cout << "Test successful!" << std::endl; - } - catch(interprocess_exception &ex){ - std::cout << "Unexpected exception: " << ex.what() << std::endl; - return 1; - } - - return 0; - } diff --git a/doc/html/boostbook.css b/doc/html/boostbook.css index d84d538..e816cce 100644 --- a/doc/html/boostbook.css +++ b/doc/html/boostbook.css @@ -35,12 +35,12 @@ /* Code on paragraphs */ p tt.computeroutput { - font-size: 9pt; + font-size: 10pt; } pre.synopsis { - font-size: 90%; + font-size: 10pt; margin: 1pc 4% 0pc 4%; padding: 0.5pc 0.5pc 0.5pc 0.5pc; } @@ -48,27 +48,19 @@ .programlisting, .screen { - font-size: 9pt; + font-size: 10pt; display: block; margin: 1pc 4% 0pc 4%; padding: 0.5pc 0.5pc 0.5pc 0.5pc; } - /* Program listings in tables don't get borders */ - td .programlisting, - td .screen - { - margin: 0pc 0pc 0pc 0pc; - padding: 0pc 0pc 0pc 0pc; - } - /*============================================================================= Headings =============================================================================*/ h1, h2, h3, h4, h5, h6 { - text-align: left; + text-align: left; margin: 1em 0em 0.5em 0em; font-weight: bold; } @@ -139,13 +131,13 @@ font-size: 10pt; line-height: 1.3; } - + /* Unordered lists */ ul { text-align: left; } - + /* Ordered lists */ ol { @@ -160,7 +152,7 @@ { text-decoration: none; /* no underline */ } - + a:hover { text-decoration: underline; @@ -174,13 +166,13 @@ { text-align: right; } - + .spirit-nav a { color: white; padding-left: 0.5em; } - + .spirit-nav img { border-width: 0px; @@ -194,10 +186,19 @@ { margin: 1pc 4% 0pc 4%; padding: 0.1pc 1pc 0.1pc 1pc; - font-size: 80%; + font-size: 10pt; line-height: 1.15; } - + + .toc-main + { + width: 600; + text-align: center; + margin: 1pc 1pc 1pc 10%; + padding: 2pc 1pc 3pc 1pc; + line-height: 0.1; + } + .boost-toc { float: right; @@ -215,7 +216,7 @@ padding-right: 0.5em; padding-left: 0.5em; } - + .informaltable table, .table table { @@ -223,20 +224,19 @@ margin-left: 4%; margin-right: 4%; } - + div.informaltable table, div.table table { padding: 4px; } - + /* Table Cells */ div.informaltable table tr td, div.table table tr td { padding: 0.5em; text-align: left; - font-size: 9pt; } div.informaltable table tr th, @@ -244,7 +244,7 @@ { padding: 0.5em 0.5em 0.5em 0.5em; border: 1pt solid white; - font-size: 80%; + font-size: 120%; } /*============================================================================= @@ -258,13 +258,13 @@ div.warning, p.blurb { - font-size: 9pt; /* A little bit smaller than the main text */ + font-size: 10pt; line-height: 1.2; display: block; margin: 1pc 4% 0pc 4%; padding: 0.5pc 0.5pc 0.5pc 0.5pc; } - + p.blurb img { padding: 1pt; @@ -274,8 +274,6 @@ Variable Lists =============================================================================*/ - /* Make the terms in definition lists bold */ - div.variablelist dl dt, span.term { font-weight: bold; @@ -288,28 +286,26 @@ vertical-align: top; padding: 0em 2em 0em 0em; font-size: 10pt; - margin: 0em 0em 0.5em 0em; - line-height: 1; } + div.variablelist table tbody tr td p + { + margin: 0em 0em 0.5em 0em; + } + + /* Make the terms in definition lists bold */ div.variablelist dl dt { - margin-bottom: 0.2em; + font-weight: bold; + font-size: 10pt; } div.variablelist dl dd { - margin: 0em 0em 0.5em 2em; + margin: 1em 0em 1em 2em; font-size: 10pt; } - div.variablelist table tbody tr td p, - div.variablelist dl dd p - { - margin: 0em 0em 0.5em 0em; - line-height: 1; - } - /*============================================================================= Misc =============================================================================*/ @@ -333,6 +329,7 @@ /* Copyright, Legal Notice */ div div.legalnotice p { + font-size: 8pt; text-align: left } @@ -342,15 +339,15 @@ @media screen { - /* Links */ + /* Links */ a { - color: #005a9c; + color: #0C7445; } - + a:visited { - color: #9c5a9c; + color: #663974; } h1 a, h2 a, h3 a, h4 a, h5 a, h6 a, @@ -360,8 +357,8 @@ text-decoration: none; /* no underline */ color: #000000; } - - /* Syntax Highlighting */ + + /* Syntax Highlighting */ .keyword { color: #0000AA; } .identifier { color: #000000; } .special { color: #707070; } @@ -370,40 +367,40 @@ .comment { color: #800000; } .string { color: teal; } .number { color: teal; } - .white_bkd { background-color: #FFFFFF; } - .dk_grey_bkd { background-color: #999999; } - - /* Copyright, Legal Notice */ - .copyright + .white_bkd { background-color: #E8FBE9; } + .dk_grey_bkd { background-color: #A0DAAC; } + + /* Copyright, Legal Notice */ + .copyright { color: #666666; font-size: small; } - + div div.legalnotice p { color: #666666; } - - /* Program listing */ + + /* Program listing */ pre.synopsis { border: 1px solid #DCDCDC; + border-bottom: 3px solid #9D9D9D; + border-right: 3px solid #9D9D9D; + background-color: #FAFFFB; } - + .programlisting, .screen { border: 1px solid #DCDCDC; + border-bottom: 3px solid #9D9D9D; + border-right: 3px solid #9D9D9D; + background-color: #FAFFFB; } - - td .programlisting, - td .screen - { - border: 0px solid #DCDCDC; - } - - /* Blurbs */ + + /* Blurbs */ div.note, div.tip, div.important, @@ -412,98 +409,128 @@ p.blurb { border: 1px solid #DCDCDC; + border-bottom: 3px solid #9D9D9D; + border-right: 3px solid #9D9D9D; + background-color: #FAFFFB; } - - /* Table of contents */ + + /* Table of contents */ .toc { border: 1px solid #DCDCDC; + border-bottom: 3px solid #9D9D9D; + border-right: 3px solid #9D9D9D; + background-color: #FAFFFB; } - - /* Tables */ + + /* Table of contents */ + .toc-main + { + border: 1px solid #DCDCDC; + border-bottom: 3px solid #9D9D9D; + border-right: 3px solid #9D9D9D; + background-color: #FAFFFB; + } + + + /* Tables */ div.informaltable table tr td, div.table table tr td { border: 1px solid #DCDCDC; + background-color: #FAFFFB; } - + div.informaltable table tr th, div.table table tr th { - background-color: #F0F0F0; + background-color: #E3F9E4; border: 1px solid #DCDCDC; } - - /* Misc */ + + /* Misc */ span.highlight { color: #00A000; } } - + @media print { - /* Links */ + /* Links */ a { color: black; } - + a:visited { color: black; } - + .spirit-nav { display: none; } - - /* Program listing */ + + /* Program listing */ pre.synopsis { border: 1px solid gray; + background-color: #FAFFFB; } - + .programlisting, .screen { border: 1px solid gray; + background-color: #FAFFFB; } - - td .programlisting, - td .screen - { - border: 0px solid #DCDCDC; - } - - /* Table of contents */ + + /* Table of contents */ .toc { - border: 1px solid gray; + border: 1px solid #DCDCDC; + border-bottom: 3px solid #9D9D9D; + border-right: 3px solid #9D9D9D; + background-color: #FAFFFB; } - + + /* Table of contents */ + .toc-main + { + border: 1px solid #DCDCDC; + border-bottom: 3px solid #9D9D9D; + border-right: 3px solid #9D9D9D; + background-color: #FAFFFB; + } + .informaltable table, .table table { - border: 1px solid gray; + border: 1px solid #DCDCDC; + border-bottom: 3px solid #9D9D9D; + border-right: 3px solid #9D9D9D; border-collapse: collapse; + background-color: #FAFFFB; } - - /* Tables */ + + /* Tables */ div.informaltable table tr td, div.table table tr td { - border: 1px solid gray; + border: 1px solid #DCDCDC; + background-color: #FAFFFB; } - + div.informaltable table tr th, div.table table tr th { - border: 1px solid gray; + border: 1px solid #DCDCDC; + background-color: #FAFFFB; } - - /* Misc */ + + /* Misc */ span.highlight { font-weight: bold; diff --git a/doc/interprocess.qbk b/doc/interprocess.qbk index 4c95d91..8e89142 100644 --- a/doc/interprocess.qbk +++ b/doc/interprocess.qbk @@ -1,8 +1,8 @@ [library Interprocess [quickbook 1.4] - [version 2006-10-13] + [version 2007-05-03] [authors [Gaztañaga, Ion]] - [copyright 2005- 2006 Ion Gaztañaga] + [copyright 2005- 2007 Ion Gaztañaga] [purpose Interprocess communication utilities] [license Distributed under the Boost Software License, Version 1.0. @@ -47,79 +47,14 @@ STL-like containers, in shared memory and memory mapped files: You can just allocate a portion of a shared memory segment, copy the message to that buffer, send the offset of that portion of shared memory to another process, and you are done. Let's see the example: - -[/ doc_ipc_messageA.cpp] - -[c++] - - #include - - int main () - { - using namespace boost::interprocess; - - //An special shared memory from which we are - //able to allocate raw memory buffers. - //First remove any old shared memory of the same name, create - //the shared memory segment and initialize needed resources - shared_memory_object::remove("MySharedMemory"); - managed_shared_memory segment - (create_only, - "MySharedMemory", //segment name - 65536); //segment size in bytes - - //Allocate a portion of the segment - void * shptr = segment.allocate(1024/*bytes to allocate*/); - - //An handle from the base address can identify any byte of the shared - //memory segment even if it is mapped in different base addresses - managed_shared_memory::handle_t handle = segment.get_handle_from_address(shptr); - (void)handle; - // Copy message to buffer - // . . . - // Send handle to other process - // . . . - // Wait response from other process - // . . . - - //Deallocate the portion previously allocated - segment.deallocate(shptr); - return 0; - } +[import ../example/doc_ipc_messageA.cpp] +[doc_ipc_messageA] In receiver process one just could write the following lines: -[/ doc_ipc_messageB.cpp] - -[c++] - - #include - - int main () - { - using namespace boost::interprocess; - - //An special shared memory from which we are - //able to allocate raw memory buffers. - //Connect to the already created shared memory segment - //and initialize needed resources - managed_shared_memory segment(open_only, "MySharedMemory"); //segment name - - //An handle from the base address can identify any byte of the shared - //memory segment even if it is mapped in different base addresses - managed_shared_memory::handle_t handle = 0; - - //Wait handle msg from the other process and put it in - //"handle" local variable - //Get buffer local address from handle - void *msg = segment.get_address_from_handle(handle); - (void)msg; - //Do anything with msg - //. . . - //Send ack to sender process - return 0; - } +[import ../example/doc_ipc_messageB.cpp] +[doc_ipc_messageB] [endsect] @@ -129,97 +64,19 @@ You want to create objects in a shared memory segment, giving a string name to t any other process can find, use and delete them from the segment when the objects are not needed anymore. Just write in one process: -[/ doc_named_allocA.cpp ] -[c++] +[import ../example/doc_named_allocA.cpp] +[doc_named_allocA] - #include - #include +In other process execute the following: - int main () - { - using namespace boost::interprocess; - typedef std::pair MyType; - - //An special shared memory where we can - //construct objects associated with a name. - //First remove any old shared memory of the same name, create - //the shared memory segment and initialize needed resources - shared_memory_object::remove("MySharedMemory"); - managed_shared_memory segment( - create_only, - "MySharedMemory", //segment name - 65536); //segment size in bytes - - //Create an object of MyType initialized to {0.0, 0} - MyType *instance = segment.construct - ("MyType instance") /*name of the object*/ - (0.0 /*ctor first argument*/, - 0 /*ctor second argument*/); - - //Create an array of 10 elements of MyType initialized to {0.0, 0} - MyType *array = segment.construct - ("MyType array") /*name of the object*/ - [10] /*number of elements*/ - (0.0 /*ctor first argument*/, - 0 /*ctor second argument*/); - return 0; - } - -In other process, while the first process is alive, execute the following: - -[/ doc_named_allocB.cpp ] -[c++] - - #include - #include - #include - #include - - int main () - { - using namespace boost::interprocess; - typedef std::pair MyType; - - //An special shared memory where we can - //construct objects associated with a name. - //Connect to the already created shared memory segment - //and initialize needed resources - managed_shared_memory segment( - open_only, - "MySharedMemory"); - - //Find the array and object - std::pair res; - res = segment.find ("MyType array"); - - std::size_t array_len = res.second; - //Length should be 10 - assert(array_len == 10); - - //Find the array and the object - res = segment.find ("MyType instance"); - - std::size_t len = res.second; - - //Length should be 1 - assert(len == 1); - - //Use data - // . . . - - //We're done, delete array from memory - segment.destroy("MyType array"); - - //We're done, delete object from memory - segment.destroy("MyType instance"); - return 0; - } +[import ../example/doc_named_allocB.cpp] +[doc_named_allocB] [endsect] [section:qg_offset_ptr Using an offset smart pointer for shared memory] -Interprocess offers offset_ptr smart pointer family +[*Boost.Interprocess] offers offset_ptr smart pointer family as an offset pointer that stores the distance between the address of the offset pointer itself and the address of the pointed object. When offset_ptr is placed in a shared memory segment, it @@ -231,57 +88,8 @@ This allows placing objects with pointer members in shared memory. For example, if we want to create a linked list in shared memory: -[/ doc_offset_ptr.cpp] -[c++] - - #include - #include - - using namespace boost::interprocess; - - //Shared memory linked list node - struct list_node - { - offset_ptr next; - int value; - }; - - int main () - { - //Destroy any previous shared memory with the name to be used. - //Create an special shared memory from which we can - //allocate buffers of raw memory. - shared_memory_object::remove("MySharedMemory"); - managed_shared_memory segment( - create_only, - "MySharedMemory",//segment name - 65536); //segment size in bytes - - //Create linked list with 10 nodes in shared memory - offset_ptr prev = 0, current, first; - - int i; - for(i = 0; i < 10; ++i, prev = current){ - current = static_cast(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; - } +[import ../example/doc_offset_ptr.cpp] +[doc_offset_ptr] To help with basic data structures, [*Boost.Interprocess] offers containers like vector, list, map, so you can avoid these manual data structures just like with standard containers. @@ -296,95 +104,30 @@ To do this, we just need to create a an special (managed) shared memory segment, declare a [*Boost.Interprocess] allocator and construct the vector in shared memory just if it was any other object. Just execute this first process: -[/doc_contA.cpp] - -[c++] - -#include - #include - #include - - int main () - { - using namespace boost::interprocess; - //Shared memory front-end that is able to construct objects - //associated with a c-string. Erase previous shared memory with the name - //to be used and create the memory segment at the specified address and initialize resources - shared_memory_object::remove("MySharedMemory"); - managed_shared_memory segment - (create_only - ,"MySharedMemory" //segment name - ,65536); //segment size in bytes - - //Alias an STL compatible allocator of ints that allocates ints from the managed - //shared memory segment. This allocator will allow to place containers - //in managed shared memory segments - typedef allocator - ShmemAllocator; - - //Alias a vector that uses the previous STL-like allocator - typedef vector MyVector; - - //Initialize shared memory STL-compatible allocator - const ShmemAllocator alloc_inst (segment.get_segment_manager()); - - //Construct a shared memory vector vector - MyVector *myvector = - segment.construct("MyVector") //object name - (alloc_inst);//first ctor parameter - - //Insert data in the vector - for(int i = 0; i < 100; ++i){ - myvector->push_back(i); - } - - return 0; - } +[import ../example/doc_contA.cpp] +[doc_contA] After this process is executed we can search the constructed vector and use it with STL algorithms: -[/doc_contB.cpp] +[import ../example/doc_contB.cpp] +[doc_contB] -[c++] +[endsect] - #include - #include - #include - #include +[section:qg_interprocess_map Creating maps in shared memory] - int main () - { - using namespace boost::interprocess; +Just like a vector, [*Boost.Interprocess] allows creating maps in shared memory and memory +mapped files. [*Boost.Interprocess]'s map is +The construction of map is a bit tricky, because - //An special shared memory where we can - //construct objects associated with a name. - //Connect to the already created shared memory segment - //and initialize needed resources - managed_shared_memory segment - (open_only - ,"MySharedMemory"); //segment name +For example, we can construct STL-like containers in shared memory. +To do this, we just need to create a an special (managed) shared memory segment, +declare a [*Boost.Interprocess] allocator and construct the vector in shared memory +just if it was any other object. Just execute this first process: - //Alias an STL compatible allocator of ints that allocates ints from the managed - //shared memory segment. This allocator will allow to place containers - //in managed shared memory segments - typedef allocator - ShmemAllocator; - - //Alias a vector that uses the previous STL-like allocator - typedef vector MyVector; - - //Find the vector using the c-string name - MyVector *myvector = segment.find("MyVector").first; - - //Use vector in reverse order - std::sort(myvector->rbegin(), myvector->rend()); - // . . . - - //When done, destroy the vector from the segment - segment.destroy("MyVector"); - return 0; - } +[import ../example/doc_map.cpp] +[doc_map] [endsect] @@ -396,7 +139,7 @@ STL algorithms: [*Boost.Interprocess] does not work only with processes but also with threads. [*Boost.Interprocess] synchronization mechanisms can synchronize threads -between from different processes, but also threads from the same process. +from different processes, but also threads from the same process. [endsect] @@ -417,7 +160,7 @@ processes we have several alternatives: * Two processes can share a [*memory] region. This is the case of classical shared memory or memory mapped files. Once the processes set up the - memory region, the processes can read/write the data without like any + memory region, the processes can read/write the data like any other memory segment without calling the operating system's kernel. This also requieres some kind of manual synchronization between processes. @@ -569,7 +312,7 @@ just as if it was a file: shared_memory_object shm_obj (create_only //only create ,"shared_memory" //name - ,read_write //read-write mode + ,read_write //read-write mode ); * To open or create a shared memory segment: @@ -580,7 +323,7 @@ just as if it was a file: shared_memory_object shm_obj (open_or_create //open or create ,"shared_memory" //name - ,read_only //read-only mode + ,read_only //read-only mode ); * To only open a shared memory segment. Throws if does not exist: @@ -591,7 +334,7 @@ just as if it was a file: shared_memory_object shm_obj (open_only //only open ,"shared_memory" //name - ,read_write //read-write mode + ,read_write //read-write mode ); When a shared memory object is created, its size is 0. @@ -636,7 +379,7 @@ is a `memory_mappable` object: //Map the second half of the memory mapped_region region ( shm //Memory-mappable object - , read_write//Access mode + , read_write //Access mode , ShmSize/2 //Offset from the beginning of shm , ShmSize-ShmSize/2 //Length of the region ); @@ -665,98 +408,69 @@ shared memory object, maps it and initializes all the bytes to a value. After th a client process opens the shared memory, maps it, and checks that the data is correctly initialized. This is the server process: -[/ doc_shared_memory.cpp] - -[c++] - - #include - #include - #include - #include - - int main () - { - using namespace boost::interprocess; - try{ - //Erase previous shared memory - shared_memory_object::remove("shared_memory"); - - //Create a shared memory object. - shared_memory_object shm - (create_only //only create - ,"shared_memory" //name - ,read_write //read-write mode - ); - - //Set size - shm.truncate(1000); - - //Map the whole shared memory in this process - mapped_region region - (shm //What to map - ,read_write //Map it as read-write - ); - - //Get the address of the mapped region - void * addr = region.get_address(); - std::size_t size = region.get_size(); - - //Write all the memory to 1 - std::memset(addr, 1, size); - - } - catch(interprocess_exception &ex){ - std::cout << ex.what() << std::endl; - return 1; - } - - return 0; - } +[import ../example/doc_shared_memory.cpp] +[doc_shared_memory] Now the client process: -[c++] +[import ../example/doc_shared_memory2.cpp] +[doc_shared_memory2] - #include - #include +[endsect] - int main () - { - using namespace boost::interprocess; - try{ - //Open already created shared memory object. - shared_memory_object shm - (open_only //only open - ,"shared_memory" //name - ,read_only//read-only mode - ); +[section:windows_shared_memory Native windows shared memory] - //Map the whole shared memory in this process - mapped_region region - (shm //What to map - ,read_only //Map it as read-only - ); +Windows operating system also offers shared memory, but the lifetime of this +shared memory is very different to kernel or filesystem lifetime. The shared memory +is created backed by the pagefile and it's automatically destroyed when the last +process attached to the shared memory is destroyed. - //Get the address of the mapped region - void * addr = region.get_address(); +Because of this reason, there is no effective way to simulate kernel or filesystem +persistence using native windows shared memory and [*Boost.Interprocess] emulates +shared memory using memory mapped files. This assures portability between POSIX +and Windows operating systems. - //Check that memory was initialized to 1 - const char *mem = static_cast(addr); - for(std::size_t i = 0; i < size; ++i){ - if(*mem++ != 1){ - std::cout << "Error checking memory!" << std::endl; - return 1; - } - } +However, accessing native windows shared memory is a common request of +[*Boost.Interprocess] users because they want to access using modern C++ +mechanisms to shared memory created with other process that don't use +[*Boost.Interprocess]. In order to manage the native windows shared memory +[*Boost.Interprocess] offers the +[classref boost::interprocess::windows_shared_memory windows_shared_memory] class. - std::cout << "Test successful!" << std::endl; - } - catch(interprocess_exception &ex){ - std::cout << "Unexpected exception: " << ex.what() << std::endl; - return 1; - } - return 0; - } +Windows shared memory creation is a bit different from portable shared memory +creation: the size of the segment must be specified when creating the object and +can't be specified through `truncate` like with the shared memory object. + +Take in care that when the last process attached to a shared memory is destroyed +[*the shared memory is destroyed] so there is [*no persistency] with native windows +shared memory. Native windows shared memory has also another limitation: a process can +open and map the whole shared memory created by another process but it can't know +which is the size of that memory. This limitation is imposed by the Windows API so +the user must somehow trasmit the size of the segment to processes opening the +segment. + +Let's repeat the same example presented for the portable shared memory object: +A server process creates a +shared memory object, maps it and initializes all the bytes to a value. After that, +a client process opens the shared memory, maps it, and checks +that the data is correctly initialized. Take in care that [*if the server exits before +the client connects to the shared memory the client connection will fail], because +the shared memory segment is destroyed when no processes are attached to the memory. + +This is the server process: + +[import ../example/doc_windows_shared_memory.cpp] +[doc_windows_shared_memory] + +Now, before destroying the +[classref boost::interprocess::windows_shared memory windows_shared memory] +object, launch the client process: + +[import ../example/doc_windows_shared_memory2.cpp] +[doc_windows_shared_memory2] + +As we can see, native windows shared memory needs synchronization to make sure +that the shared memory won't be destroyed before the client is launched. [endsect] @@ -841,12 +555,12 @@ achieved in [*Boost.Interprocess] creating a `file_mapping` object: using boost::interprocess; file_mapping m_file - ("/usr/home/file" //filename - ,read_write //read-write mode + ("/usr/home/file" //filename + ,read_write //read-write mode ); Now we can use the newly created object to create mapped regions. For more details -regarding `file_mapping` see the +regarding this class see the [classref boost::interprocess::file_mapping] class reference. [endsect] @@ -867,7 +581,7 @@ devices that have also mapping capabilities: //Map the second half of the file mapped_region region ( m_file //Memory-mappable object - , read_write//Access mode + , read_write //Access mode , FileSize/2 //Offset from the beginning of shm , FileSize-FileSize/2 //Length of the region ); @@ -920,119 +634,13 @@ memory segment, maps it and initializes all the bytes the a value. After that, a client process opens the shared memory, maps it, and checks that the data is correctly initialized. This is the server process: -[c++] - - #include - #include - #include - #include - #include - - int main () - { - using namespace boost::interprocess; - try{ - //Create a file - std::filebuf fbuf; - fbuf.open("file.bin", std::ios_base::in | std::ios_base::out - | std::ios_base::trunc | std::ios_base::binary); - - //Set the size - fbuf.pubseekoff(9999, std::ios_base::beg); - fbuf.sputc(0); - fbuf.close(); - - //Create a file mapping. - file_mapping m_file("file.bin", read_write); - - //Map the whole file in this process - mapped_region region - (m_file //What to map - ,read_write //Map it as read-write - ); - - if(region.get_size() != 10000) - return 1; - - //Get the address of the mapped region - void * addr = region.get_address(); - std::size_t size = region.get_size(); - - //Write all the memory to 1 - std::memset(addr, 1, size); - - } - catch(interprocess_exception &ex){ - std::cout << ex.what() << std::endl; - return 1; - } - - return 0; - } +[import ../example/doc_file_mapping.cpp] +[doc_file_mapping] Now the client process: -[c++] - - #include - #include - #include - #include - - int main () - { - using namespace boost::interprocess; - try{ - //Open the file mapping - file_mapping m_file ("file.bin", read_only); - - //Map the whole file in this process - mapped_region region - (m_file //What to map - ,read_only //Map it as read-only - ); - - //Get the address of the mapped region - void * addr = region.get_address(); - std::size_t size = region.get_size(); - - //Check that memory was initialized to 1 - const char *mem = static_cast(addr); - for(std::size_t i = 0; i < size; ++i){ - if(*mem++ != 1){ - std::cout << "Error checking memory!" << std::endl; - return 1; - } - } - - //Flush data to disk - region.flush(); - - //Now test it reading the file - std::filebuf fbuf; - fbuf.open("file.bin", std::ios_base::in | std::ios_base::binary); - - //Read it to memory - std::vector vect(region.get_size(), 0); - fbuf.sgetn(&vect[0], std::streamsize(vect.size())); - - //Check that memory was initialized to 1 - mem = static_cast(&vect[0]); - for(std::size_t i = 0; i < size; ++i){ - if(*mem++ != 1){ - std::cout << "Error checking memory!" << std::endl; - return 1; - } - } - - std::cout << "Test successful!" << std::endl; - } - catch(interprocess_exception &ex){ - std::cout << "Unexpected exception: " << ex.what() << std::endl; - return 1; - } - return 0; - } +[import ../example/doc_file_mapping2.cpp] +[doc_file_mapping2] [endsect] @@ -1092,7 +700,7 @@ To map an object in a fixed address, the user can specify that address in the [c++] mapped_region region ( shm //Map shared memory - , read_write //Map it as read-write + , read_write //Map it as read-write , 0 //Map from offset 0 , 0 //Map until the end , (void*)0x3F000000 //Map it exactly there @@ -1100,7 +708,7 @@ To map an object in a fixed address, the user can specify that address in the However, the user can't map the region in any address, even if the address is not being used. The offset parameter that marks the start of the mapping region -is also limited. This limitations are explained in the next section. +is also limited. These limitations are explained in the next section. [endsect] @@ -1114,25 +722,26 @@ to a multiple of a value called [*page size]. This is due to the fact that the [*operating system performs mapping operations over whole pages]. If fixed mapping address is used, ['offset] and ['address] -parameters should be multiples of that value. This value is, tipically, 4KB or 8KB. +parameters should be multiples of that value. +This value is, tipically, 4KB or 8KB for 32 bit operating systems. [c++] //These might fail because the offset is not a multiple of the page size //and we are using fixed address mapping - mapped_region region1( shm //Map shared memory - , read_write //Map it as read-write - , 1 //Map from offset 1 - , 1 //Map 1 byte - , (void*)0x3F000000 //Aligned mapping address + mapped_region region1( shm //Map shared memory + , read_write //Map it as read-write + , 1 //Map from offset 1 + , 1 //Map 1 byte + , (void*)0x3F000000 //Aligned mapping address ); //These might fail because the address is not a multiple of the page size - mapped_region region2( shm //Map shared memory - , read_write //Map it as read-write - , 0 //Map from offset 0 - , 1 //Map 1 byte - , (void*)0x3F000001 //Not aligned mapping address + mapped_region region2( shm //Map shared memory + , read_write //Map it as read-write + , 0 //Map from offset 0 + , 1 //Map 1 byte + , (void*)0x3F000001 //Not aligned mapping address ); Since the operating system performs mapping operations over whole pages, specifying @@ -1143,32 +752,32 @@ more resources than necessary. If the user specifies the following 1 byte mappin //Map one byte of the shared memory object. //A whole memory page will be used for this. - mapped_region region ( shm //Map shared memory - , read_write //Map it as read-write - , 0 //Map from offset 0 - , 1 //Map 1 byte + mapped_region region ( shm //Map shared memory + , read_write //Map it as read-write + , 0 //Map from offset 0 + , 1 //Map 1 byte ); The operating system will reserve a whole page that will not be reused by any other mapping so we are going to waste [*(page size - 1)] bytes. If we want to use effiently operating system resources, we should create regions whose size is a multiple of [*page size] bytes. If the user specifies the following two -mapped regions for a file with as size = 2*page_size bytes: +mapped regions for a file with which has `2*page_size` bytes: //Map the first quarter of the file //This will use a whole page - mapped_region region1( shm //Map shared memory - , read_write //Map it as read-write - , 0 //Map from offset 0 - , page_size/2 //Map page_size/2 bytes + mapped_region region1( shm //Map shared memory + , read_write //Map it as read-write + , 0 //Map from offset 0 + , page_size/2 //Map page_size/2 bytes ); //Map the rest of the file //This will use a 2 pages - mapped_region region2( shm //Map shared memory - , read_write //Map it as read-write - , page_size/2 //Map from offset 0 - , 3*page_size/2 //Map page_size/2 bytes + mapped_region region2( shm //Map shared memory + , read_write //Map it as read-write + , page_size/2 //Map from offset 0 + , 3*page_size/2 //Map page_size/2 bytes ); In this example, a half of the page is wasted in the first mapping and another @@ -1176,17 +785,17 @@ half is wasted in the second because the offset is not a multiple of the page size. The mapping with the minimum resource usage would be to map whole pages: //Map the whole first half: uses 1 page - mapped_region region1( shm //Map shared memory - , read_write //Map it as read-write - , 0 //Map from offset 0 - , page_size //Map page_size/2 bytes + mapped_region region1( shm //Map shared memory + , read_write //Map it as read-write + , 0 //Map from offset 0 + , page_size //Map page_size/2 bytes ); //Map the second half: uses 1 page - mapped_region region2( shm //Map shared memory - , read_write //Map it as read-write - , page_size //Map from offset 0 - , page_size //Map page_size/2 bytes + mapped_region region2( shm //Map shared memory + , read_write //Map it as read-write + , page_size //Map from offset 0 + , page_size //Map page_size/2 bytes ); How can we obtain the [*page size]? The `mapped_region` class has an static @@ -1198,13 +807,13 @@ function that returns that value: std::size_t page_size = mapped_region::get_page_size(); //This mapping will optimally use system resources - mapped_region region ( shm //Map shared memory - , read_write //Map it as read-write - , 0 //Map from offset 0 - , page_size //Map whole page + mapped_region region ( shm //Map shared memory + , read_write //Map it as read-write + , 0 //Map from offset 0 + , page_size //Map whole page ); -An operating system might also limit the number of mapped memory regions per +The operating system might also limit the number of mapped memory regions per process or per system. [endsect] @@ -1564,163 +1173,23 @@ cyclic buffer, write the trace and continue. To protect the cyclic buffer, we can store a process shared mutex in the cyclic buffer. Each process will lock the mutex before writing the data and -will write a flag when ends writing the traces: +will write a flag when ends writing the traces +(`doc_anonymous_mutex_shared_data.hpp` header): -[c++] - - #include - #include - - struct shared_memory_log - { - enum { NumItems = 100 }; - enum { LineSize = 100 }; - - shared_memory_log() - : current_line(0) - , end_a(false) - , end_b(false) - {} - - //Mutex to protect access to the queue - boost::interprocess::interprocess_mutex mutex; - - //Items to fill - char items[NumItems][LineSize]; - int current_line; - bool end_a; - bool end_b; - }; +[import ../example/doc_anonymous_mutex_shared_data.hpp] +[doc_anonymous_mutex_shared_data] This is the process main process. Creates the shared memory, constructs the the cyclic buffer and start writing traces: -[c++] - - #include - #include - #include "doc_anonymous_mutex_shared_data.hpp" - #include - #include - - using namespace boost::interprocess; - - int main () - { - try{ - //Erase previous shared memory - shared_memory_object::remove("shared_memory"); - - //Create a shared memory object. - shared_memory_object shm - (create_only //only create - ,"shared_memory" //name - ,read_write //read-write mode - ); - - //Set size - shm.truncate(sizeof(shared_memory_log)); - - //Map the whole shared memory in this process - mapped_region region - (shm //What to map - ,read_write //Map it as read-write - ); - - //Get the address of the mapped region - void * addr = region.get_address(); - - //Construct the shared structure in memory - shared_memory_log * data = new (addr) shared_memory_log; - - //Write some logs - for(int i = 0; i < shared_memory_log::NumItems; ++i){ - //Lock the mutex - scoped_lock lock(data->mutex); - sprintf(data->items[(data->current_line++) % shared_memory_log::NumItems] - ,"%s_%d", "process_a", i); - if(i == (shared_memory_log::NumItems-1)) - data->end_a = true; - //Mutex is released here - } - - //Wait until the other process ends - while(1){ - scoped_lock lock(data->mutex); - if(data->end_b) - break; - } - } - catch(interprocess_exception &ex){ - std::cout << ex.what() << std::endl; - return 1; - } - - //Erase shared memory - shared_memory_object::remove("shared_memory"); - - return 0; - } +[import ../example/doc_anonymous_mutexA.cpp] +[doc_anonymous_mutexA] The second process opens the shared memory, obtains access to the cyclic buffer and starts writing traces: -[c++] - - #include - #include - #include "doc_anonymous_mutex_shared_data.hpp" - #include - - using namespace boost::interprocess; - - int main () - { - try{ - //Open the shared memory object. - shared_memory_object shm - (open_only //only create - ,"shared_memory" //name - ,read_write //read-write mode - ); - - //Map the whole shared memory in this process - mapped_region region - (shm //What to map - ,read_write //Map it as read-write - ); - - //Get the address of the mapped region - void * addr = region.get_address(); - - //Construct the shared structure in memory - shared_memory_log * data = static_cast(addr); - - //Write some logs - for(int i = 0; i < 100; ++i){ - //Lock the mutex - scoped_lock lock(data->mutex); - sprintf(data->items[(data->current_line++) % shared_memory_log::NumItems] - ,"%s_%d", "process_a", i); - if(i == (shared_memory_log::NumItems-1)) - data->end_b = true; - //Mutex is released here - } - - //Wait until the other process ends - while(1){ - scoped_lock lock(data->mutex); - if(data->end_a) - break; - } - } - catch(interprocess_exception &ex){ - std::cout << ex.what() << std::endl; - return 1; - } - - return 0; - } +[import ../example/doc_anonymous_mutexB.cpp] +[doc_anonymous_mutexB] As we can see, a mutex is useful to protect data but not to notify to another process an event. For this, we need a condition variable, as we will see in the next section. @@ -1735,41 +1204,8 @@ interrupt a process in any moment we can mix parts of the messages of both proce so we need a way to write the whole message to the file atomically. To achieve this, we can use a named mutex so that each process locks the mutex before writing: -[c++] - - #include - #include - #include - - int main () - { - using namespace boost::interprocess; - try{ - - //Open or create the named mutex - named_mutex mutex(open_or_create, "cout_named_mutex"); - - std::ofstream file("file_name"); - - for(int i = 0; i < 10; ++i){ - - //Do some operations... - - //Write to console atomically - scoped_lock lock(mutex); - file << "Process name, "; - file << "This is iteration #" << i; - file << std::endl; - } - } - catch(interprocess_exception &ex){ - std::cout << ex.what() << std::endl; - return 1; - } - - return 0; - } - +[import ../example/doc_named_mutex.cpp] +[doc_named_mutex] [endsect] @@ -1842,176 +1278,23 @@ condition variables: the first one is used to block the sender until the second process prints the message and the second one to block the receiver until the buffer has a trace to print. -The shared memory trace buffer: +The shared memory trace buffer (doc_anonymous_condition_shared_data.hpp): -[c++] - - #include - #include - - struct trace_queue - { - enum { LineSize = 100 }; - - trace_queue() - : message_in(false) - {} - - //Mutex to protect access to the queue - boost::interprocess::interprocess_mutex mutex; - - //Condition to wait when the queue is empty - boost::interprocess::interprocess_condition cond_empty; - - //Condition to wait when the queue is full - boost::interprocess::interprocess_condition cond_full; - - //Items to fill - char items[LineSize]; - - //Is there any message - bool message_in; - }; +[import ../example/doc_anonymous_condition_shared_data.hpp] +[doc_anonymous_condition_shared_data] This is the process main process. Creates the shared memory, places there the buffer and starts writing messages one by one until it writes "last message" to indicate that there are no more messages to print: -[c++] - - #include - #include - #include - #include "doc_anonymous_condition_shared_data.hpp" - - using namespace boost::interprocess; - - int main () - { - try{ - //Erase previous shared memory - shared_memory_object::remove("shared_memory"); - - //Create a shared memory object. - shared_memory_object shm - (create_only //only create - ,"shared_memory" //name - ,read_write //read-write mode - ); - - //Set size - shm.truncate(sizeof(trace_queue)); - - //Map the whole shared memory in this process - mapped_region region - (shm //What to map - ,read_write //Map it as read-write - ); - - //Get the address of the mapped region - void * addr = region.get_address(); - - //Construct the shared structure in memory - trace_queue * data = new (addr) trace_queue; - - const int NumMsg = 100; - - for(int i = 0; i < NumMsg; ++i){ - scoped_lock lock(data->mutex); - if(data->message_in){ - data->cond_full.wait(lock); - } - if(i == (NumMsg-1)) - sprintf(data->items, "%s", "last message"); - else - sprintf(data->items, "%s_%d", "my_trace", i); - - //Notify to the other process that there is a message - data->cond_empty.notify_one(); - - //Mark message buffer as full - data->message_in = true; - } - } - catch(interprocess_exception &ex){ - std::cout << ex.what() << std::endl; - return 1; - } - - //Erase shared memory - shared_memory_object::remove("shared_memory"); - - return 0; - } - +[import ../example/doc_anonymous_conditionA.cpp] +[doc_anonymous_conditionA] The second process opens the shared memory and prints each message until the "last message" message is received: -[c++] - - #include - #include - #include - #include "doc_anonymous_condition_shared_data.hpp" - - using namespace boost::interprocess; - - int main () - { - try{ - //Erase previous shared memory - shared_memory_object::remove("shared_memory"); - - //Create a shared memory object. - shared_memory_object shm - (open_only //only create - ,"shared_memory" //name - ,read_write //read-write mode - ); - - //Map the whole shared memory in this process - mapped_region region - (shm //What to map - ,read_write //Map it as read-write - ); - - //Get the address of the mapped region - void * addr = region.get_address(); - - //Obtain a pointer to the shared structure - trace_queue * data = static_cast(addr); - - //Print messages until the other process marks the end - bool end_loop = false; - do{ - scoped_lock lock(data->mutex); - if(!data->message_in){ - data->cond_empty.wait(lock); - } - if(strcmp(data->items, "last message") == 0){ - end_loop = true; - } - else{ - //Print the message - std::cout << data->items << std::endl; - //Notify the other process that the buffer is empty - data->message_in = false; - data->cond_full.notify_one(); - } - } - while(!end_loop); - } - catch(interprocess_exception &ex){ - std::cout << ex.what() << std::endl; - return 1; - } - - //Erase shared memory - shared_memory_object::remove("shared_memory"); - - return 0; - } +[import ../example/doc_anonymous_conditionB.cpp] +[doc_anonymous_conditionB] With condition variables, a process can block if it can't continue the work, and when the conditions to continue are met another process can wake it. @@ -2077,146 +1360,23 @@ to the array and the process will block if the array is full. The second process will copy the transmitted data to its own buffer, blocking if there is no new data in the buffer. -This is the shared integer array: +This is the shared integer array (doc_anonymous_semaphore_shared_data.hpp): -[c++] - - #include - - struct shared_memory_buffer - { - enum { NumItems = 10 }; - - shared_memory_buffer() - : mutex(1), nempty(NumItems), nstored(0) - {} - - //Semaphores to protect and synchronize access - boost::interprocess::interprocess_semaphore - mutex, nempty, nstored; - - //Items to fill - int items[NumItems]; - }; +[import ../example/doc_anonymous_semaphore_shared_data.hpp] +[doc_anonymous_semaphore_shared_data] This is the process main process. Creates the shared memory, places there the interger array and starts integers one by one, blocking if the array is full: -[c++] - - #include - #include - #include "doc_anonymous_semaphore_shared_data.hpp" - - using namespace boost::interprocess; - - int main () - { - try{ - //Erase previous shared memory - shared_memory_object::remove("shared_memory"); - - //Create a shared memory object. - shared_memory_object shm - (create_only //only create - ,"shared_memory" //name - ,read_write //read-write mode - ); - - //Set size - shm.truncate(sizeof(shared_memory_buffer)); - - //Map the whole shared memory in this process - mapped_region region - (shm //What to map - ,read_write //Map it as read-write - ); - - //Get the address of the mapped region - void * addr = region.get_address(); - - //Construct the shared structure in memory - shared_memory_buffer * data = new (addr) shared_memory_buffer; - - const int NumMsg = 100; - - //Insert data in the array - for(int i = 0; i < NumMsg; ++i){ - data->nempty.wait(); - data->mutex.wait(); - data->items[i % shared_memory_buffer::NumItems] = i; - data->mutex.post(); - data->nstored.post(); - } - } - catch(interprocess_exception &ex){ - std::cout << ex.what() << std::endl; - return 1; - } - - //Erase shared memory - shared_memory_object::remove("shared_memory"); - - return 0; - } +[import ../example/doc_anonymous_semaphoreA.cpp] +[doc_anonymous_semaphoreA] The second process opens the shared memory and copies the received integers to it's own buffer: -[c++] - - #include - #include - #include "doc_anonymous_semaphore_shared_data.hpp" - - using namespace boost::interprocess; - - int main () - { - try{ - //Create a shared memory object. - shared_memory_object shm - (open_only //only create - ,"shared_memory" //name - ,read_write //read-write mode - ); - - //Map the whole shared memory in this process - mapped_region region - (shm //What to map - ,read_write //Map it as read-write - ); - - //Get the address of the mapped region - void * addr = region.get_address(); - - //Obtain the shared structure - shared_memory_buffer * data = static_cast(addr); - - const int NumMsg = 100; - - int extracted_data [NumMsg]; - - //Extract the data - for(int i = 0; i < NumMsg; ++i){ - data->nstored.wait(); - data->mutex.wait(); - extracted_data[i] = data->items[i % shared_memory_buffer::NumItems]; - data->mutex.post(); - data->nempty.post(); - } - } - catch(interprocess_exception &ex){ - std::cout << ex.what() << std::endl; - return 1; - } - - //Erase shared memory - shared_memory_object::remove("shared_memory"); - - return 0; - } +[import ../example/doc_anonymous_semaphoreB.cpp] +[doc_anonymous_semaphoreB] The same interprocess communication can be achieved with a condition variables and mutexes, but for several synchronization patterns, a semaphore is more @@ -2703,9 +1863,16 @@ more features and operations, see their reference for more informations [endsect] -[section:upgradable_mutexes_example Anonymous Upgradable Mutex Example] +[/section:upgradable_mutexes_example Anonymous Upgradable Mutex Example] -[endsect] +[/import ../example/doc_anonymous_upgradable_mutexA.cpp] +[/doc_anonymous_upgradable_mutexA] + + +[/import ../example/doc_anonymous_upgradable_mutexB.cpp] +[/doc_anonymous_upgradable_mutexB] + +[/endsect] [endsect] @@ -3094,7 +2261,7 @@ The message queue is explicitly removed calling the static `remove` function: using boost::interprocess; message_queue::remove("message_queue"); -The funtion might fail if the message queue is still being used by any process. +The funtion can fail if the message queue is still being used by any process. [endsect] @@ -3108,79 +2275,15 @@ To use a message queue you must include the following header: In the following example, the first process creates the message queue, and writes an array of integers on it. The other process just reads the array and checks that -the sequence number is correct. +the sequence number is correct. This is the first process: -[c++] +[import ../example/doc_message_queueA.cpp] +[doc_message_queueA] - #include - #include - #include +This is the second process: - using namespace boost::interprocess; - - int main () - { - try{ - //Erase previous message queue - message_queue::remove("message_queue"); - - //Create a message_queue. - message_queue mq - (create_only //only create - ,"message_queue" //name - ,100 //max message number - ,sizeof(int) //max message size - ); - - //Send 100 numbers - for(int i = 0; i < 100; ++i){ - mq.send(&i, sizeof(i), 0); - } - } - catch(interprocess_exception &ex){ - std::cout << ex.what() << std::endl; - return 1; - } - - return 0; - } - - -[c++] - - #include - #include - #include - - using namespace boost::interprocess; - - int main () - { - try{ - //Open a message queue. - message_queue mq - (open_only //only create - ,"message_queue" //name - ); - - unsigned int priority; - unsigned int recvd_size; - - //Receive 100 numbers - for(int i = 0; i < 100; ++i){ - int number; - mq.receive(&number, sizeof(number), recvd_size, priority); - if(number != i || recvd_size != sizeof(number)) - return 1; - } - } - catch(interprocess_exception &ex){ - std::cout << ex.what() << std::endl; - return 1; - } - - return 0; - } +[import ../example/doc_message_queueB.cpp] +[doc_message_queueB] To know more about this class and all its operations, please see the [classref boost::interprocess::message_queue] class reference. @@ -3424,7 +2527,7 @@ This will produce a compilation error: [section:file_lock_not_thread_safe Caution: Synchronization limitations] -If you plan to use file locks just like a named mutex, be careful, because portable +If you plan to use file locks just like named mutexes, be careful, because portable file locks have synchronization limitations, mainly because different implementations (POSIX, Windows) offer different guarantees. Interprocess file locks have the following limitations: @@ -3514,7 +2617,7 @@ processes. The memory segment can be mapped in different address in each process //Map the whole shared memory mapped_region region ( shm //Memory-mappable object - , read_write //Access mode + , read_write //Access mode ); //This address can be different in each process @@ -3570,8 +2673,8 @@ between the pointee's address and the One of the big problems of `offset_ptr` is the representation of the null pointer. The null pointer can't be safely represented like an offset, since the 0 absolute address -is always out of the mapped region and since the segment can be -mapped in a different base address, the distance between the address 0 +is always out of the mapped region and the segment can be mapped +in a different base address in each process, the distance between the address 0 and `offset_ptr` is different for every process. Some implementations choose @@ -3581,11 +2684,11 @@ point to themselves (the end node in an empty container, for example), and 0 offset value is needed. An alternative is to store, in addition to the offset, a boolean to indicate if the pointer is null. However, this increments the size of the -pointer and huts performance. +pointer and hurts performance. In consequence, [classref boost::interprocess::offset_ptr offset_ptr] defines offset 1 -as the null pointer, meaning that this class can point to the byte +as the null pointer, meaning that this class [*can't] point to the byte after its own ['this] pointer: [c++] @@ -3611,7 +2714,8 @@ after its own ['this] pointer: In practice, this limitation is not important, since a user almost never wants to point to this address. -The offset_ptr class offers all pointer-like operations and +[classref boost::interprocess::offset_ptr offset_ptr] +offers all pointer-like operations and random_access_iterator typedefs, so it can be used in STL algorithms requiring random access and detected via traits. For more information about the members and operations of the class, see @@ -3683,7 +2787,7 @@ These classes can be customized with the following template parameters: the created named objects (for example, *char* or *wchar_t*) * *MemoryAlgorithm* is the memory algorithm used to allocate portions of the - segment (for example simple sequential fit). The internal typedefs of the + segment (for example, rbtree_best_fit ). The internal typedefs of the memory algorithm also define: * The synchronization type (`MemoryAlgorithm::mutex_family`) to be used in all allocation operations. @@ -3727,27 +2831,27 @@ specializations: [c++] /*!Defines a managed shared memory with c-strings as keys for named objects, - the simple sequential fit algorithm (with process-shared mutexes, - and offset_ptr pointer) - as memory allocation algorithm and flat_map (an ordered vector) as index. + the default memory algorithm (with process-shared mutexes, + and offset_ptr as internal pointers) as memory allocation algorithm + and the default index type as the index. This class allows the shared memory to be mapped in different base in different processes*/ typedef - basic_managed_shared_memory > - ,flat_map_index> + basic_managed_shared_memory as void_pointer*/ + ,/*Default index type*/> managed_shared_memory; /*!Defines a managed shared memory with wide strings as keys for named objects, - the simple sequential fit algorithm (with process-shared mutexes, - and offset_ptr pointer) - as memory allocation algorithm and flat_map (an ordered vector) as index. + the default memory algorithm (with process-shared mutexes, + and offset_ptr as internal pointers) as memory allocation algorithm + and the default index type as the index. This class allows the shared memory to be mapped in different base in different processes*/ typedef - basic_managed_shared_memory > - ,flat_map_index> + basic_managed_shared_memory as void_pointer*/ + ,/*Default index type*/> wmanaged_shared_memory; `managed_shared_memory` allocates objects in shared memory asociated with a c-string and @@ -3755,6 +2859,36 @@ specializations: terminated string. Both define the pointer type as `offset_ptr` so they can be used to map the shared memory at different base addresses in different processes. +If the user wants to map the shared memory in the same address in all processes and +want to use raw pointers internally instead of offset pointers, [*Boost.Interprocess] +defines the following types: + +[c++] + + /*!Defines a managed shared memory with c-strings as keys for named objects, + the default memory algorithm (with process-shared mutexes, + and offset_ptr as internal pointers) as memory allocation algorithm + and the default index type as the index. + This class allows the shared memory to be mapped in different base + in different processes*/ + typedef basic_managed_shared_memory + + fixed_managed_shared_memory; + + /*!Defines a managed shared memory with wide strings as keys for named objects, + the default memory algorithm (with process-shared mutexes, + and offset_ptr as internal pointers) as memory allocation algorithm + and the default index type as the index. + This class allows the shared memory to be mapped in different base + in different processes*/ + typedef basic_managed_shared_memory + + wfixed_managed_shared_memory; + [endsect] [section:constructing_managed_shared_memories Constructing Managed Shared Memory] @@ -3828,10 +2962,42 @@ the shared memory object from the system you must use the `shared_memory_object: function. Shared memory object removing might fail if any process still has the shared memory object mapped. +The user can also map the managed shared memory in a fixed address. This option is +essential when using using `fixed_managed_shared_memory`. To do this, just +add the mapping address as an extra parameter: + +[c++] + + fixed_managed_shared_memory segment + (open_only + ,"MyFixedAddressSharedMemory" //Shared memory object name + ,(void*)0x30000000 //Mapping address + +[endsect] + +[section:windows_managed_memory_common_shm Using native windows shared memory] + +Windows users might also want to use native windows shared memory instead of +the portable [classref boost::interprocess::shared_memory_object shared_memory_object] +based managed memory. This is achieved through the +[classref boost::interprocess::basic_managed_windows_shared_memory basic_managed_windows_shared_memory] +class. To use it just include: + +[c++] + + #include + +This class has the same interface as +[classref boost::interprocess::basic_managed_shared_memory basic_managed_shared_memory] +but uses native windows shared memory. Note that this managed class has the same +lifetime issues as the windows shared memory: when the last process attached to the +windows shared memory is detached from the memory (or ends/crashes) the memory is +destroyed. So there is no persistence support for windows shared memory. + [endsect] For more information about managed shared memory capabilities, see -[classref boost::interprocess::basic_managed_shared_memory] class reference. +[classref boost::interprocess::basic_managed_shared_memory basic_managed_shared_memory] class reference. [endsect] @@ -3849,22 +3015,22 @@ specializations: //Named object creation managed memory segment //All objects are constructed in the memory-mapped file // Names are c-strings, - // Default memory management algorithm(simple_seq_fit with no mutexes) + // Default memory management algorithm(rbtree_best_fit with no mutexes) // Name-object mappings are stored in the default index type (flat_map) typedef basic_managed_mapped_file < char, - simple_seq_fit >, + rbtree_best_fit >, flat_map_index > managed_mapped_file; //Named object creation managed memory segment //All objects are constructed in the memory-mapped file // Names are wide-strings, - // Default memory management algorithm(simple_seq_fit with no mutexes) + // Default memory management algorithm(rbtree_best_fit with no mutexes) // Name-object mappings are stored in the default index type (flat_map) typedef basic_managed_mapped_file< wchar_t, - simple_seq_fit >, + rbtree_best_fit >, flat_map_index > wmanaged_mapped_file; @@ -3950,7 +3116,7 @@ by any process. [endsect] For more information about managed mapped file capabilities, see -[classref boost::interprocess::basic_managed_mapped_file] class reference. +[classref boost::interprocess::basic_managed_mapped_file basic_managed_mapped_file] class reference. [endsect] @@ -3970,31 +3136,38 @@ comes with throwing and no throwing versions. Throwing version throws boost::interprocess::bad_alloc (which derives from `std::bad_alloc`) if there is no more memory and the non-throwing version returns 0 pointer. -[c++] - - #include +[import ../example/doc_managed_raw_allocation.cpp] +[doc_managed_raw_allocation] - int main() - { - using namespace boost::interprocess; +[endsect] - //Managed memory segment that allocates portions of a shared memory - //segment with the default management algorithm - managed_shared_memory managed_shm(create_only, "MyManagedShm", 65536); +[section:allocate_aligned Allocating aligned fragments of a managed memory segment] - //Allocate 100 bytes of memory from segment, throwing version - void *ptr = managed_shm.allocate(100); +Sometimes it's interesting to be able to allocate aligned fragments of memory +from a segment and managed memory segments offer also that possibility. - //Deallocate it - managed_shm.deallocate(ptr); +This allocation is similar to the previously shown raw memory allocation but +it takes an additional parameter specifying the alignment. There is +a restriction for the alignment: [*the alignment must be power of two]. - //Non throwing version - ptr = managed_shm.allocate(100, std::nothrow); +If a user wants to allocate many aligned blocks (for example aligned to 128 bytes), +the size that minimizes the memory waste is a value that's is nearly a multiple +of that alignment (for example 128 - some bytes). This way, if the first bytes +of a big block of memory are used +to fulfill the aligned allocation, the rest of the block is also aligned to that +value and ready for the next aligned allocation. Note +that [*a size equal to the alignment is not correct] because the memory +allocation algorithm needs some payload bytes to store deallocation information. - //Deallocate it - managed_shm.deallocate(ptr); - return 0; - } +If the user could know the size of the payload, he could request a size that will +be optimal to allocate aligned chunks of memory maximizing both the size of the +request [*and] the possibilities of future aligned allocations. This information +is stored in the PayloadPerAllocation constant of managed memory segments. + +Here's is an small example showing how aligned allocation is used: + +[import ../example/doc_managed_aligned_allocation.cpp] +[doc_managed_aligned_allocation] [endsect] @@ -4009,15 +3182,15 @@ of a managed memory segment or objects constructed in the managed segment. [c++] - //Process A obtains the offset of the address - managed_shared_memory::handle handle = + //Process A obtains the offset of the address + managed_shared_memory::handle handle = segment.get_handle_from_address(processA_address); - //Process A sends this address using any mechanism to process B + //Process A sends this address using any mechanism to process B - //Process B obtains the handle and transforms it again to an address + //Process B obtains the handle and transforms it again to an address managed_shared_memory::handle handle = ... - void * processB_address = segment.get_address_from_handle(handle); + void * processB_address = segment.get_address_from_handle(handle); [endsect] @@ -4180,19 +3353,19 @@ Each index has its own characteristics, like search-time, insertion time, deleti memory use, and memory allocation patterns. [*Boost.Interprocess] offers 3 index types right now: -* [*boost::interprocess::flat_map_index]: Based on boost::interprocess::flat_map, an ordered +* [*boost::interprocess::flat_map_index flat_map_index]: Based on boost::interprocess::flat_map, an ordered vector similar to Loki library's AssocVector class, offers great search time and minimum memory use. But the vector must be reallocated when is full, so all data must be copied to the new buffer. Ideal when insertions are mainly in initialization time and in run-time we just need searches. -* [*boost::interprocess::map_index]: Based on boost::interprocess::map, a managed memory ready +* [*boost::interprocess::map_index map_index]: Based on boost::interprocess::map, a managed memory ready version of std::map. Since it's a node based container, it has no reallocations, the tree must be just rebalanced sometimes. Offers equilibrated insertion/deletion/search times with more overhead per node comparing to *boost::interprocess::flat_map_index*. Ideal when searches/insertions/deletions are in random order. -* [*boost::interprocess::null_index]: This index is for people using a managed +* [*boost::interprocess::null_index null_index]: This index is for people using a managed memory segment just for raw memory buffer allocations and they don't make use of named/unique allocations. This class is just empty and saves some space and compilation time. @@ -4201,19 +3374,19 @@ right now: As an example, if we want to define new managed shared memory class using *boost::interprocess::map* as the index type we -just must specify [boost::interprocess::map_index] as a template parameter: +just must specify [boost::interprocess::map_index map_index] as a template parameter: [c++] //This managed memory segment can allocate objects with: // -> a wchar_t string as key - // -> boost::interprocess::simple_seq_fit with process-shared mutexes + // -> boost::interprocess::rbtree_best_fit with process-shared mutexes // as memory allocation algorithm. // -> boost::interprocess::map<...> as the index to store name/object mappings // typedef boost::interprocess::basic_managed_shared_memory < wchar_t - , boost::interprocess::simple_seq_fit > + , boost::interprocess::rbtree_best_fit > , boost::interprocess::map_index > my_managed_shared_memory; @@ -4239,8 +3412,8 @@ memory buffer, a single [*segment manager] class can manage several managed memory segment types. Some [*Boost.Interprocess] classes require a pointer to the segment manager in -their constructor, and this can be obtained from any managed memory segment using -`get_segment_manager` member: +their constructors, and the segment manager can be obtained from any managed +memory segment using `get_segment_manager` member: [c++] @@ -4251,343 +3424,69 @@ their constructor, and this can be obtained from any managed memory segment usin [endsect] -[section:stl_allocators STL compatible allocators] +[section:allocator_introduction Introduction to Interprocess allocators] -[section:allocator_introduction Introduction to STL compatible allocators] - -As seen, [*Boost.Interprocess] offers raw memory allocation and object construction using managed -memory segments (managed shared memory, managed mapped files...) and -one of the first user requests is the use of containers in managed shared memories. To achieve this, -[*Boost.Interprocess] makes use of managed memory segment's memory allocation algorithms to build 2 common -memory allocation schemes: variable size object allocation and fixed size object allocation (segregated storage), -implemented in these allocators: - -* *boost::interprocess::allocator* offers general purpose, variable size allocation. - -* *boost::interprocess::node_allocator* offers a segregated storage allocation scheme sharing a common - pool between all instances of the class placed in the same managed memory, so memory usage is optimized. - -* *boost::interprocess::private_node_allocator* offers a segregated storage allocation scheme where - each `private_node_allocator` owns its own pool. This allocator offers faster allocation - than node_allocator since it avoids synchronization between threads/processes that happens - when accesing the common pool, but imposes a higher memory usage. Take in care that the - standard does not recommend this private, per allocator, pool. - -* *boost::interprocess::cached_node_allocator* offers a segregated storage allocation scheme between - node_allocator and private_node_allocator. This allocator caches some nodes from the common - the common pool and stores them privately so that these are quickly available - without the synchronization overhead for future allocations. +As seen, [*Boost.Interprocess] offers raw memory allocation and object construction +using managed memory segments (managed shared memory, managed mapped files...) and +one of the first user requests is the use of containers in managed shared memories. +To achieve this, [*Boost.Interprocess] makes use of managed memory segment's +memory allocation algorithms to build several memory allocation schemes, including +general purpose and node allocators. [*Boost.Interprocess] STL compatible allocators are configurable via template parameters. Allocators define their `pointer` typedef based on the `void_pointer` typedef of the segment manager passed as template argument. When this `segment_manager::void_pointer` is a relative pointer, -(for example, `boost::interprocess::offset_ptr`) the user can place these allocators in +(for example, `offset_ptr`) the user can place these allocators in memory mapped in different base addresses in several processes. -[endsect] +[section:allocator_properties Properties of [*Boost.Interprocess] allocators] -[section:allocator boost::interprocess::allocator: STL compatible allocator for managed memory segments] +Container allocators are normally default-contructible because the are stateless. +`std::allocator` and [*Boost.Pool's] `boost::pool_allocator`/`boost::fast_pool_allocator` +are examples of default-constructible allocators. -The *boost::interprocess::allocator* class defines a STL compatible allocator class that -uses the managed memory segment's algorithm to allocate and deallocate memory. This is -achieved though the [*segment manager] of the managed memory segment. -This allocator is templatized with the allocated type, and the segment manager. +On the other hand, [*Boost.Interprocess] allocators need to allocate memory from a +concrete memory segment and not from a system-wide memory source (like the heap). +[*Boost.Interprocess] allocators are [*stateful], which means that they must be +configured to tell them where the shared memory or the memory mapped file is. -To use `boost::interprocess::allocator`, you must include the following header: +This information is transmitted at compile-time and run-time: The allocators +receive a template parameter defining the type of the segment manager and +their constructor receive a pointer to the segment manager of the managed memory +segment where the user wants to allocate the values. + +[*Boost.Interprocess] allocators have [*no default-constructors] and containers +must be explicitly initialized with a configured allocator: [c++] - #include + //The allocators must be templatized with the segment manager type + typedef any_interprocess_allocator + Allocator; -[c++] - - namespace boost::interprocess { - - /*!An STL compatible allocator that uses a segment manager as - memory source. The internal pointer type will of the same type (raw, smart) as - "typename SegmentManager::void_pointer" type. This allows - placing the allocator in shared memory, memory mapped-files, etc...*/ - template - class allocator - { - public: - - /*!Returns the segment manager. Never throws*/ - segment_manager* get_segment_manager() const; - - /*!Constructor from the segment manager. Never throws*/ - allocator(segment_manager *segment_mngr); - - //The rest of the interface is the same of std::allocator - }; - - }} // namespace boost::interprocess { - -The class *allocator* must be always initialized with the allocation -algorithm obtained from the segment where you want *boost::interprocess::allocator* -to allocate memory. - -[c++] - - //Alias allocator type with - // T=int - // SegmentManager = managed_shared_memory::segment_manager - typedef allocator Allocator; - - //Initialize allocator with the segment manager - Allocator alloc_inst (segment.get_segment_manager()); - -The allocator just provides the needed typedefs and forwards all allocation -and deallocation requests to the segment manager passed in the constructor. - -[endsect] - -[section:node_allocator boost::interprocess::node_allocator: a simple segregated storage] - -Variable size memory algorithms waste -some space in management information for each allocation. Sometimes, -usually for small objects, this is not acceptable. Memory algorithms can -also fragment the managed memory segment under some allocation and -deallocation schemes, reducing their performance. When allocating -many objects of the same type, a simple segregated storage becomes -a fast and space-friendly allocator, as explained in Boost Pool library. - -To build normal node allocators, usually a global, thread shared singleton -pool is used for each node size. This is not possible if you try to share -a node allocator between processes. To achieve this sharing, the *node_allocator* -uses a unique name to identify the pool shared by all this node_allocators. In the -initialization, a *node_allocator* object searches this unique object in the segment. -If it is not preset, it builds one. This way, all *node_allocator* objects built -inside a memory segment share a unique memory pool. - -The common segregated storage is not only shared between node_allocators of the -same type, but it is also shared between all node_allocators that allocate objects -of the same size, for example, *node_allocator* and *node_allocator*. -This saves a lot of memory but also imposes an synchronization overhead for each -node allocation. - -The common segregated storage, dynamically created using the unique name explained before, -integrates a reference count so that a node_allocator can know if any other node_allocator -is attached to the same common segregated storage to allow an ordered common segregated -storage destruction when the last node_allocator is destroyed. - -To use `boost::interprocess::node_allocator`, you must include the following header: - -[c++] - - #include - -[c++] - - /*!An STL node allocator that uses a segment manager as memory - source. The internal pointer type will of the same type (raw, smart) as - "typename SegmentManager::void_pointer" type. This allows - placing the allocator in shared memory, memory mapped-files, etc... - This node allocator shares a segregated storage between all instances - of node_allocator with equal sizeof(T) placed in the same segment - group. N is the number of nodes allocated at once when the allocator - needs runs out of nodes*/ - template - class node_allocator - { - public: - - //No default constructor - - /*!Constructor from a segment manager. - Can throw boost::interprocess::bad_alloc*/ - node_allocator(SegmentManager *segment_mngr); - - /*!Returns a pointer to the segment manager. Never throws*/ - SegmentManager *get_segment_manager() const; - - /*...*/ - //The rest is the same interface as std::allocator - /*...*/ - -The [*node_allocator] must be always initialized with the segment -manager obtained from the segment where you want [*node_allocator] to allocate memory. - -[c++] - - //Alias allocator type with - // T=int - // N=64 - // SegmentManager = managed_shared_memory::segment_manager - typedef node_allocator NodeAllocator; - - //Initialize allocator instance with the segment manager - NodeAllocator alloc_inst (segment.get_segment_manager()); - -All STL compatible containers that want to use this allocation scheme -must be constructed with an initialized node_allocator so -that they can allocate the values with the node allocator: - -[c++] + //The allocator must be constructed with a pointer to the segment manager + Allocator alloc_instance (segment.get_segment_manager(), ...); + //Containers must be initialized with a configured allocator + typedef my_list MyIntList; MyIntList mylist(alloc_inst); - mylist.insert(mylist.begin(), 3); + + //This would lead to a compilation error, because + //the allocator has no default constructor + //MyIntList mylist; + +[*Boost.Interprocess] allocators also have a `get_segment_manager()` function +that returns the underlying segment manager that they have received in the +constructor: + +[c++] + + Allocator::segment_manager s = alloc_instance.get_segment_manager(); + AnotherType *a = s->construct(anonymous_instance)(/*Parameters*/); [endsect] -[section:private_node_allocator boost::interprocess::private_node_allocator: a private segregated storage] - -As said, the node_allocator shares a common segregated storage between -node_allocators that allocate objects of the same size and this optimizes -memory usage. However, it needs a unique/named object construction feature -so that this sharing can be possible. Also -imposes a synchronization overhead per node allocation because of this share. -Sometimes, the unique object service is not available (for example, when -building index types to implement the named allocation service itself) or the -synchronization overhead is not acceptable. - -So [*private_node_allocator] uses the same segregated storage as `node_allocator`, -but each [*private_node_allocator] has its own segregated storage pool. No synchronization -is used when allocating nodes, so there is far less overhead for an operation -that usually involves just a few pointer operations when allocating and -deallocating a node. - -To use `boost::interprocess::private_node_allocator`, you must include the following header: - -[c++] - - #include - -[c++] - - /*!An STL node allocator that uses a segment manager as memory - source. The internal pointer type will of the same type (raw, smart) as - "typename SegmentManager::void_pointer" type. This allows - placing the allocator in shared memory, memory mapped-files, etc... - This allocator has its own node pool. N is the number of nodes allocated - at once when the allocator needs runs out of nodes*/ - template - class private_node_allocator - { - public: - - //No default constructor - - /*!Constructor from a segment manager. Never throws*/ - private_node_allocator(SegmentManager *segment_mngr); - - /*!Returns a pointer to the segment manager. Never throws*/ - SegmentManager *get_segment_manager() const; - - /*...*/ - //The rest is the same interface as std::allocator - /*...*/ - -Any [*private_node_allocator] must be initialized with a pointer -to the segment manager of the segment from you want [*private_node_allocator] -to allocate memory: - -[c++] - - //Alias allocator type with - // T=int - // N=64 - // SegmentManager = managed_shared_memory::segment_manager - typedef private_node_allocator - PrivateNodeAllocator; - - //Initialize allocator instance with the segment manager - PrivateNodeAllocator alloc_inst (segment.get_segment_manager()); - -All STL compatible containers that want to use this allocation scheme -must be constructed with an initialized private_node_allocator so -that they can allocate the values with the private node allocator: - -[c++] - - MyIntList mylist(alloc_inst); - mylist.insert(mylist.begin(), 3); - -[endsect] - -[section:cached_node_allocator boost::interprocess::cached_node_allocator: caching nodes to avoid overhead] - -The total node sharing of [*boost::interprocess::node_allocator] can impose a high overhead for some -applications and the minimal synchronization overhead of [*boost::interprocess::private_node_allocator] -can impose a unacceptable memory waste for other applications. - -To solve this, [*Boost.Interprocess] offers an allocator, [*boost::interprocess::cached_node_allocator], that -allocates nodes from the common pool but caches some of them privately so that following -allocations have no synchronization overhead. When the cache is full, the allocator -returns some cached nodes to the common pool, and those will be available to other -allocators. - -To use `boost::interprocess::cached_node_allocator`, you must include the following header: - -[c++] - - #include - -[c++] - - /*!An STL node allocator that uses a segment manager as memory - source. The internal pointer type will of the same type (raw, smart) as - "typename SegmentManager::void_pointer" type. This allows - placing the allocator in shared memory, memory mapped-files, etc... - This node allocator shares a segregated storage between all instances - of cached_node_allocator with equal sizeof(T) placed in the same - managed memory segment. But also caches some nodes privately to - avoid some synchronization overhead./* - - template - class cached_node_allocator - { - public: - - //No default constructor - - /*!Constructor from a segment manager. Never throws*/ - cached_node_allocator(AllocAlgo_t *segment_mngr); - - /*!Returns a pointer to the segment manager. Never throws*/ - SegmentManager *get_segment_manager() const; - - /*!Sets the new max cached nodes value. This can provoke deallocations - if "newmax" is less than current cached nodes. Never throws*/ - void set_max_cached_nodes(std::size_t newmax); - - /*!Returns the max cached nodes parameter. Never throws*/ - std::size_t get_max_cached_nodes() const; - - /*...*/ - //The rest is the same interface as std::allocator - /*...*/ - -Any *cached_node_allocator* must be initialized with a pointer to the segment -manager of the managed memory segment: - -[c++] - - //Alias allocator type with - // T=int - // SegmentManager = managed_shared_memory::segment_manager - typedef cached_node_allocator - CachedNodeAllocator; - - //Initialize allocator instance with algorithm - CachedNodeAllocator alloc_inst (segment.get_segment_manager()); - -All STL compatible containers that want to use this allocation scheme -must be constructed with an initialized `cached_node_allocator` so -that they can allocate the values with the cached_node_allocator: - -[c++] - - //Change cache size as desired (for example 100 nodes) - alloc_inst.set_max_cached_nodes(100); - - //Initialize container - MyIntList mylist(alloc_inst); - mylist.insert(mylist.begin(), 3); - -[endsect] - -[section:allocator_swapping Swapping STL compatible allocators] +[section:allocator_swapping Swapping Boost.Interprocess allocators] When swapping STL containers, there is an active discussion on what to do with the allocators. Some STL implementations, for example Dinkumware from Visual .NET 2003, @@ -4605,13 +3504,511 @@ to any object placed in other shared memory segment, since in each process, the the segments is different. However, if both shared memory allocators are in the same segment, a non-throwing swap is possible, just like heap allocators. -Until a final resolution is achieved. [*Boost.Interprocess] STL compatible allocators implement a non-throwing +Until a final resolution is achieved. [*Boost.Interprocess] allocators implement a non-throwing swap function that swaps internal pointers. If an allocator placed in a shared memory segment is swapped with other placed in a different shared memory segment, the result is undefined. But a crash is quite sure. [endsect] +[section:allocator allocator: A general purpose allocator for managed memory segments] + +The [classref boost::interprocess::allocator allocator] class defines an allocator class that +uses the managed memory segment's algorithm to allocate and deallocate memory. This is +achieved through the [*segment manager] of the managed memory segment. This allocator +is the equivalent for managed memory segments of the standard `std::allocator`. +[classref boost::interprocess::allocator allocator] +is templatized with the allocated type, and the segment manager. + +[*Equality:] Two [classref boost::interprocess::allocator allocator] instances +constructed with the same segment manager compare equal. If an instance is +created using copy constructor, that instance compares equal with the original one. + +[*Allocation thread-safety:] Allocation and deallocation are implemented as calls +to the segment manager's allocation function so the allocator offers the same +thread-safety as the segment manager. + +To use [classref boost::interprocess::allocator allocator] you must include +the following header: + +[c++] + + #include + + +[classref boost::interprocess::allocator allocator] has the following declaration: + +[c++] + + namespace boost { + namespace interprocess { + + template + class allocator; + + } //namespace interprocess { + } //namespace boost { + +The allocator just provides the needed typedefs and forwards all allocation +and deallocation requests to the segment manager passed in the constructor, just +like `std::allocator` forwards the requests to `operator new[]`. + +Using [classref boost::interprocess::allocator allocator] is straightforward: + +[import ../example/doc_allocator.cpp] +[doc_allocator] + +[endsect] + +[endsect] + +[section:stl_allocators_segregated_storage Segregated storage node allocators] + +Variable size memory algorithms waste +some space in management information for each allocation. Sometimes, +usually for small objects, this is not acceptable. Memory algorithms can +also fragment the managed memory segment under some allocation and +deallocation schemes, reducing their performance. When allocating +many objects of the same type, a simple segregated storage becomes +a fast and space-friendly allocator, as explained in the +[@http://www.boost.org/libs/pool/ [*Boost.Pool]] library. + +Segregate storage node +allocators allocate large memory chunks from a general purpose memory +allocator and divide that chunk into several nodes. No bookeeping information +is stored in the nodes to achieve minimal memory waste: free nodes are linked +using a pointer constructed in the memory of the node. + +[*Boost.Interprocess] +offers 3 allocators based on this segregated storage algorithm: +[classref boost::interprocess::node_allocator node_allocator], +[classref boost::interprocess::private_node_allocator private_node_allocator] and +[classref boost::interprocess::cached_node_allocator cached_node_allocator]. + +To know the details of the implementation of +of the segregated storage pools see the +[link interprocess.architecture_2.implementation_segregated_storage_pools Implementation of [*Boost.Interprocess] segregated storage pools] +section. + +[section:segregated_allocators_common Additional parameters and functions of segregated storage node allocators] + +[classref boost::interprocess::node_allocator node_allocator], +[classref boost::interprocess::private_node_allocator private_node_allocator] and +[classref boost::interprocess::cached_node_allocator cached_node_allocator] implement +the standard allocator interface and the functions explained in the +[link interprocess.allocator_introduction.allocator_properties Properties of Boost.Interprocess allocators]. + +All these allocators are templatized by 3 parameters: + +* `class T`: The type to be allocated. +* `class SegmentManager`: The type of the segment manager that will be passed in the constructor. +* `std::size_t NodesPerChunk`: The number of nodes that a memory chunk will contain. + This value will define the size of the memory the pool will request to the + segment manager when the pool runs out of nodes. This parameter has a default value. + +These allocators also offer the `deallocate_free_chunks()` function. This function will +traverse all the memory chunks of the pool and will return to the managed memory segment +the free chunks of memory. If this function is not used, deallocating the free chunks does +not happen until the pool is destroyed so the only way to return memory allocated +by the pool to the segment before destructing the pool is calling manually this function. +This function is quite time-consuming because it has quadratic complexity (O(N^2)). + +[endsect] + +[section:node_allocator node_allocator: A process-shared segregated storage] + +For heap-memory node allocators (like [*Boost.Pool's] `boost::fast_pool_allocator` +usually a global, thread-shared singleton +pool is used for each node size. This is not possible if you try to share +a node allocator between processes. To achieve this sharing +[classref boost::interprocess::node_allocator node_allocator] +uses the segment manager's unique type allocation service +(see [link interprocess.managed_memory_segment_features.unique Unique instance construction] section). + +In the initialization, a +[classref boost::interprocess::node_allocator node_allocator] +object searches this unique object in +the segment. If it is not preset, it builds one. This way, all +[classref boost::interprocess::node_allocator node_allocator] +objects built inside a memory segment share a unique memory pool. + +The common segregated storage is not only shared between node_allocators of the +same type, but it is also shared between all node allocators that allocate objects +of the same size, for example, [*node_allocator] and [*node_allocator]. +This saves a lot of memory but also imposes an synchronization overhead for each +node allocation. + +The dynamically created common segregated storage +integrates a reference count so that a +[classref boost::interprocess::node_allocator node_allocator] +can know if any other +[classref boost::interprocess::node_allocator node_allocator] +is attached to the same common segregated storage. When the last +allocator attached to the pool is destroyed, the pool is destroyed. + +[*Equality:] Two [classref boost::interprocess::node_allocator node_allocator] instances +constructed with the same segment manager compare equal. If an instance is +created using copy constructor, that instance compares equal with the original one. + +[*Allocation thread-safety:] Allocation and deallocation are implemented as calls +to the shared pool. The shared pool offers the same synchronization guarantees +as the segment manager. + +To use [classref boost::interprocess::node_allocator node_allocator], +you must include the following header: + +[c++] + + #include + +[classref boost::interprocess::node_allocator node_allocator] has the following declaration: + +[c++] + + namespace boost { + namespace interprocess { + + template + class node_allocator; + + } //namespace interprocess { + } //namespace boost { + +An example using [classref boost::interprocess::node_allocator node_allocator]: + +[import ../example/doc_node_allocator.cpp] +[doc_node_allocator] + +[endsect] + +[section:private_node_allocator private_node_allocator: a private segregated storage] + +As said, the node_allocator shares a common segregated storage between +node_allocators that allocate objects of the same size and this optimizes +memory usage. However, it needs a unique/named object construction feature +so that this sharing can be possible. Also +imposes a synchronization overhead per node allocation because of this share. +Sometimes, the unique object service is not available (for example, when +building index types to implement the named allocation service itself) or the +synchronization overhead is not acceptable. Many times the programmer wants to +make sure that the pool is destroyed when the allocator is destroyed, to free +the memory as soon as possible. + +So [*private_node_allocator] uses the same segregated storage as `node_allocator`, +but each [*private_node_allocator] has its own segregated storage pool. No synchronization +is used when allocating nodes, so there is far less overhead for an operation +that usually involves just a few pointer operations when allocating and +deallocating a node. + +[*Equality:] Two [classref boost::interprocess::private_node_allocator private_node_allocator] +instances [*never] compare equal. Memory allocated with one allocator [*can't] be +deallocated with another one. + +[*Allocation thread-safety:] Allocation and deallocation are [*not] thread-safe. + +To use [classref boost::interprocess::private_node_allocator private_node_allocator], +you must include the following header: + +[c++] + + #include + +[classref boost::interprocess::private_node_allocator private_node_allocator] +has the following declaration: + +[c++] + + namespace boost { + namespace interprocess { + + template + class private_node_allocator; + + } //namespace interprocess { + } //namespace boost { + +An example using [classref boost::interprocess::private_node_allocator private_node_allocator]: + +[import ../example/doc_private_node_allocator.cpp] +[doc_private_node_allocator] + +[endsect] + +[section:cached_node_allocator cached_node_allocator: caching nodes to avoid overhead] + +The total node sharing of [classref boost::interprocess::node_allocator node_allocator] can impose a high overhead for some +applications and the minimal synchronization overhead of [classref boost::interprocess::private_node_allocator private_node_allocator] +can impose a unacceptable memory waste for other applications. + +To solve this, [*Boost.Interprocess] offers an allocator, +[classref boost::interprocess::cached_node_allocator cached_node_allocator], that +allocates nodes from the common pool but caches some of them privately so that following +allocations have no synchronization overhead. When the cache is full, the allocator +returns some cached nodes to the common pool, and those will be available to other +allocators. + +[*Equality:] Two [classref boost::interprocess::cached_node_allocator cached_node_allocator] +instances constructed with the same segment manager compare equal. If an instance is +created using copy constructor, that instance compares equal with the original one. + +[*Allocation thread-safety:] Allocation and deallocation are [*not] thread-safe. + +To use [classref boost::interprocess::cached_node_allocator cached_node_allocator], +you must include the following header: + +[c++] + + #include + +[classref boost::interprocess::cached_node_allocator cached_node_allocator] +has the following declaration: + +[c++] + + namespace boost { + namespace interprocess { + + template + class cached_node_allocator; + + } //namespace interprocess { + } //namespace boost { + +A [classref boost::interprocess::cached_node_allocator cached_node_allocator] instance +and a [classref boost::interprocess::node_allocator node_allocator] instance +share the same pool if both instances receive the same template parameters. This means +that nodes returned to the shared pool by one of them can be reused by the other. +Please note that this does not mean that both allocators compare equal, this is just +information for programmers that want to maximize the use of the pool. + +[classref boost::interprocess::cached_node_allocator cached_node_allocator], offers +additional functions to control the cache (the cache can be controlled per instance): + +* `void set_max_cached_nodes(std::size_t n)`: Sets the maximum cached nodes limit. + If cached nodes reach the limit, some are returned to the shared pool. + +* `std::size_t get_max_cached_nodes() const`: Returns the maximum cached nodes limit. + +* `void deallocate_cache()`: Returns the cached nodes to the shared pool. + +An example using [classref boost::interprocess::cached_node_allocator cached_node_allocator]: + +[import ../example/doc_cached_node_allocator.cpp] +[doc_cached_node_allocator] + +[endsect] +[endsect] + +[section:stl_allocators_adaptive Adaptive pool node allocators] + +Node allocators based on simple segregated storage algorithm are both +space-efficient and fast but they have a problem: they only can grow. Every allocated +node avoids any payload to store additional data and that leads to the following limitation: +when a node is deallocated, it's stored in a free list of nodes but memory is not +returned to the segment manager so a deallocated +node can be only reused by other containers using the same node pool. + +This behaviour can be problematic if several containers use +[classref boost::interprocess::node_allocator] to temporarily allocate a lot +of objects but they end storing a few of them: the node pool will be full of nodes +that won't be reused wasting memory from the segment. + +Adaptive pool based allocators trade some space (the overhead can be as low as 1%) +and performance (aceptable for many applications) with the ability to return free chunks +of nodes to the memory segment, so that they can be used by any other container or managed +object construction. To know the details of the implementation of +of "adaptive pools" see the +[link interprocess.architecture_2.implementation_adaptive_pools Implementation of [*Boost.Intrusive] adaptive pools] +section. + +Like with segregated storage based node allocators, Boost.Interprocess offers +3 new allocators: [classref boost::interprocess::adaptive_pool adaptive_pool], +[classref boost::interprocess::private_adaptive_pool private_adaptive_pool], +[classref boost::interprocess::cached_adaptive_pool cached_adaptive_pool]. + +[section:adaptive_allocators_common Additional parameters and functions of adaptive pool node allocators] + +[classref boost::interprocess::adaptive_pool adaptive_pool], +[classref boost::interprocess::private_adaptive_pool private_adaptive_pool] and +[classref boost::interprocess::cached_adaptive_pool cached_adaptive_pool] implement +the standard allocator interface and the functions explained in the +[link interprocess.allocator_introduction.allocator_properties Properties of Boost.Interprocess allocators]. + +All these allocators are templatized by 4 parameters: + +* `class T`: The type to be allocated. +* `class SegmentManager`: The type of the segment manager that will be passed in the constructor. +* `std::size_t NodesPerChunk`: The number of nodes that a memory chunk will contain. + This value will define the size of the memory the pool will request to the + segment manager when the pool runs out of nodes. This parameter has a default value. +* `std::size_t MaxFreeChunks`: The maximum number of free chunks that the pool + will hold. If this limit is reached the pool returns the chunks to the segment manager. + This parameter has a default value. + +These allocators also offer the `deallocate_free_chunks()` function. This function will +traverse all the memory chunks of the pool and will return to the managed memory segment +the free chunks of memory. This function is much faster than for segregated storage +allocators, because the adaptive pool algorithm offers constant-time access to free +chunks. + +[endsect] + +[section:adaptive_pool adaptive_pool: a process-shared adaptive pool] + +Just like [classref boost::interprocess::node_allocator node_allocator] +a global, process-thread pool is used for each node size. In the +initialization, [classref boost::interprocess::adaptive_pool adaptive_pool] +searches the pool in the segment. If it is not preset, it builds one. +The adaptive pool, is created using a unique name. +The adaptive pool it is also shared between +all node_allocators that allocate objects of the same size, for example, +[*adaptive_pool] and [*adaptive_pool]. + +The common adaptive pool is destroyed when all the allocators attached +to the pool are destroyed. + +[*Equality:] Two [classref boost::interprocess::adaptive_pool adaptive_pool] instances +constructed with the same segment manager compare equal. If an instance is +created using copy constructor, that instance compares equal with the original one. + +[*Allocation thread-safety:] Allocation and deallocation are implemented as calls +to the shared pool. The shared pool offers the same synchronization guarantees +as the segment manager. + +To use [classref boost::interprocess::adaptive_pool adaptive_pool], +you must include the following header: + +[c++] + + #include + +[classref boost::interprocess::adaptive_pool adaptive_pool] has the following declaration: + +[c++] + + namespace boost { + namespace interprocess { + + template + class adaptive_pool; + + } //namespace interprocess { + } //namespace boost { + +An example using [classref boost::interprocess::adaptive_pool adaptive_pool]: + +[import ../example/doc_adaptive_pool.cpp] +[doc_adaptive_pool] + +[endsect] + +[section:private_adaptive_pool private_adaptive_pool: a private adaptive pool] + +Just like [classref boost::interprocess::private_node_allocator private_node_allocator] +owns a private segregated storage pool, +[classref boost::interprocess::private_adaptive_pool private_adaptive_pool] owns +its own adaptive pool. If the user wants to avoid the excessive node allocation +synchronization overhead in a container +[classref boost::interprocess::private_adaptive_pool private_adaptive_pool] +is a good choice. + +[*Equality:] Two [classref boost::interprocess::private_adaptive_pool private_adaptive_pool] +instances [*never] compare equal. Memory allocated with one allocator [*can't] be +deallocated with another one. + +[*Allocation thread-safety:] Allocation and deallocation are [*not] thread-safe. + +To use [classref boost::interprocess::private_adaptive_pool private_adaptive_pool], +you must include the following header: + +[c++] + + #include + +[classref boost::interprocess::private_adaptive_pool private_adaptive_pool] +has the following declaration: + +[c++] + + namespace boost { + namespace interprocess { + + template + class private_adaptive_pool; + + } //namespace interprocess { + } //namespace boost { + +An example using [classref boost::interprocess::private_adaptive_pool private_adaptive_pool]: + +[import ../example/doc_private_adaptive_pool.cpp] +[doc_private_adaptive_pool] + +[endsect] + +[section:cached_adaptive_pool boost::interprocess::cached_adaptive_pool: Avoiding synchronization overhead] + +Adaptive pools have also a cached version. In this allocator the allocator caches +some nodes to avoid the synchronization and bookeeping overhead of the shared +adaptive pool. +[classref boost::interprocess::cached_adaptive_pool cached_adaptive_pool] +allocates nodes from the common adaptive pool but caches some of them privately so that following +allocations have no synchronization overhead. When the cache is full, the allocator +returns some cached nodes to the common pool, and those will be available to other +[classref boost::interprocess::cached_adaptive_pool cached_adaptive_pools] or +[classref boost::interprocess::adaptive_pool adaptive_pools] of the same managed segment. + +[*Equality:] Two [classref boost::interprocess::cached_adaptive_pool cached_adaptive_pool] +instances constructed with the same segment manager compare equal. If an instance is +created using copy constructor, that instance compares equal with the original one. + +[*Allocation thread-safety:] Allocation and deallocation are [*not] thread-safe. + +To use [classref boost::interprocess::cached_adaptive_pool cached_adaptive_pool], +you must include the following header: + +[c++] + + #include + +[classref boost::interprocess::cached_adaptive_pool cached_adaptive_pool] +has the following declaration: + +[c++] + + namespace boost { + namespace interprocess { + + template + class cached_adaptive_pool; + + } //namespace interprocess { + } //namespace boost { + +A [classref boost::interprocess::cached_adaptive_pool cached_adaptive_pool] instance +and an [classref boost::interprocess::adaptive_pool adaptive_pool] instance +share the same pool if both instances receive the same template parameters. This means +that nodes returned to the shared pool by one of them can be reused by the other. +Please note that this does not mean that both allocators compare equal, this is just +information for programmers that want to maximize the use of the pool. + +[classref boost::interprocess::cached_adaptive_pool cached_adaptive_pool], offers +additional functions to control the cache (the cache can be controlled per instance): + +* `void set_max_cached_nodes(std::size_t n)`: Sets the maximum cached nodes limit. + If cached nodes reach the limit, some are returned to the shared pool. + +* `std::size_t get_max_cached_nodes() const`: Returns the maximum cached nodes limit. + +* `void deallocate_cache()`: Returns the cached nodes to the shared pool. + +An example using [classref boost::interprocess::cached_adaptive_pool cached_adaptive_pool]: + +[import ../example/doc_cached_adaptive_pool.cpp] +[doc_cached_adaptive_pool] + +[endsect] + [endsect] [section:containers_explained Interprocess and containers in managed memory segments] @@ -4673,61 +4070,63 @@ allocators. Until STL implementations handle allocator::pointer typedefs in a generic way, [*Boost.Interprocess] offers the following classes: -* [*boost:interprocess::vector] is the implementation of std::vector ready +* [*boost:interprocess::vector] is the implementation of `std::vector` ready to be used in managed memory segments like shared memory. To use it include: [c++] #include -* [*boost:interprocess::deque] is the implementation of std::deque ready +* [*boost:interprocess::deque] is the implementation of `std::deque` ready to be used in managed memory segments like shared memory. To use it include: [c++] #include -* [boost:interprocess::list] is the implementation of std::list ready +* [classref boost::interprocess::list list] is the implementation of `std::list` ready to be used in managed memory segments like shared memory. To use it include: [c++] #include -* [boost:interprocess::slist] is the implementation of SGI's slist container (singly linked list) ready +* [classref boost::interprocess::slist slist] is the implementation of SGI's `slist` container (singly linked list) ready to be used in managed memory segments like shared memory. To use it include: [c++] #include -* [boost:interprocess::set/multiset/map/multimap] family is the implementation of +* [classref boost::interprocess::set set]/ + [classref boost::interprocess::multiset multiset]/ + [classref boost::interprocess::map map]/ + [classref boost::interprocess::multimap multimap] family is the implementation of std::set/multiset/map/multimap family ready to be used in managed memory segments like shared memory. To use them include: [c++] - #include #include - #include - #include + #include - -* [*boost:interprocess::flat_set/flat_multiset/flat_map/flat_multimap] classes are the +* [classref boost::interprocess::flat_set flat_set]/ + [classref boost::interprocess::flat_multiset flat_multiset]/ + [classref boost::interprocess::flat_map flat_map]/ + [classref boost::interprocess::flat_multimap flat_multimap] classes are the adaptation and extension of Andrei Alexandrescu's famous AssocVector class from Loki library, ready for the shared memory. These classes offer the same - functionality as std::set/multiset/map/multimap implemented with an ordered vector, + functionality as `std::set/multiset/map/multimap` implemented with an ordered vector, which has faster lookups than the standard ordered associative containers based on red-black trees, but slower insertions. To use it include: [c++] - #include #include - #include - #include + #include -* [*boost:interprocess::basic_string] is the implementation of std::basic_string ready +* [classref boost::interprocess::basic_string basic_string] + is the implementation of `std::basic_string` ready to be used in managed memory segments like shared memory. It's implemented using a vector-like contiguous storage, so it has fast c string conversion and can be used with the @@ -4748,55 +4147,8 @@ so that the container allocates the values in the managed memory segment. To place the container itself in shared memory, we construct it in the managed memory segment just like any other object with [*Boost.Interprocess]: -[/doc_cont.cpp] - -[c++] - - #include - #include - #include - - int main () - { - using namespace boost::interprocess; - - shared_memory_object::remove("MySharedMemory"); - //A managed shared memory where we can construct objects - //associated with a c-string - managed_shared_memory segment(create_only, - "MySharedMemory", //segment name - 65536); - - //Alias an STL-like allocator of ints that allocates ints from the segment - typedef allocator - ShmemAllocator; - - //Alias a vector that uses the previous STL-like allocator - typedef vector MyVector; - - int initVal[] = {0, 1, 2, 3, 4, 5, 6 }; - const int *begVal = initVal; - const int *endVal = initVal + sizeof(initVal)/sizeof(initVal[0]); - - //Initialize the STL-like allocator - const ShmemAllocator alloc_inst (segment.get_segment_manager()); - - //Construct the vector in the shared memory segment with the STL-like allocator - //from a range of iterators - MyVector *myvector = - segment.construct - ("MyVector")/*object name*/ - (begVal /*first ctor parameter*/, - endVal /*second ctor parameter*/, - alloc_inst /*third ctor parameter*/); - - //Use vector as your want - std::sort(myvector->rbegin(), myvector->rend()); - // . . . - //When done, destroy and delete vector from the segment - segment.destroy("MyVector"); - return 0; - } +[import ../example/doc_cont.cpp] +[doc_cont] These containers also show how easy is to create/modify an existing container making possible to place it in shared memory. @@ -4808,91 +4160,37 @@ an existing container making possible to place it in shared memory. [*Boost.Interprocess] containers are placed in shared memory/memory mapped files, etc... using two mechanisms [*at the same time]: -* [*Boost.Interprocess] `construct<>`, `find_or_construct<>`... functions. These +* [*Boost.Interprocess ]`construct<>`, `find_or_construct<>`... functions. These functions place a C++ object in the shared memory/memory mapped file. But this places only the object, but *not* the memory that this object may allocate dynamically. * Shared memory allocators. These allow allocating shared memory/memory mapped file portions so that containers can allocate dynamically fragments of memory to store - new inserted elements. + newly inserted elements. This means that to place any [*Boost.Interprocess] container (including -[*Boost.Interprocess] strings) in shared memory/memory mapped file all containers *must*: +[*Boost.Interprocess] strings) in shared memory or memory mapped files, +containers *must*: -* Define their template allocator parameter to a shared memory one. +* Define their template allocator parameter to a [*Boost.Interprocess] allocator. -* Every container constructor must take a shared memory allocator as parameter. +* Every container constructor must take the [*Boost.Interprocess] allocator as parameter. * You must use construct<>/find_or_construct<>... functions to place the container - in shared memory. + in the managed memory. -If you do the first two points but you don't use construct<>/find_or_construct<> +If you do the first two points but you don't use `construct<>` or `find_or_construct<>` you are creating a container placed *only* in your process but that allocates memory for contained types from shared memory/memory mapped file. Let's see an example: -[/doc_where_allocate.cpp] - -[c++] - - #include - #include - #include - #include - - int main () - { - using namespace boost::interprocess; - //Typedefs - typedef allocator - CharAllocator; - typedef basic_string, CharAllocator> - MyShmString; - typedef allocator - StringAllocator; - typedef vector - MyShmStringVector; - - //Open shared memory - shared_memory_object::remove("myshm"); - managed_shared_memory shm(create_only, "myshm", 10000); - - //Create allocators - CharAllocator charallocator (shm.get_segment_manager()); - StringAllocator stringallocator(shm.get_segment_manager()); - - //This string is in only in this process (the pointer pointing to the - //buffer that will hold the text is not in shared memory). - //But the buffer that will hold "this is my text" is allocated from - //shared memory - MyShmString mystring(charallocator); - mystring = "this is my text"; - - //This vector is only in this process (the pointer pointing to the - //buffer that will hold the MyShmString-s is not in shared memory). - //But the buffer that will hold 10 MyShmString-s is allocated from - //shared memory using StringAllocator. Since strings use a shared - //memory allocator (CharAllocator) the 10 buffers that hold - //"this is my text" text are also in shared memory. - MyShmStringVector myvector(stringallocator); - myvector.insert(myvector.begin(), 10, mystring); - - //This vector is fully constructed in shared memory. All pointers - //buffers are constructed in the same shared memory segment - //This vector can be safely accessed from other processes. - MyShmStringVector *myshmvector = - shm.construct("myshmvector")(stringallocator); - myshmvector->insert(myshmvector->begin(), 10, mystring); - - //Destroy vector. This will free all strings that the vector contains - shm.destroy_ptr(myshmvector); - return 0; - } +[import ../example/doc_where_allocate.cpp] +[doc_where_allocate] [endsect] -[section:stl_container_move_semantics Move semantics in Interprocess containers] +[section:containers_and_move_semantics Move semantics in Interprocess containers] [*Boost.Interprocess] containers support move semantics, which means that the contents of a container can be moved from a container two another one, without any copying. The @@ -4908,74 +4206,8 @@ To transfer the contents of a container to another one, use about functions supporting move-semantics, see the reference section of Boost.Interprocess containers: -[/doc_move_containers.cpp] - -[c++] - - #include - #include - #include - #include - #include - - int main () - { - using namespace boost::interprocess; - - //Typedefs - typedef managed_shared_memory::segment_manager SegmentManager; - typedef allocator CharAllocator; - typedef basic_string - ,CharAllocator> MyShmString; - typedef allocator StringAllocator; - typedef vector MyShmStringVector; - - //Remove old shared memory and create new one - shared_memory_object::remove("myshm"); - managed_shared_memory shm(create_only, "myshm", 10000); - - //Create allocators - CharAllocator charallocator (shm.get_segment_manager()); - StringAllocator stringallocator(shm.get_segment_manager()); - - //Create a vector of strings in shared memory. - MyShmStringVector *myshmvector = - shm.construct("myshmvector")(stringallocator); - - //Insert 50 strings in shared memory. The strings will be allocated - //only once and no string copy-constructor will be called when inserting - //strings, leading to a great performance. - MyShmString string_to_compare(charallocator); - string_to_compare = "this is a long, long, long, long, long, long, string..."; - - myshmvector->reserve(50); - for(int i = 0; i < 50; ++i){ - MyShmString move_me(string_to_compare); - //In the following line, no string copy-constructor will be called. - //"move_me"'s contents will be transferred to the string created in - //the vector - myshmvector->push_back(move(move_me)); - - //The source string is in default constructed state - assert(move_me.empty()); - - //The newly created string will be equal to the "move_me"'s old contents - assert(myshmvector->back() == string_to_compare); - } - - //Now erase a string... - myshmvector->pop_back(); - - //...And insert one in the first position. - //No string copy-constructor or assignments will be called, but - //move constructors and move-assignments. No memory allocation - //function will be called in this operations!! - myshmvector->insert(myshmvector->begin(), move(string_to_compare)); - - //Destroy vector. This will free all strings that the vector contains - shm.destroy_ptr(myshmvector); - return 0; - } +[import ../example/doc_move_containers.cpp] +[doc_move_containers] [endsect] @@ -5023,9 +4255,9 @@ Sometimes, the user wants to create simple objects, STL compatible containers, S strings and more, all in a single buffer. This buffer could be a big static buffer, a memory-mapped auxiliary device or any other user buffer. -This would allow a easy serialization, since we just have copy the buffer to duplicate -all the objects created in the original buffer, and this includes complex objects like -maps, lists or any user classes. [*Boost.Interprocess] offers classes to handle user +This would allow an easy serialization and we-ll just need to copy the buffer to duplicate +all the objects created in the original buffer, including complex objects like +maps, lists.... [*Boost.Interprocess] offers managed memory segment classes to handle user provided buffers that allow the same functionality as shared memory classes: [c++] @@ -5043,11 +4275,11 @@ provided buffers that allow the same functionality as shared memory classes: //All objects are constructed in a a user provided buffer // Names are c-strings, // Default memory management algorithm - // (simple_seq_fit with no mutexes and relative pointers) + // (rbtree_best_fit with no mutexes and relative pointers) // Name-object mappings are stored in the default index type (flat_map) typedef basic_managed_external_buffer < char, - simple_seq_fit, offset_ptr , + rbtree_best_fit >, flat_map_index > managed_external_buffer; @@ -5055,11 +4287,11 @@ provided buffers that allow the same functionality as shared memory classes: //All objects are constructed in a a user provided buffer // Names are wide-strings, // Default memory management algorithm - // (simple_seq_fit with no mutexes and relative pointers) + // (rbtree_best_fit with no mutexes and relative pointers) // Name-object mappings are stored in the default index type (flat_map) typedef basic_managed_external_buffer< wchar_t, - simple_seq_fit >, + rbtree_best_fit >, flat_map_index > wmanaged_external_buffer; @@ -5069,42 +4301,19 @@ To use a managed external buffer, you must include the following header: #include -Let's see an example of the use of these classes: +Let's see an example of the use of managed_external_buffer: -[c++] - - //Create the user memory who will store all objects - const int memsize = 65536; - static char static_buffer [memsize]; - - //Named (wide-string) new capable class - //Initializes the static buffer - wmanaged_external_buffer objects_in_user_memory - (create_only, static_buffer, memsize); - - //We optimize resources to create 100 named objects in the static buffer - objects_in_user_memory.reserve_named_objects(100); - - //Alias node allocator type - //This allocator will allocate memory inside the static buffer - typedef wmanaged_external_buffer::node_allocator_type - ::type node_allocator_t; - - //Alias a STL compatible list to be constructed in the static buffer - typedef boost::interprocess::list MyBufferList; - - //The list must be initialized with the allocator - MyBufferList *list = objects_in_user_memory.construct(L"MyList") - (objects_in_user_memory.get_segment_manager()); - - //All objects created with objects_in_user_memory will be stored in the static_buffer! - - //Destroy the whole list from the static buffer - objects_in_user_memory.destroy(L"MyList"); +[import ../example/doc_managed_external_buffer.cpp] +[doc_managed_external_buffer] [*Boost.Interprocess] STL compatible allocators can also be used to place STL compatible containers in the user segment. +[classref boost::interprocess::managed_external_buffer managed_external_buffer] can +be also useful to build small databases for embedded systems limiting the size of +the used memory to a predefined memory chunk, instead of letting the database +fragment the heap memory. + [endsect] [section:managed_heap_memory Managed Heap Memory: Boost.Interprocess machinery in heap memory] @@ -5130,11 +4339,11 @@ These are the classes: //All objects are constructed in a single buffer allocated via new[] // Names are c-strings, // Default memory management algorithm - // (simple_seq_fit with no mutexes and relative pointers) + // (rbtree_best_fit with no mutexes and relative pointers) // Name-object mappings are stored in the default index type (flat_map) typedef basic_managed_heap_memory < char, - simple_seq_fit, + rbtree_best_fit, flat_map_index > managed_heap_memory; @@ -5142,11 +4351,11 @@ These are the classes: //All objects are constructed in a single buffer allocated via new[] // Names are wide-strings, // Default memory management algorithm - // (simple_seq_fit with no mutexes and relative pointers) + // (rbtree_best_fit with no mutexes and relative pointers) // Name-object mappings are stored in the default index type (flat_map) typedef basic_managed_heap_memory< wchar_t, - simple_seq_fit, + rbtree_best_fit, flat_map_index > wmanaged_heap_memory; @@ -5156,37 +4365,10 @@ To use a managed heap memory, you must include the following header: #include -The use is exactly the same as before, except that memory is created by -the managed memory segment itself using dynamic (new/delete) memory: - -[c++] - - //Create the heap memory who will store all objects - const int memsize = 65536; - - //Managed memory segment built above heap memory (new/delete) - wmanaged_heap_memory objects_in_heap_memory(memsize); - - //We optimize resources to create 100 named objects in the dynamic buffer - objects_in_heap_memory.reserve_named_objects(100); - - //Alias node allocator type - //This allocator will allocate memory inside the dynamic buffer - typedef wmanaged_heap_memory::node_allocator_type - ::type node_allocator_t; - - //Alias a STL compatible list to be constructed in the dynamic buffer - typedef boost::interprocess::list MyHeapList; - - //The list must be initialized with the allocator - //since it has no default constructor - MyHeapList *heaplist = objects_in_heap_memory.construct(L"MyList") - (objects_in_heap_memory.get_segment_manager()); - - //All objects created with objects_in_user_memory will be stored in the static_buffer! - - //Destroy the whole list from the dynamic buffer - objects_in_heap_memory.destroy(L"MyList"); +The use is exactly the same as +[classref boost::interprocess::managed_external_buffer], +except that memory is created by +the managed memory segment itself using dynamic (new/delete) memory. [*basic_managed_heap_memory] also offers a `grow(std::size_t extra_bytes)` function that tries to resize internal heap memory so that we have room for more objects. @@ -5196,69 +4378,8 @@ To be able to use this function, all pointers constructed in the heap buffer tha point to objects in the heap buffer must be relative pointers (for example `offset_ptr`). Otherwise, the result is undefined. Here is an example: -[c++] - - #include - #include - #include - #include - - using namespace boost::interprocess; - typedef list > - MyList; - - int main () - { - //We will create a buffer of 1000 bytes to store a list - managed_heap_memory heap_memory(1000); - - MyList * mylist = heap_memory.construct("MyList") - (heap_memory.get_segment_manager()); - - //Obtain handle, that identifies the list in the buffer - managed_heap_memory::handle_t list_handle = heap_memory.get_handle_from_address(mylist); - - //Fill list until there is no more memory in the buffer - try{ - while(1) { - mylist->insert(mylist->begin(), 0); - } - } - catch(const bad_alloc &){ - //memory is full - } - //Let's obtain the size of the list - std::size_t old_size = mylist->size(); - - //To make the list bigger, let's increase the heap buffer - //in 1000 bytes more. - heap_memory.grow(1000); - - //If memory has been reallocated, the old pointer is invalid, so - //use previously obtained handle to find the new pointer. - mylist = static_cast - (heap_memory.get_address_from_handle(list_handle)); - - //Fill list until there is no more memory in the buffer - try{ - while(1) { - mylist->insert(mylist->begin(), 0); - } - } - catch(const bad_alloc &){ - //memory is full - } - - //Let's obtain the new size of the list - std::size_t new_size = mylist->size(); - - assert(new_size > old_size); - - //Destroy list - heap_memory.destroy_ptr(mylist); - - return 0; - } +[import ../example/doc_managed_heap_memory.cpp] +[doc_managed_heap_memory] [endsect] @@ -5290,136 +4411,16 @@ the following example shows how a message queue can be used to serialize a whole database constructed in a memory buffer using [*Boost.Interprocess], send the database through a message queue and duplicated in another buffer: -[c++] - - //This test creates a in memory data-base using Interprocess machinery and - //serializes it through a message queue. Then rebuilds the data-base in - //another buffer and checks it against the original data-base - bool test_serialize_db() - { - //Typedef data to create a Interprocess map - typedef std::pair MyPair; - typedef std::less MyLess; - typedef node_allocator - node_allocator_t; - typedef map, - node_allocator_t> - MyMap; - - //Some constants - const std::size_t BufferSize = 65536; - const std::size_t MaxMsgSize = 100; - - //Allocate a memory buffer to hold the destiny database using vector - std::vector buffer_destiny(BufferSize, 0); - - message_queue::remove("message_queue"); - //Create the message-queues - message_queue mq1(create_only, "message_queue", 1, MaxMsgSize); - - //Open previously created message-queue simulating other process - message_queue mq2(open_only, "message_queue"); - - //A managed heap memory to create the origin database - managed_heap_memory db_origin(buffer_destiny.size()); - - //Construct the map in the first buffer - MyMap *map1 = db_origin.construct("MyMap") - (MyLess(), - db_origin.get_segment_manager()); - if(!map1) - return false; - - //Fill map1 until is full - try{ - std::size_t i = 0; - while(1){ - (*map1)[i] = i; - ++i; - } - } - catch(boost::interprocess::bad_alloc &){} - - //Data control data sending through the message queue - std::size_t sent = 0; - std::size_t recvd = 0; - std::size_t total_recvd = 0; - unsigned int priority; - - //Send whole first buffer through the mq1, read it - //through mq2 to the second buffer - while(1){ - //Send a fragment of buffer1 through mq1 - std::size_t bytes_to_send = MaxMsgSize < (db_origin.get_size() - sent) ? - MaxMsgSize : (db_origin.get_size() - sent); - mq1.send( &static_cast(db_origin.get_address())[sent] - , bytes_to_send - , 0); - sent += bytes_to_send; - //Receive the fragment through mq2 to buffer_destiny - mq2.receive( &buffer_destiny[total_recvd] - , BufferSize - recvd - , recvd - , priority); - total_recvd += recvd; - - //Check if we have received all the buffer - if(total_recvd == BufferSize){ - break; - } - } - - //The buffer will contain a copy of the original database - //so let's interpret the buffer with managed_external_buffer - managed_external_buffer db_destiny(open_only, &buffer_destiny[0], BufferSize); - - //Let's find the map - std::pair ret = db_destiny.find("MyMap"); - MyMap *map2 = ret.first; - - //Check if we have found it - if(!map2){ - return false; - } - - //Check if it is a single variable (not an array) - if(ret.second != 1){ - return false; - } - - //Now let's compare size - if(map1->size() != map2->size()){ - return false; - } - - //Now let's compare all db values - for(std::size_t i = 0, num_elements = map1->size(); i < num_elements; ++i){ - if((*map1)[i] != (*map2)[i]){ - return false; - } - } - - //Destroy maps from db-s - db_origin.destroy_ptr(map1); - db_destiny.destroy_ptr(map2); - - return true; - } +[import ../test/message_queue_test.cpp] +[message_queue_test_test_serialize_db] [endsect] [endsect] -[section:customizing_boost_interprocess Customizing Boost.Interprocess] +[section:memory_algorithms Boost.Interprocess memory allocation algorithms] -[section:custom_interprocess_alloc Writing a new shared memory allocation algorithm] - -Interprocess by default, uses a simple, space-friendly allocation algorithm implemented -by the class simple_seq_fit: - -[section:simple_seq_fit simple_seq_fit: Default shared memory management algorithm] +[section:simple_seq_fit simple_seq_fit: A simple shared memory management algorithm] The algorithm is a variation of sequential fit using singly linked list of free memory buffers. The algorithm is based @@ -5437,18 +4438,19 @@ always to the first block: [c++] - simple_seq_fit extra free_block 1 free_block 2 free_block 3 - header block_ctrl usr block_ctrl usr block_ctrl usr - ____________ _____ ___________________ ___________________ ___________________ - | | | | | | | | | | | | | - | free | ctrl| |extra| | next | size | mem | | next | size | mem | | next | size | mem | - |____________| |_____| |_____________|_____| |_____________|_____| |_____________|_____| - | | | | | | | - |__>__>__>__> _> _| |__>__>__>__>__>__| |__>__>__>__>__>__| | - | | - |_<_<_<_<_<_<_<_<_<_<_<_<_<_<_<_<_<_<_<_<_<_<_<_| - + simple_seq_fit memory layout: + main extra allocated free_block_1 allocated free_block_2 allocated free_block_3 + header header block ctrl usr block ctrl usr block ctrl usr + _________ _____ _________ _______________ _________ _______________ _________ _______________ + | || || || | || || | || || | | + |free|ctrl||extra|| ||next|size| mem || ||next|size| mem || ||next|size| mem | + |_________||_____||_________||_________|_____||_________||_________|_____||_________||_________|_____| + | | | | | | | + |_>_>_>_>_>_>_>_>_>_>_>_>_| |_>_>_>_>_>_>_>_>_>_>_>_>_| |_>_>_>_>_>_>_>_>_>_>_>_| | + | | + |_<_<_<_<_<_<_<_<_<_<_<_<_<_<_<_<_<_<_<_<_<_<_<_<_<_<_<__| + When a user requests N bytes of memory, the allocator traverses the free block list looking for a block large enough. If the "mem" part of the block has the same @@ -5470,82 +4472,844 @@ is measured in multiples of "basic_size" bytes. The basic size will be the size of the control block aligned to machine most restrictive alignment. -[c++] +This algorithm is a low size overhead algorithm suitable for simple allocation +schemes. This algorithm should only be used when size is a major concern, because +the performance of this algorithm suffers when the memory is fragmented. This +algorithm has linear allocation and deallocation time, so when the number +of allocations is high, the user should use a more performance-friendly algorithm. - /*!This class implements the simple sequential fit algorithm with a simply - linked list of free buffers.*/ - template - class simple_seq_fit : private boost::noncopyable - { - private: - - /*!Block control stucture*/ - struct block_ctrl - { - /*!Offset pointer to the next block. This pointer - can't be null, since it's a diff pointer.*/ - offset_ptr next; - /*!This block's memory size (including block_ctrl - header) in BasicSize units*/ - std::size_t size; - }; - - /*...*/ - - public: - /*!Shared interprocess_mutex family used for the rest of the interprocess framework*/ - typedef MutexFamily mutex_family; - /*!the pointer type to be used for the rest of the interprocess framework*/ - typedef VoidPointer void_pointer; - - public: - /*!Constructor. "size" is the total size of the maanged memory segment, - "extra_hdr_bytes" indicates the extra bytes after the sizeof(simple_seq_fit) - that the allocator should not use at all.*/ - simple_seq_fit (std::size_t size, std::size_t extra_hdr_bytes); - /*!Obtains the minimium size needed by the algorithm*/ - static std::size_t get_min_size (std::size_t extra_hdr_bytes); - /*!Allocates bytes, returns 0 if there is not more memory*/ - void* allocate (std::size_t nbytes); - /*!Deallocates previously allocated bytes*/ - void deallocate (void *adr); - /*!Returns the size of the memory segment*/ - std::size_t get_size() const; - /*!Increases managed memory in extra_size bytes more*/ - void grow(std::size_t extra_size); - /*...*/ - }; - -Let's explain these structs: - -* [*simple_seq_fit] is the main control block of the allocator. - -* The [*extra_hdr_bytes] memory comes just after simple_seq_fit object. - This memory will be used by other classes to write more control - data at fixed position. - -* [*block_ctrl] is the structure which controls a free block - in memory. It contains the size of the free block (in aligned - sizeof (block_ctrl) units, called basic_size, as we've - said before) and an offset pointer to the next free block - in the shared memory segment. The number of bytes returned - by the allocator will be multiple of basic_size bytes to - maintain the alignment requirements. +In most 32 systems, with 8 byte alignment, "basic_size" is 8 bytes. +This means that an allocation request of 1 byte leads to +the creation of a 16 byte block, where 8 bytes are available to the user. +The allocation of 8 bytes leads also to the same 16 byte block. [endsect] -[section:custom_alloc_algo How to implement you own algorithm] +[section:rbtree_best_fit rbtree_best_fit: Best-fit logarithmic-time complexity allocation] + +This algorithm is an advanced algorithm using red-black trees to sort the free +portions of the memory segment by size. This allows logarithmic complexity +allocation. Apart from this, a doubly-linked list of all portions of memory +(free and allocated) is maintained to allow constant-time access to previous +and next blocks when doing merging operations. + +The data used to create the red-black tree of free nodes is overwritten by the user +since it's no longer used once the memory is allocated. This maintains the memory +size overhead down to the doubly linked list overhead, which is pretty small (two pointers). +Basically this is the scheme: + +[c++] + + rbtree_best_fit memory layout: + + main allocated block free block allocated block free block + header + _______________ _______________ _________________________________ _______________ _________________________________ + | || | || | | || | || | | | + | main header ||next|prev| mem ||next|prev|left|right|parent| mem ||next|prev| mem ||next|prev|left|right|parent| mem | + |_______________||_________|_____||_________|_________________|_____||_________|_____||_________|_________________|_____| + + +This allocation algorithm is pretty fast and scales well with big shared memory +segments and big number of allocations. To form a block a minimum memory size is needed: +the sum of the doubly linked list and the red-black tree control data. +The size of a block is measured in multiples of the most restrictive alignment value. + +In most 32 systems with 8 byte alignment the minimum size of a block is 24 byte. +When a block is allocated the control data related to the red black tree +is overwritten by the user (because it's only needed for free blocks). + +In those systems a 1 byte allocation request means that: + +* 24 bytes of memory from the segment are used to form a block. +* 16 bytes of them are usable for the user. + +For really small allocations (<= 8 bytes), this algorithm wastes more memory than the +simple sequential fit algorithm (8 bytes more). +For allocations bigger than 8 bytes the memory overhead is exactly the same. +This is the default allocation algorithm in [*Boost.Interprocess] managed memory +segments. + + +[endsect] + +[endsect] + +[section:streams Direct iostream formatting: vectorstream and bufferstream] + +Shared memory, memory-mapped files and all [*Boost.Interprocess] mechanisms are focused +on efficiency. The reason why shared memory is used is that it's the +fastest IPC mechanism available. When passing text-oriented messages through +shared memory, there is need to format the message. Obviously C++ offers +the iostream framework for that work. + +Some programmers appreciate the iostream safety and design for memory +formatting but feel that the stringstream family is far from efficient not +when formatting, but when obtaining formatted data to a string, or when +setting the string from which the stream will extract data. An example: + +[c++] + + //Some formatting elements + std::string my_text = "..."; + int number; + + //Data reader + std::istringstream input_processor; + + //This makes a copy of the string. If not using a + //reference counted string, this is a serious overhead. + input_processor.str(my_text); + + //Extract data + while(/*...*/){ + input_processor >> number; + } + + //Data writer + std::ostringstream output_processor; + + //Write data + while(/*...*/){ + output_processor << number; + } + + //This returns a temporary string. Even with return-value + //optimization this is expensive. + my_text = input_processor.str(); + +The problem is even worse if the string is a shared-memory string, because +to extract data, we must copy the data first from shared-memory to a +std::string and then to a stringstream. To encode data in a shared-memory +string we should copy data from a stringstream to a std::string and then +to the shared-memory string. + +Because of this overhead, [*Boost.Interprocess] offers a way to format memory-strings +(in shared memory, memory mapped files or any other memory segment) that +can avoid all unneeded string copy and memory allocation/deallocation, while +using all iostream facilities. [*Boost.Interprocess] *vectorstream* and *bufferstream* implement +vector-based and fixed-size buffer based storage support for iostreams and +all the formatting/locale hard work is done by standard std::basic_streambuf<> +and std::basic_iostream<> classes. + +[section:vectorstream Formatting directly in your character vector: vectorstream] + +The *vectorstream* class family (*basic_vectorbuf*, *basic_ivectorstream* +,*basic_ovectorstream* and *basic_vectorstream*) is an efficient way to obtain +formatted reading/writing directly in a character vector. This way, if +a shared-memory vector is used, data is extracted/written from/to the shared-memory +vector, without additional copy/allocation. We can see the declaration of +basic_vectorstream here: + + /*!A basic_iostream class that holds a character vector specified by CharVector + template parameter as its formatting buffer. The vector must have + contiguous storage, like std::vector, boost::interprocess::vector or + boost::interprocess::basic_string*/ + template > + class basic_vectorstream + : public std::basic_iostream + + { + public: + typedef CharVector vector_type; + typedef typename std::basic_ios + ::char_type char_type; + typedef typename std::basic_ios::int_type int_type; + typedef typename std::basic_ios::pos_type pos_type; + typedef typename std::basic_ios::off_type off_type; + typedef typename std::basic_ios::traits_type traits_type; + + /*!Constructor. Throws if vector_type default constructor throws.*/ + basic_vectorstream(std::ios_base::openmode mode + = std::ios_base::in | std::ios_base::out); + + /*!Constructor. Throws if vector_type(const Parameter ¶m) throws.*/ + template + basic_vectorstream(const Parameter ¶m, std::ios_base::openmode mode + = std::ios_base::in | std::ios_base::out); + + ~basic_vectorstream(){} + + //Returns the address of the stored stream buffer. + basic_vectorbuf* rdbuf() const; + + /*!Swaps the underlying vector with the passed vector. + This function resets the position in the stream. + Does not throw.*/ + void swap_vector(vector_type &vect); + + /*!Returns a const reference to the internal vector. + Does not throw.*/ + const vector_type &vector() const; + + /*!Preallocates memory from the internal vector. + Resets the stream to the first position. + Throws if the internals vector's memory allocation throws.*/ + void reserve(typename vector_type::size_type size); + }; + +The vector type is templatized, so that we can use any type of vector: +[*std::vector], [classref boost::interprocess::vector].... But the storage must be *contiguous*, +we can't use a deque. We can even use *boost::interprocess::basic_string*, since it has a +vector interface and it has contiguous storage. *We can't use std::string*, because +although some std::string implementation are vector-based, others can have +optimizations and reference-counted implementations. + +The user can obtain a const reference to the internal vector using +`vector_type vector() const` function and he also can swap the internal vector +with an external one calling `void swap_vector(vector_type &vect)`. +The swap function resets the stream position. +This functions allow efficient methods to obtain the formatted data avoiding +all allocations and data copies. + +Let's see an example to see how to use vectorstream: + +[import ../example/doc_vectorstream.cpp] +[doc_vectorstream] + +[endsect] + +[section:bufferstream Formatting directly in your character buffer: bufferstream] + +As seen, vectorstream offers an easy and secure way for efficient iostream +formatting, but many times, we have to read or write formatted data from/to a +fixed size character buffer (a static buffer, a c-string, or any other). +Because of the overhead of stringstream, many developers (specially in +embedded systems) choose sprintf family. The *bufferstream* classes offer +iostream interface with direct formatting in a fixed size memory buffer with +protection against buffer overflows. This is the interface: + + /*!A basic_iostream class that uses a fixed size character buffer + as its formatting buffer.*/ + template > + class basic_bufferstream + : public std::basic_iostream + + { + public: // Typedefs + typedef typename std::basic_ios + ::char_type char_type; + typedef typename std::basic_ios::int_type int_type; + typedef typename std::basic_ios::pos_type pos_type; + typedef typename std::basic_ios::off_type off_type; + typedef typename std::basic_ios::traits_type traits_type; + + /*!Constructor. Does not throw.*/ + basic_bufferstream(std::ios_base::openmode mode + = std::ios_base::in | std::ios_base::out); + + /*!Constructor. Assigns formatting buffer. Does not throw.*/ + basic_bufferstream(CharT *buffer, std::size_t length, + std::ios_base::openmode mode + = std::ios_base::in | std::ios_base::out); + + /*!Returns the address of the stored stream buffer.*/ + basic_bufferbuf* rdbuf() const; + + /*!Returns the pointer and size of the internal buffer. + Does not throw.*/ + std::pair buffer() const; + + /*!Sets the underlying buffer to a new value. Resets + stream position. Does not throw.*/ + void buffer(CharT *buffer, std::size_t length); + }; + + //Some typedefs to simplify usage + typedef basic_bufferstream bufferstream; + typedef basic_bufferstream wbufferstream; + // ... + +While reading from a fixed size buffer, *bufferstream* activates endbit flag if +we try to read an address beyond the end of the buffer. While writing to a +fixed size buffer, *bufferstream* will active the badbit flag if a buffer overflow +is going to happen and disallows writing. This way, the fixed size buffer +formatting through *bufferstream* is secure and efficient, and offers a good +alternative to sprintf/sscanf functions. Let's see an example: + +[import ../example/doc_bufferstream.cpp] +[doc_bufferstream] + +As seen, *bufferstream* offers an efficient way to format data without any +allocation and extra copies. This is very helpful in embedded systems, or +formatting inside time-critical loops, where stringstream extra copies would +be too expensive. Unlike sprintf/sscanf, it has protection against buffer +overflows. As we know, according to the *Technical Report on C++ Performance*, +it's possible to design efficient iostreams for embedded platforms, so this +bufferstream class comes handy to format data to stack, static or shared memory +buffers. + +[endsect] + +[endsect] + +[section:interprocess_smart_ptr Boost.Interprocess ownership smart pointers] + +C++ users know the importance of ownership smart pointers when dealing with resources. +Boost offers a wide range of such type of pointers: `intrusive_ptr<>`, +`scoped_ptr<>`, `shared_ptr<>`... + +When building complex shared memory/memory mapped files structures, programmers +would like to use also the advantages of these smart pointers. The problem is that +Boost and C++ TR1 smart pointers are not ready to be used for shared memory. The cause +is that those smart pointers contain raw pointers and they use virtual functions, +something that is not possible if you want to place your data in shared memory. +The virtual function limitation makes even impossible to achieve the same level of +functionality of Boost and TR1 with [*Boost.Interprocess] smart pointers. + +Interprocess ownership smart pointers are mainly "smart pointers contaning smart pointers", +so we can specify the pointer type they contain. + +[section:intrusive_ptr Intrusive pointer] + +[classref boost::interprocess::intrusive_ptr] is the generalization of `boost::intrusive_ptr<>` +to allow non-raw pointers as intrusive pointer members. As the known +`boost::intrusive_ptr` we must specify the pointee type but we also must also specify +the pointer type to be stored in the intrusive_ptr: + +[c++] + + /*!The intrusive_ptr class template stores a pointer to an object + with an embedded reference count. intrusive_ptr is parameterized on + T (the type of the object pointed to) and VoidPointer(a void pointer type + that defines the type of pointer that intrusive_ptr will store). + intrusive_ptr defines a class with a T* member whereas + intrusive_ptr > defines a class with a offset_ptr member. + Relies on unqualified calls to: + + void intrusive_ptr_add_ref(T * p); + void intrusive_ptr_release(T * p); + + with (p != 0) + + The object is responsible for destroying itself.*/ + template + class intrusive_ptr + { + public: + /*!Provides the type of the internal stored pointer.*/ + typedef typename /*...*/ pointer; + /*!Provides the type of the stored pointer.*/ + typedef T element_type; + + /*!Constructor. Initializes internal pointer to 0. Does not throw*/ + intrusive_ptr(); + + /*!Constructor. Copies pointer and if "p" is not zero and + "add_ref" is true calls intrusive_ptr_add_ref(get_pointer(p)). + Does not throw*/ + intrusive_ptr(const pointer &p, bool add_ref = true); + + /*!Copy constructor. Copies the internal pointer and if "p" is not + zero calls intrusive_ptr_add_ref(get_pointer(p)). Does not throw*/ + intrusive_ptr(intrusive_ptr const & rhs); + + /*!Constructor from related. Copies the internal pointer and if "p" is not + zero calls intrusive_ptr_add_ref(get_pointer(p)). Does not throw*/ + template intrusive_ptr (intrusive_ptr const & rhs); + + /*!Destructor. If internal pointer is not 0, calls + intrusive_ptr_release(get_pointer(m_ptr)). Does not throw*/ + ~intrusive_ptr(); + + /*!Assignment operator. Equivalent to intrusive_ptr(r).swap(*this). + Does not throw*/ + intrusive_ptr & operator=(intrusive_ptr const & rhs); + + /*!Assignment from related. Equivalent to intrusive_ptr(r).swap(*this). + Does not throw*/ + template intrusive_ptr & operator= (intrusive_ptr const & rhs); + + /*!Assignment from pointer. Equivalent to intrusive_ptr(r).swap(*this). + Does not throw*/ + intrusive_ptr & operator=(pointer rhs); + + /*!Returns a reference to the internal pointer. Does not throw*/ + pointer &get(); + + /*!Returns a reference to the internal pointer. Does not throw*/ + const pointer &get() const; + + /*!Returns *get(). Does not throw*/ + T & operator*() const; + + /*!Returns *get(). Does not throw*/ + const pointer &operator->() const; + + /*!Returns get(). Does not throw*/ + pointer &operator->(); + + operator unspecified_bool_type () const; + + /*!Not operator. Does not throw*/ + bool operator! () const; + + /*!Exchanges the contents of the two smart pointers. Does not throw*/ + void swap(intrusive_ptr & rhs); + }; + +So `boost::interprocess::intrusive_ptr` is equivalent to +`boost::instrusive_ptr`. But if we want to place the intrusive_ptr in +shared memory we must specify a relative pointer type like +`boost::interprocess::intrusive_ptr >` + +[import ../example/doc_intrusive.cpp] +[doc_intrusive] + +[endsect] + +[section:scoped_ptr Scoped pointer] + +`boost::interprocess::scoped_ptr<>` is the big brother of `boost::scoped_ptr<>`, which +adds a custom deleter to specify how the pointer passed to the scoped_ptr must be destroyed. +Also, the `pointer` typedef of the deleter will specify the pointer type stored by scoped_ptr. + +[c++] + + /*!scoped_ptr stores a pointer to a dynamically allocated object. + The object pointed to is guaranteed to be deleted, either on destruction + of the scoped_ptr, or via an explicit reset. The user can avoid this + deletion using release(). + scoped_ptr is parameterized on T (the type of the object pointed to) and + Deleter (the functor to be executed to delete the internal pointer). + The internal pointer will be of the same pointer type as typename + Deleter::pointer type (that is, if typename Deleter::pointer is + offset_ptr, the internal pointer will be offset_ptr).*/ + template + class scoped_ptr + { + public: + + /*!Provides the type of the stored pointer.*/ + typedef T element_type; + + /*!Provides the type of the internal stored pointer.*/ + typedef /*...*/ pointer; + + /*!Constructs a scoped_ptr, storing a copy of p(which can be 0) and d. + Does not throw.*/ + explicit scoped_ptr(const pointer &p = 0, const Deleter &d = Deleter()); + + /*!If the stored pointer is not 0, destroys the object pointed to by the stored pointer. + calling the operator() of the stored deleter.*/ + ~scoped_ptr(); + + /*!Deletes the object pointed to by the stored pointer and then + stores a copy of p. Never throws*/ + void reset(const pointer &p = 0); + + /*!Deletes the object pointed to by the stored pointer and then + stores a copy of p and a copy of d.*/ + void reset(const pointer &p, const Deleter &d); + + /*!Assigns internal pointer as 0 and returns previous pointer. This will + avoid deletion on destructor*/ + pointer release(): + + /*!Returns a reference to the object pointed to by the stored pointer. + Never throws.*/ + reference operator*() const; + + /*!Returns the internal stored pointer. Never throws*/ + pointer &operator->(); + + /*!Returns the internal stored pointer. Never throws.*/ + const pointer &operator->() const; + + /*!Returns the stored pointer. Never throws.*/ + pointer & get(); + + /*!Returns the stored pointer. Never throws.*/ + const pointer & get() const; + + /*!Returns true if the stored pointer is 0. Never throws.*/ + bool operator! () const; + + /*!Exchanges the internal pointer and deleter with other scoped_ptr + Never throws.*/ + void swap(scoped_ptr & b); + }; + +`scoped_ptr<>` comes handy to implement *rollbacks* with exceptions: if an exception +is thrown or we call `return` in the scope of `scoped_ptr<>` the deleter is +automatically called so that *the deleter can be considered as a rollback* function. +If all goes well, we call `release()` member function to avoid rollback when +the `scoped_ptr` goes out of scope. + +[import ../example/doc_scoped_ptr.cpp] +[doc_scoped_ptr] + +[endsect] + +[endsect] + +[section:architecture Boost.Interprocess architecture and internals (I)] + +[section:basic_guidelines Basic guidelines] + +When building [*Boost.Interprocess] architecture, I took some basic guidelines that can be +resumed in these points: + +* [*Boost.Interprocess] should be portable at least in UNIX and Windows systems. That + means unifying not only interfaces but also behaviour. This is why + [*Boost.Interprocess] has chosen kernel or filesystem persistence for shared memory + and named synchronization mechanisms. Process persistence for shared memory is also + desirable but it's difficult to achieve in UNIX systems. + +* [*Boost.Interprocess] inter-process synchronization primitives should be equal to thread + synchronization primitives. [*Boost.Interprocess] aims to have an interface compatible + with the C++ standard thread API. + +* [*Boost.Interprocess] architecture should be modular, customizable but efficient. That's + why [*Boost.Interprocess] is based on templates and memory algorithms, index types, + mutex types and other classes are templatizable. + +* [*Boost.Interprocess] architecture should allow the same concurrency as thread based + programming. Different mutual exclusion levels are defined so that a process + can concurrently allocate raw memory when expanding a shared memory vector while another + process can be safely searching a named object. + +* [*Boost.Interprocess] containers know nothing about [*Boost.Interprocess]. All specific + behaviour is contained in the STL-like allocators. That allows STL vendors to slightly + modify (or better said, generalize) their standard container implementations and obtain + a fully std::allocator and boost::interprocess::allocator compatible container. This also + make [*Boost.Interprocess] containers compatible with standard algorithms. + +[*Boost.Interprocess] is built above 3 basic classes: a [*memory algorithm], a +[*segment manager] and a [*managed memory segment]: + +[endsect] + +[section:architecture_memory_algorithm The memory algorithm] + +The [*memory algorithm] is an object that is placed in the first bytes of a +shared memory/memory mapped file segment. The [*memory algorithm] can return +portions of that segment to users marking them as used and the user can return those +portions to the [*memory algorithm] so that the [*memory algorithm] mark them as free +again. There is an exception though: some bytes beyond the end of the memory +algorithm object, are reserved and can't be used for this dynamic allocation. +This "reserved" zone will be used to place other additional objects +in a well-known place. + +To sum up, a [*memory algorithm] has the same mission as malloc/free of +standard C library, but it just can return portions of the segment +where it is placed. The layout of a memory segment would be: + +[c++] + + Layout of the memory segment: + ____________ __________ ____________________________________________ + | | | | + | memory | reserved | The memory algorithm will return portions | + | algorithm | | of the rest of the segment. | + |____________|__________|____________________________________________| + + +The [*memory algorithm] takes care of memory synchronizations, just like malloc/free +guarantees that two threads can call malloc/free at the same time. This is usually +achieved placing a process-shared mutex as a member of the memory algorithm. Take +in care that the memory algorithm knows [*nothing] about the segment (if it is +shared memory, a shared memory file, etc.). For the memory algorithm the segment +is just a fixed size memory buffer. + +The [*memory algorithm] is also a configuration point for the rest of the +[*Boost.Interprocess] +framework since it defines two basic types as member typedefs: + +[c++] + + typedef /*implementation dependent*/ void_pointer; + typedef /*implementation dependent*/ mutex_family; + + +The `void_pointer` typedef defines the pointer type that will be used in the +[*Boost.Interprocess] framework (segment manager, allocators, containers). If the memory +algorithm is ready to be placed in a shared memory/mapped file mapped in different base +addresses, this pointer type will be defined as `offset_ptr` or a similar relative +pointer. If the [*memory algorithm] will be used just with fixed address mapping, +`void_pointer` can be defined as `void*`. + +The rest of the interface of a [*Boost.Interprocess] [*memory algorithm] is described in +[link interprocess.customizing_boost_interprocess.custom_interprocess_alloc Writing a new shared memory allocation algorithm] +section. As memory algorithm examples, you can see the implementations +[classref boost::interprocess::simple_seq_fit simple_seq_fit] or +[classref boost::interprocess::rbtree_best_fit rbtree_best_fit] classes. + +[endsect] + +[section:architecture_segment_manager The segment manager] + +The *segment manager*, is an object also placed in the first bytes of the +managed memory segment (shared memory, memory mapped file), that offers more +sofisticated services built above the [*memory algorithm]. How can [*both] the +segment manager and memory algorithm be placed in the beginning of the segment? +That's because the segment manager [*owns] the memory algorithm: The +truth is that the memory algorithm is [*embedded] in the segment manager: + + +[c++] + + The layout of managed memory segment: + _______ _________________ + | | | | + | some | memory | other |<- The memory algorithm considers + |members|algorithm|members| "other members" as reserved memory, so + |_______|_________|_______| it does not use it for dynamic allocation. + |_________________________|____________________________________________ + | | | + | segment manager | The memory algorithm will return portions | + | | of the rest of the segment. | + |_________________________|____________________________________________| + + +The [*segment manager] initializes the memory algorithm and tells the memory +manager that it should not use the memory where the rest of the +[*segment manager]'s member are placed for dynamic allocations. The +other members of the [*segment manager] are [*a recursive mutex] +(defined by the memory algorithm's [*mutex_family::recursive_mutex] typedef member), +and [*two indexes (maps)]: one to implement named allocations, and another one to +implement "unique instance" allocations. + +* The first index is a map with a pointer to a c-string (the name of the named object) + as a key and a structure with information of the dynamically allocated object + (the most importants being the address and the size of the object). + +* The second index is used to implement "unique instances" + and is basically the same as the first index, + but the name of the object comes from a `typeid(T).name()` operation. + +The memory needed to store [name pointer, object information] pairs in the index is +allocated also via the *memory algorithm*, so we can tell that internal indexes +are just like ordinary user objects built in the segment. The rest of the memory +to store the name of the object, the object itself, and meta-data for +destruction/deallocation is allocated using the *memory algorithm* in a single +`allocate()` call. + +As seen, the [*segment manager] knows [*nothing] about shared memory/memory mapped files. +The [*segment manager] itself does not allocate portions of the segment, +it just asks the *memory algorithm* to allocate the needed memory from the rest +of the segment. The [*segment manager] is a class built above the memory algorithm +that offers named object construction, unique instance constructions, and many +other services. + +The [*segment manager] is implemented in [*Boost.Interprocess] by +the [classref boost::interprocess::segment_manager segment_manager] class. + +[c++] + + template class IndexType> + class segment_manager; + +As seen, the segment manager is quite generic: we can specify the character type +to be used to identify named objects, we can specify the memory algorithm that will +control dynamically the portions of the memory segment, and we can specify +also the index type that will store the [name pointer, object information] mapping. +We can construct our own index types as explained in +[link interprocess.customizing_boost_interprocess.custom_indexes Building custom indexes] section. + +[endsect] + +[section:architecture_managed_memory Boost.Interprocess managed memory segments] + +The [*Boost.Interprocess] managed memory segments that construct the shared memory/memory +mapped file, place there the segment manager and forward the user requests to the +segment manager. For example, [classref boost::interprocess::basic_managed_shared_memory basic_managed_shared_memory] +is a [*Boost.Interprocess] managed memory segment that works with shared memory. +[classref boost::interprocess::basic_managed_mapped_file basic_managed_mapped_file] works with memory mapped files, etc... + +Basically, the interface of a [*Boost.Interprocess] managed memory segment is the same as +the [*segment manager] but it also offers functions to "open", "create", or "open or create" +shared memory/memory-mapped files segments and initialize all needed resources. +Managed memory segment classes are not built in shared memory or memory mapped files, they +are normal C++ classes that store a pointer to the segment manager (which is built +in shared memory or memory mapped files). + +Apart from this, managed memory segments offer specific functions: `managed_mapped_file` +offers functions to flush memory contents to the file, `managed_heap_memory` offers +functions to expand the memory, etc... + +Most of the functions of [*Boost.Interprocess] managed memory segments can be shared +between all managed memory segments, since many times they just forward the functions +to the segment manager. Because of this, +in [*Boost.Interprocess] all managed memory segments derive from a common class that +implements memory-independent (shared memory, memory mapped files) functions: +[@../../../../boost/interprocess/detail/managed_memory_impl.hpp +boost::interprocess::detail::basic_managed_memory_impl] + +Deriving from this class, [*Boost.Interprocess] implements several managed memory +classes, for different memory backends: + +* [classref boost::interprocess::basic_managed_shared_memory basic_managed_shared_memory] (for shared memory). +* [classref boost::interprocess::basic_managed_mapped_file basic_managed_mapped_file] (for memory mapped files). +* [classref boost::interprocess::basic_managed_heap_memory basic_managed_heap_memory] (for heap allocated memory). +* [classref boost::interprocess::basic_managed_external_buffer basic_managed_external_buffer] (for user provided external buffer). + +[endsect] +[endsect] + +[section:architecture_2 Boost.Interprocess architecture and internals (II)] + +[section:architecture_allocators Boost.Interprocess allocators] + +The [*Boost.Interprocess] STL-like allocators are fairly simple and follow the usual C++ +allocator approach. Normally, allocators for STL containers are based above new/delete +operators and above those, they implement pools, arenas and other allocation tricks. + +In [*Boost.Interprocess] allocators, the approach is similar, but all allocators are based +on the *segment manager*. The segment manager is the only one that provides from simple +memory allocation to named object creations. [*Boost.Interprocess] allocators always store +a pointer to the segment manager, so that they can obtain memory from the segment or share +a common pool between allocators. + +As you can imagine, the member pointers of the allocator are not a raw pointers, but +pointer types defined by the `segment_manager::void_pointer` type. Apart from this, +the `pointer` typedef of [*Boost.Interprocess] allocators is also of the same type of +`segment_manager::void_pointer`. + +This means that if our allocation algorithm defines `void_pointer` as `offset_ptr`, +`boost::interprocess::allocator` will store an `offset_ptr` +to point to the segment manager and the `boost::interprocess::allocator::pointer` type +will be `offset_ptr`. This way, [*Boost.Interprocess] allocators can be placed in the +memory segment managed by the segment manager, that is, shared memory, memory mapped files, +etc... + +[endsect] + +[section:implementation_segregated_storage_pools Implementation of [*Boost.Interprocess] segregated storage pools] + +Segregated storage pools are simple and follow the classic segregated storage algorithm. + +* The pool allocates chuncks of memory using the segment manager's raw memory + allocation functions. +* The chunk contains a pointer to form a singly linked list of chunks. The pool + will contain a pointer to the first chunk. +* The rest of the memory of the chunk is divided in nodes of the requested size and + no memory is used as payload for each node. Since the memory of a free node + is not used that memory is used to place a pointer to form a singly linked list of + free nodes. The pool has a pointer to the first free node. +* Allocating a node is just taking the first free node from the list. If the list + is empty, a new chunk is allocated, linked in the list of chunks and the new free + nodes are linked in the free node list. +* Deallocation returns the node to the free node list. +* When the pool is destroyed, the list of chunks is traversed and memory is returned + to the segment manager. + +The pool is implemented by the +[@../../../../boost/interprocess/allocators/detail/node_pool.hpp +private_node_pool and shared_node_pool] classes. + +[endsect] + +[section:implementation_adaptive_pools Implementation of [*Boost.Interprocess] adaptive pools] + +Adaptive pools are a variation of segregated lists but they have a more complicated +approach: + +* Instead of using raw allocation, the pool allocates [*aligned] chuncks of memory + using the segment manager. This is an [*essential] feature since a node can reach + its chunk information applying a simple mask to its address. + +* The chunks contains pointers to form a doubly linked list of chunks and + an additional pointer to create a singly linked list of free nodes placed + on that chunk. So unlike the segregated storage algorithm, the free list + of nodes is implemented [*per chunk]. + +* The pool maintains the chunks in increasing order of free nodes. This improves + locality and minimizes the dispersion of node allocations across the chunks + facilitating the creation of totally free chunks. + +* The pool has a pointer to the chunk with the minimum (but not zero) free nodes. + This chunk is called the "active" chunk. + +* Allocating a node is just returning the first free node of the "active" chunk. + The list of chunks is reordered according to the free nodes count. + The pointer to the "active" pool is updated if necessary. + +* If the pool runs out of nodes, a new chunk is allocated, and pushed back in the + list of chunks. The pointer to the "active" pool is updated if necessary. + +* Deallocation returns the node to the free node list of its chunk and updates + the "active" pool accordingly. + +* If the number of totally free chunks exceds the limit, chunks are returned + to the segment manager. + +* When the pool is destroyed, the list of chunks is traversed and memory is returned + to the segment manager. + +The adaptive pool is implemented by the +[@../../../../boost/interprocess/allocators/detail/adaptive_node_pool.hpp +private_adaptive_node_pool and adaptive_node_pool] classes. + +[endsect] + +[section:architecture_containers Boost.Interprocess containers] + +[*Boost.Interprocess] containers are standard conforming counterparts of STL containers +in `boost::interprocess` namespace, but with these little details: + +* [*Boost.Interprocess] STL containers don't assume that memory allocated with + an allocator can be deallocated with other allocator of + the same type. They always compare allocators with `operator==()` + to know if this is possible. + +* The pointers of the internal structures of the [*Boost.Interprocess] containers are + of the same type the `pointer` type defined by the allocator of the container. This + allows placing containers in managed memory segments mapped in different base addresses. + +[endsect] + +[endsect] + +[section:customizing_boost_interprocess Customizing Boost.Interprocess] + +[section:custom_interprocess_alloc Writing a new shared memory allocation algorithm] If the default algorithm does not satisfy user requirements, it's easy to provide different algorithms like bitmapping or -more advanced segregated lists to meet requirements. The characteristics -of your own algorithm: +more advanced segregated lists to meet requirements. The class implementing +the algorithm must be compatible with shared memory, so it shouldn't have any +virtual function or virtual inheritance or +any indirect base class with virtual function or inheritance. -* It shouldn't have any virtual function or virtual inheritance or - any indirect base class with virtual function or inheritance. +This is the interface to be implemented: -* I has to implement the same public functions and typedefs of -simple_seq_fit. +[c++] + + class my_algorithm + { + public: + + //!The mutex type to be used by the rest of Interprocess framework + typedef implementation_defined mutex_family; + + //!The pointer type to be used by the rest of Interprocess framework + typedef implementation_defined void_pointer; + + //!Constructor. "size" is the total size of the maanged memory segment, + //!"extra_hdr_bytes" indicates the extra bytes after the sizeof(my_algorithm) + //!that the allocator should not use at all. + my_algorithm (std::size_t size, std::size_t extra_hdr_bytes); + + //!Obtains the minimium size needed by the algorithm + static std::size_t get_min_size (std::size_t extra_hdr_bytes); + + //!Allocates bytes, returns 0 if there is not more memory + void* allocate (std::size_t nbytes); + + //!Deallocates previously allocated bytes + void deallocate (void *adr); + + //!Returns the size of the memory segment + std::size_t get_size() const; + + //!Increases managed memory in extra_size bytes more + void grow(std::size_t extra_size); + /*...*/ + }; Let's see the public typedefs to define: @@ -5589,27 +5353,27 @@ The user can specify the desired mutex family. typedef mutex_family mutex_family; -The new algorithm (let's call it *my_algorithm*) must implement the all the functions -that boost::interprocess::simple_seq_fit class offers: +The new algorithm (let's call it *my_algorithm*) must implement all the functions +that boost::interprocess::rbtree_best_fit class offers: -* The *my_algorithm* constructor must take 2 arguments: - * *size* indicates the total size of the managed memory segment, and - the *my_algorithm* object will be always constructed a at offset 0 +* [*my_algorithm]'s constructor must take 2 arguments: + * [*size] indicates the total size of the managed memory segment, and + [*my_algorithm] object will be always constructed a at offset 0 of the memory segment. - * The *extra_hdr_bytes* parameter indicates the number of bytes after - the offset sizeof(*my_algorithm*) that *my_algorithm* can't use at all. This extra + * The [*extra_hdr_bytes] parameter indicates the number of bytes after + the offset `sizeof(my_algorithm)` that [*my_algorithm] can't use at all. This extra bytes will be used to store additional data that should not be overwritten. - So, *my_algorithm* will be placed at address XXX of the memory segment, and will - manage the *[XXX + sizeof(my_algorithm) + extra_hdr_bytes, XXX + size)* range of + So, [*my_algorithm] will be placed at address XXX of the memory segment, and will + manage the [*[XXX + sizeof(my_algorithm) + extra_hdr_bytes, XXX + size)] range of the segment. * The [*get_min_size()] function should return the minimum space the algorithm - needs to be valid with the passed *extra_hdr_bytes* parameter. This function will + needs to be valid with the passed [*extra_hdr_bytes] parameter. This function will be used to check if the memory segment is big enough to place the algorithm there. * The [*allocate()] function must return 0 if there is no more available memory. - The memory returned by *my_algorithm* + The memory returned by [*my_algorithm] must be aligned to the most restrictive memory alignment of the system, for example, to the value returned by *boost::alignment_of::value*. This function should be executed with the synchronization capabilities offered @@ -5623,7 +5387,7 @@ that boost::interprocess::simple_seq_fit class offers: allocations. This function should offer the same synchronization as `allocate()`. * The [*size()] function will return the passed [*size] parameter in the constructor. - So, *my_algorithm* should store the size internally. + So, [*my_algorithm] should store the size internally. * The [*grow()] function will expand the managed memory by [*my_algorithm] in [*extra_size] bytes. So [*size()] function should return the updated size, @@ -5644,8 +5408,6 @@ That's it. Now we can create new managed shared memory that uses our new algorit [endsect] -[endsect] - [section:custom_allocators Building custom STL compatible allocators for Boost.Interprocess] If provided STL-like allocators don't satisfy user needs, the user @@ -5830,53 +5592,12 @@ will manage the index. `segment_manager` will define interesting internal types void reserve(std::size_t n); -For example, the default index type `flat_map_index` based in `boost::interprocess::flat_map` +For example, the index type `flat_map_index` based in `boost::interprocess::flat_map` is just defined as: -[c++] +[import ../../../boost/interprocess/indexes/flat_map_index.hpp] +[flat_map_index] - namespace boost { namespace interprocess { - - /*!Helper class to define typedefs from IndexTraits*/ - template - struct flat_map_index_aux - { - typedef typename MapConfig::key_type key_type; - typedef typename MapConfig::mapped_type mapped_type; - typedef typename MapConfig::segment_manager segment_manager; - typedef std::less key_less; - typedef std::pair value_type; - typedef allocator allocator_type; - typedef flat_map index_t; - }; - - /*!Index type based in flat_map. Just derives from flat_map and - defines the interface needed by the shared named object creation class.*/ - template - class flat_map_index - //Derive class from `flat_map` specialization - : public flat_map_index_aux::index_t - { - typedef flat_map_index_aux index_aux; - typedef typename index_aux::index_t base_type; - typedef typename index_aux::segment_manager segment_manager; - - public: - /*!Constructor. Takes a pointer to the - segment manager. Can throw*/ - flat_map_index(segment_manager *segment_mngr) - : base_type(typename index_aux::key_less(), - typename index_aux::allocator_type(segment_mngr)) - {} - - /*!This reserves memory to optimize the insertion of n - elements in the index*/ - void reserve(std::size_t n) - { base_type::reserve(n); } - }; - - }} //namespace boost { namespace interprocess If the user is defining a node container based index (a container whose iterators are not invalidated when inserting or erasing other elements), [*Boost.Interprocess] can @@ -5906,19 +5627,19 @@ Interprocess also defines other index types: * [*boost::null_index] that uses an dummy index type if the user just needs anonymous allocations and want's to save some space and class instantations. -Defininge a new managed memory segment that uses the new index is easy. For +Defining a new managed memory segment that uses the new index is easy. For example, a new managed shared memory that uses the new index: [c++] /*!Defines a managed shared memory with a c-strings as - a keys, the simple sequential fit algorithm (with process-shared mutexes + a keys, the red-black tree best fit algorithm (with process-shared mutexes and offset_ptr pointers) as raw shared memory management algorithm and a custom index*/ typedef basic_managed_shared_memory < char, - simple_seq_fit, + rbtree_best_fit, my_index_type > my_managed_shared_memory; @@ -5927,1091 +5648,6 @@ example, a new managed shared memory that uses the new index: [endsect] -[section:streams Direct iostream formatting: vectorstream and bufferstream] - -Shared memory, memory-mapped files and all [*Boost.Interprocess] mechanisms are focused -on efficiency. The reason why shared memory is used is that it's the -fastest IPC mechanism available. When passing text-oriented messages through -shared memory, there is need to format the message. Obviously C++ offers -the iostream framework for that work. - -Some programmers appreciate the iostream safety and design for memory -formatting but feel that the stringstream family is far from efficient not -when formatting, but when obtaining formatted data to a string, or when -setting the string from which the stream will extract data. An example: - -[c++] - - //Some formatting elements - std::string my_text = "..."; - int number; - - //Data reader - std::istringstream input_processor; - - //This makes a copy of the string. If not using a - //reference counted string, this is a serious overhead. - input_processor.str(my_text); - - //Extract data - while(/*...*/){ - input_processor >> number; - } - - //Data writer - std::ostringstream output_processor; - - //Write data - while(/*...*/){ - output_processor << number; - } - - //This returns a temporary string. Even with return-value - //optimization this is expensive. - my_text = input_processor.str(); - -The problem is even worse if the string is a shared-memory string, because -to extract data, we must copy the data first from shared-memory to a -std::string and then to a stringstream. To encode data in a shared-memory -string we should copy data from a stringstream to a std::string and then -to the shared-memory string. - -Because of this overhead, [*Boost.Interprocess] offers a way to format memory-strings -(in shared memory, memory mapped files or any other memory segment) that -can avoid all unneeded string copy and memory allocation/deallocation, while -using all iostream facilities. [*Boost.Interprocess] *vectorstream* and *bufferstream* implement -vector-based and fixed-size buffer based storage support for iostreams and -all the formatting/locale hard work is done by standard std::basic_streambuf<> -and std::basic_iostream<> classes. - -[section:vectorstream Formatting directly in your character vector: vectorstream] - -The *vectorstream* class family (*basic_vectorbuf*, *basic_ivectorstream* -,*basic_ovectorstream* and *basic_vectorstream*) is an efficient way to obtain -formatted reading/writing directly in a character vector. This way, if -a shared-memory vector is used, data is extracted/written from/to the shared-memory -vector, without additional copy/allocation. We can see the declaration of -basic_vectorbuf and basic_vectorstream here: - -[c++] - - /*!A streambuf class that controls the transmission of elements to and from - a basic_ivectorstream, basic_ovectorstream or basic_vectorstream. - It holds a character vector specified by CharVector template parameter - as its formatting buffer. The vector must have contiguous storage, like - std::vector, boost::interprocess::vector or boost::interprocess::basic_string*/ - template > - class basic_vectorbuf - : public std::basic_streambuf - { - public: - typedef CharVector vector_type; - typedef typename CharVector::value_type char_type; - typedef typename CharTraits::int_type int_type; - typedef typename CharTraits::pos_type pos_type; - typedef typename CharTraits::off_type off_type; - typedef CharTraits traits_type; - - /*!Constructor. Throws if vector_type default constructor throws.*/ - explicit basic_vectorbuf(std::ios_base::openmode mode - = std::ios_base::in | std::ios_base::out); - - /*!Constructor. Throws if vector_type(const Parameter ¶m) throws.*/ - template - explicit basic_vectorbuf(const Parameter ¶m, - std::ios_base::openmode mode - = std::ios_base::in | std::ios_base::out); - virtual ~basic_vectorbuf(){} - - /*!Swaps the underlying vector with the passed vector. - This function resets the position in the stream. - Does not throw.*/ - void swap_vector(vector_type &vect); - - /*!Returns a const reference to the internal vector. - Does not throw.*/ - const vector_type &vector() const; - - /*!Preallocates memory from the internal vector. - Resets the stream to the first position. - Throws if the internals vector's memory allocation throws.*/ - void reserve(typename vector_type::size_type size); - }; - - /*!A basic_iostream class that holds a character vector specified by CharVector - template parameter as its formatting buffer. The vector must have - contiguous storage, like std::vector, boost::interprocess::vector or - boost::interprocess::basic_string*/ - template > - class basic_vectorstream - : public std::basic_iostream - - { - public: - typedef CharVector vector_type; - typedef typename std::basic_ios - ::char_type char_type; - typedef typename std::basic_ios::int_type int_type; - typedef typename std::basic_ios::pos_type pos_type; - typedef typename std::basic_ios::off_type off_type; - typedef typename std::basic_ios::traits_type traits_type; - - /*!Constructor. Throws if vector_type default constructor throws.*/ - basic_vectorstream(std::ios_base::openmode mode - = std::ios_base::in | std::ios_base::out); - - /*!Constructor. Throws if vector_type(const Parameter ¶m) throws.*/ - template - basic_vectorstream(const Parameter ¶m, std::ios_base::openmode mode - = std::ios_base::in | std::ios_base::out); - - ~basic_vectorstream(){} - - //Returns the address of the stored stream buffer. - basic_vectorbuf* rdbuf() const; - - /*!Swaps the underlying vector with the passed vector. - This function resets the position in the stream. - Does not throw.*/ - void swap_vector(vector_type &vect); - - /*!Returns a const reference to the internal vector. - Does not throw.*/ - const vector_type &vector() const; - - /*!Preallocates memory from the internal vector. - Resets the stream to the first position. - Throws if the internals vector's memory allocation throws.*/ - void reserve(typename vector_type::size_type size); - }; - -The vector type is templatized, so that we can use any type of vector: -*std::vector*, *boost::interprocess::vector*.... But the storage must be *contiguous*, -we can't use a deque. We can even use *boost::interprocess::basic_string*, since it has a -vector interface and it has contiguous storage. *We can't use std::string*, because -although some std::string implementation are vector-based, others can have -optimizations and reference-counted implementations. - -The user can obtain a const reference to the internal vector using -`vector_type vector() const` function and he also can swap the internal vector -with an external one calling `void swap_vector(vector_type &vect)`. -The swap function resets the stream position. -This functions allow efficient methods to obtain the formatted data avoiding -all allocations and data copies. - -Let's see an example to see how to use vectorstream: - -[/ doc_vectorstream.cpp] - -[c++] - - #include - #include - #include - #include - #include - - using namespace boost::interprocess; - - typedef allocator - IntAllocator; - typedef allocator - CharAllocator; - typedef vector MyVector; - typedef basic_string - , CharAllocator> MyString; - typedef basic_vectorstream MyVectorStream; - - int main () - { - //Create shared memory - shared_memory_object::remove("MySharedMemory"); - managed_shared_memory segment( - create_only, - "MySharedMemory",//segment name - 65536); //segment size in bytes - - //Construct shared memory vector - MyVector *myvector = - segment.construct("MyVector") - (IntAllocator(segment.get_segment_manager())); - - //Fill vector - myvector->reserve(100); - for(int i = 0; i < 100; ++i){ - myvector->push_back(i); - } - - //Create the vectorstream. To create the internal shared memory - //basic_string we need to pass the shared memory allocator as - //a constructor argument - MyVectorStream myvectorstream(CharAllocator(segment.get_segment_manager())); - - //Reserve the internal string - myvectorstream.reserve(100*5); - - //Write all vector elements as text in the internal string - //Data will be directly written in shared memory, because - //internal string's allocator is a shared memory allocator - for(std::size_t i = 0, max = myvector->size(); i < max; ++i){ - myvectorstream << (*myvector)[i] << std::endl; - } - - //Auxiliary vector to compare original data - MyVector *myvector2 = - segment.construct("MyVector2") - (IntAllocator(segment.get_segment_manager())); - - //Avoid reallocations - myvector2->reserve(100); - - //Extract all values from the internal - //string directly to a shared memory vector. - std::istream_iterator it(myvectorstream), itend; - std::copy(it, itend, std::back_inserter(*myvector2)); - - //Compare vectors - assert(std::equal(myvector->begin(), myvector->end(), myvector2->begin())); - - //Create a copy of the internal string - MyString stringcopy (myvectorstream.vector()); - - //Now we create a new empty shared memory string... - MyString *mystring = - segment.construct("MyString") - (CharAllocator(segment.get_segment_manager())); - - //...and we swap vectorstream's internal string - //with the new one: after this statement mystring - //will be the owner of the formatted data. - //No reallocations, no data copies - myvectorstream.swap_vector(*mystring); - - //Let's compare both strings - assert(stringcopy == *mystring); - - //Done, destroy and delete vectors and string from the segment - segment.destroy_ptr(myvector2); - segment.destroy_ptr(myvector); - segment.destroy_ptr(mystring); - return 0; - } - -[endsect] - -[section:bufferstream Formatting directly in your character buffer: bufferstream] - -As seen, vectorstream offers an easy and secure way for efficient iostream -formatting, but many times, we have to read or write formatted data from/to a -fixed size character buffer (a static buffer, a c-string, or any other). -Because of the overhead of stringstream, many developers (specially in -embedded systems) choose sprintf family. The *bufferstream* classes offer -iostream interface with direct formatting in a fixed size memory buffer with -protection against buffer overflows. This is the interface: - - /*!A streambuf class that controls the transmission of elements to and from - a basic_xbufferstream. The elements are transmitted from a to a fixed - size buffer*/ - template > - class basic_bufferbuf - : public std::basic_streambuf - { - public: - typedef CharT char_type; - typedef typename CharTraits::int_type int_type; - typedef typename CharTraits::pos_type pos_type; - typedef typename CharTraits::off_type off_type; - typedef CharTraits traits_type; - typedef std::basic_streambuf base_t; - - public: - /*!Constructor. Does not throw.*/ - explicit basic_bufferbuf(std::ios_base::openmode mode - = std::ios_base::in | std::ios_base::out); - - /*!Constructor. Assigns formatting buffer. Does not throw.*/ - explicit basic_bufferbuf(CharT *buffer, std::size_t length, - std::ios_base::openmode mode - = std::ios_base::in | std::ios_base::out); - - /*!Returns the pointer and size of the internal buffer. - Does not throw.*/ - std::pair buffer() const; - - /*!Sets the underlying buffer to a new value. Does not throw.*/ - void buffer(CharT *buffer, std::size_t length); - }; - - /*!A basic_iostream class that uses a fixed size character buffer - as its formatting buffer.*/ - template > - class basic_bufferstream - : public std::basic_iostream - - { - public: // Typedefs - typedef typename std::basic_ios - ::char_type char_type; - typedef typename std::basic_ios::int_type int_type; - typedef typename std::basic_ios::pos_type pos_type; - typedef typename std::basic_ios::off_type off_type; - typedef typename std::basic_ios::traits_type traits_type; - - /*!Constructor. Does not throw.*/ - basic_bufferstream(std::ios_base::openmode mode - = std::ios_base::in | std::ios_base::out); - - /*!Constructor. Assigns formatting buffer. Does not throw.*/ - basic_bufferstream(CharT *buffer, std::size_t length, - std::ios_base::openmode mode - = std::ios_base::in | std::ios_base::out); - - /*!Returns the address of the stored stream buffer.*/ - basic_bufferbuf* rdbuf() const; - - /*!Returns the pointer and size of the internal buffer. - Does not throw.*/ - std::pair buffer() const; - - /*!Sets the underlying buffer to a new value. Resets - stream position. Does not throw.*/ - void buffer(CharT *buffer, std::size_t length); - }; - - //Some typedefs to simplify usage - typedef basic_bufferbuf bufferbuf; - typedef basic_bufferstream bufferstream; - typedef basic_ibufferstream ibufferstream; - typedef basic_obufferstream obufferstream; - - typedef basic_bufferbuf wbufferbuf; - typedef basic_bufferstream wbufferstream; - typedef basic_ibufferstream wibufferstream; - typedef basic_obufferstream wobufferstream; - -While reading from a fixed size buffer, *bufferstream* activates endbit flag if -we try to read an address beyond the end of the buffer. While writing to a -fixed size buffer, *bufferstream* will active the badbit flag if a buffer overflow -is going to happen and disallows writing. This way, the fixed size buffer -formatting through *bufferstream* is secure and efficient, and offers a good -alternative to sprintf/sscanf functions. Let's see an example: - -[/doc_bufferstream.cpp] - -[c++] - - #include - #include - #include - #include - - using namespace boost::interprocess; - - int main () - { - shared_memory_object::remove("MySharedMemory"); - //Create shared memory - managed_shared_memory segment(create_only, - "MySharedMemory", //segment name - 65536); - - //Fill data - std::vector data, data2; - data.reserve(100); - for(int i = 0; i < 100; ++i){ - data.push_back(i); - } - - //Allocate a buffer in shared memory to write data - char *my_cstring = - segment.construct("MyCString")[100*5](0); - bufferstream mybufstream(my_cstring, 100*5); - - //Now write data to the buffer - for(int i = 0; i < 100; ++i){ - mybufstream << data[i] << std::endl; - } - - //Check there was no overflow attempt - assert(mybufstream.good()); - - //Extract all values from the shared memory string - //directly to a vector. - data2.reserve(100); - std::istream_iterator it(mybufstream), itend; - std::copy(it, itend, std::back_inserter(data2)); - - //This extraction should have ended will fail error since - //the numbers formatted in the buffer end before the end - //of the buffer. (Otherwise it would trigger eofbit) - assert(mybufstream.fail()); - - //Compare data - assert(std::equal(data.begin(), data.end(), data2.begin())); - - //Clear errors and rewind - mybufstream.clear(); - mybufstream.seekp(0, std::ios::beg); - - //Now write again the data trying to do a buffer overflow - for(int i = 0; i < 500; ++i){ - mybufstream << data[i] << std::endl; - } - - //Now make sure badbit is active - //which means overflow attempt. - assert(!mybufstream.good()); - assert(mybufstream.bad()); - segment.destroy_ptr(my_cstring); - return 0; - } - -As seen, *bufferstream* offers an efficient way to format data without any -allocation and extra copies. This is very helpful in embedded systems, or -formatting inside time-critical loops, where stringstream extra copies would -be too expensive. Unlike sprintf/sscanf, it has protection against buffer -overflows. As we know, according to the *Technical Report on C++ Performance*, -it's possible to design efficient iostreams for embedded platforms, so this -bufferstream class comes handy to format data to stack, static or shared memory -buffers. - -[endsect] - -[endsect] - -[section:interprocess_smart_ptr Boost.Interprocess ownership smart pointers] - -C++ users know the importance of ownership smart pointers when dealing with resources. -Boost offers a wide range of such type of pointers: `intrusive_ptr<>`, -`scoped_ptr<>`, `shared_ptr<>`... - -When building complex shared memory/memory mapped files structures, programmers -would like to use also the advantages of these smart pointers. The problem is that -Boost and C++ TR1 smart pointers are not ready to be used for shared memory. The cause -is that those smart pointers contain raw pointers and they use virtual functions, -something that is not possible if you want to place your data in shared memory. -The virtual function limitation makes even impossible to achieve the same level of -functionality of Boost and TR1 with [*Boost.Interprocess] smart pointers. - -Interprocess ownership smart pointers are mainly "smart pointers contaning smart pointers", -so we can specify the pointer type they contain. - -[section:intrusive_ptr Intrusive pointer] - -`boost::interprocess::intrusive_ptr<>` is the generalization of `boost::intrusive_ptr<>` -to allow non-raw pointers as intrusive pointer members. As the known -`boost::intrusive_ptr` we must specify the pointee type but we also must also specify -the pointer type to be stored in the intrusive_ptr: - -[c++] - - /*!The intrusive_ptr class template stores a pointer to an object - with an embedded reference count. intrusive_ptr is parameterized on - T (the type of the object pointed to) and VoidPointer(a void pointer type - that defines the type of pointer that intrusive_ptr will store). - intrusive_ptr defines a class with a T* member whereas - intrusive_ptr > defines a class with a offset_ptr member. - Relies on unqualified calls to: - - void intrusive_ptr_add_ref(T * p); - void intrusive_ptr_release(T * p); - - with (p != 0) - - The object is responsible for destroying itself.*/ - template - class intrusive_ptr - { - public: - /*!Provides the type of the internal stored pointer.*/ - typedef typename /*...*/ pointer; - /*!Provides the type of the stored pointer.*/ - typedef T element_type; - - /*!Constructor. Initializes internal pointer to 0. Does not throw*/ - intrusive_ptr(); - - /*!Constructor. Copies pointer and if "p" is not zero and - "add_ref" is true calls intrusive_ptr_add_ref(get_pointer(p)). - Does not throw*/ - intrusive_ptr(const pointer &p, bool add_ref = true); - - /*!Copy constructor. Copies the internal pointer and if "p" is not - zero calls intrusive_ptr_add_ref(get_pointer(p)). Does not throw*/ - intrusive_ptr(intrusive_ptr const & rhs); - - /*!Constructor from related. Copies the internal pointer and if "p" is not - zero calls intrusive_ptr_add_ref(get_pointer(p)). Does not throw*/ - template intrusive_ptr (intrusive_ptr const & rhs); - - /*!Destructor. If internal pointer is not 0, calls - intrusive_ptr_release(get_pointer(m_ptr)). Does not throw*/ - ~intrusive_ptr(); - - /*!Assignment operator. Equivalent to intrusive_ptr(r).swap(*this). - Does not throw*/ - intrusive_ptr & operator=(intrusive_ptr const & rhs); - - /*!Assignment from related. Equivalent to intrusive_ptr(r).swap(*this). - Does not throw*/ - template intrusive_ptr & operator= (intrusive_ptr const & rhs); - - /*!Assignment from pointer. Equivalent to intrusive_ptr(r).swap(*this). - Does not throw*/ - intrusive_ptr & operator=(pointer rhs); - - /*!Returns a reference to the internal pointer. Does not throw*/ - pointer &get(); - - /*!Returns a reference to the internal pointer. Does not throw*/ - const pointer &get() const; - - /*!Returns *get(). Does not throw*/ - T & operator*() const; - - /*!Returns *get(). Does not throw*/ - const pointer &operator->() const; - - /*!Returns get(). Does not throw*/ - pointer &operator->(); - - operator unspecified_bool_type () const; - - /*!Not operator. Does not throw*/ - bool operator! () const; - - /*!Exchanges the contents of the two smart pointers. Does not throw*/ - void swap(intrusive_ptr & rhs); - }; - -So `boost::interprocess::intrusive_ptr` is equivalent to -`boost::instrusive_ptr`. But if we want to place the intrusive_ptr in -shared memory we must specify a relative pointer type like -`boost::interprocess::intrusive_ptr >` - -[/doc_intrusive.cpp] - -[c++] - - #include - #include - - using namespace boost::interprocess; - - namespace N { - - //A class that has an internal reference count - class reference_counted_class - { - private: - //Non-copyable - reference_counted_class(const reference_counted_class &); - //Non-assignable - reference_counted_class & operator=(const reference_counted_class &); - //A typedef to save typing - typedef managed_shared_memory::segment_manager segment_manager; - //This is the reference count - unsigned int m_use_count; - //The segment manager allows deletion from shared memory segment - offset_ptr mp_segment_manager; - - public: - //Constructor - reference_counted_class(segment_manager *s_mngr) - : m_use_count(0), mp_segment_manager(s_mngr){} - //Destructor - ~reference_counted_class(){} - - public: - //Returns the reference count - unsigned int use_count() const - { return m_use_count; } - //Adds a reference - inline friend void intrusive_ptr_add_ref(reference_counted_class * p) - { ++p->m_use_count; } - //Releases a reference - inline friend void intrusive_ptr_release(reference_counted_class * p) - { if(--p->m_use_count == 0) p->mp_segment_manager->destroy_ptr(p); } - }; - - } //namespace N { - - //A class that has an intrusive pointer to reference_counted_class - class intrusive_ptr_owner - { - typedef intrusive_ptr > intrusive_ptr_t; - intrusive_ptr_t m_intrusive_ptr; - - public: - //Takes a pointer to the reference counted class - intrusive_ptr_owner(N::reference_counted_class *ptr) - : m_intrusive_ptr(ptr){} - }; - - int main () - { - shared_memory_object::remove("my_shmem"); - //Create shared memory - managed_shared_memory shmem(create_only, "my_shmem", 10000); - //Create the unique reference counted object in shared memory - N::reference_counted_class *ref_counted = - shmem.construct - ("ref_counted")(shmem.get_segment_manager()); - //Create an array of ten intrusive pointer owners in shared memory - intrusive_ptr_owner *intrusive_owner_array = - shmem.construct - (anonymous_instance)[10](ref_counted); - //Now test that reference count is ten - if(ref_counted->use_count() != 10) - return 1; - - //Now destroy the array of intrusive pointer owners - //This should destroy every intrusive_ptr and because of - //that reference_counted_class will be destroyed - shmem.destroy_ptr(intrusive_owner_array); - - //Now the reference counted object should have been destroyed - if(shmem.find("ref_counted").first) - return 1; - //Success! - return 0; - } - -[endsect] - -[section:scoped_ptr Scoped pointer] - -`boost::interprocess::scoped_ptr<>` is the big brother of `boost::scoped_ptr<>`, which -adds a custom deleter to specify how the pointer passed to the scoped_ptr must be destroyed. -Also, the `pointer` typedef of the deleter will specify the pointer type stored by scoped_ptr. - -[c++] - - /*!scoped_ptr stores a pointer to a dynamically allocated object. - The object pointed to is guaranteed to be deleted, either on destruction - of the scoped_ptr, or via an explicit reset. The user can avoid this - deletion using release(). - scoped_ptr is parameterized on T (the type of the object pointed to) and - Deleter (the functor to be executed to delete the internal pointer). - The internal pointer will be of the same pointer type as typename - Deleter::pointer type (that is, if typename Deleter::pointer is - offset_ptr, the internal pointer will be offset_ptr).*/ - template - class scoped_ptr - { - public: - - /*!Provides the type of the stored pointer.*/ - typedef T element_type; - - /*!Provides the type of the internal stored pointer.*/ - typedef /*...*/ pointer; - - /*!Constructs a scoped_ptr, storing a copy of p(which can be 0) and d. - Does not throw.*/ - explicit scoped_ptr(const pointer &p = 0, const Deleter &d = Deleter()); - - /*!If the stored pointer is not 0, destroys the object pointed to by the stored pointer. - calling the operator() of the stored deleter.*/ - ~scoped_ptr(); - - /*!Deletes the object pointed to by the stored pointer and then - stores a copy of p. Never throws*/ - void reset(const pointer &p = 0); - - /*!Deletes the object pointed to by the stored pointer and then - stores a copy of p and a copy of d.*/ - void reset(const pointer &p, const Deleter &d); - - /*!Assigns internal pointer as 0 and returns previous pointer. This will - avoid deletion on destructor*/ - pointer release(): - - /*!Returns a reference to the object pointed to by the stored pointer. - Never throws.*/ - reference operator*() const; - - /*!Returns the internal stored pointer. Never throws*/ - pointer &operator->(); - - /*!Returns the internal stored pointer. Never throws.*/ - const pointer &operator->() const; - - /*!Returns the stored pointer. Never throws.*/ - pointer & get(); - - /*!Returns the stored pointer. Never throws.*/ - const pointer & get() const; - - /*!Returns true if the stored pointer is 0. Never throws.*/ - bool operator! () const; - - /*!Exchanges the internal pointer and deleter with other scoped_ptr - Never throws.*/ - void swap(scoped_ptr & b); - }; - -`scoped_ptr<>` comes handy to implement *rollbacks* with exceptions: if an exception -is thrown or we call `return` in the scope of `scoped_ptr<>` the deleter is -automatically called so that *the deleter can be considered as a rollback* function. -If all goes well, we call `release()` member function to avoid rollback when -the `scoped_ptr` goes out of scope. - -[/doc_scoped_ptr.cpp] - -[c++] - - #include - #include - - using namespace boost::interprocess; - - class my_class - {}; - - class my_exception - {}; - - //A functor that destroys the shared memory object - template - class my_deleter - { - private: - //A typedef to save typing - typedef managed_shared_memory::segment_manager segment_manager; - //This my_deleter is created in the stack, not in shared memory, - //so we can use raw pointers - segment_manager *mp_segment_manager; - - public: - //This typedef will specify the pointer type that - //scoped_ptr will store - typedef T *pointer; - //Constructor - my_deleter(segment_manager *s_mngr) - : mp_segment_manager(s_mngr){} - - void operator()(pointer object_to_delete) - { mp_segment_manager->destroy_ptr(object_to_delete); } - }; - - int main () - { - //Create shared memory - shared_memory_object::remove("my_shmem"); - managed_shared_memory shmem(create_only, "my_shmem", 10000); - - //In the first try, there will be no exceptions - //in the second try we will throw an exception - for(int i = 0; i < 2; ++i){ - //Create an object in shared memory - my_class * my_object = shmem.construct("my_object")(); - - //Since the next shared memory allocation can throw - //assign it to a scoped_ptr so that if an exception occurs - //we destroy the object automatically - my_deleter d(shmem.get_segment_manager()); - - try{ - scoped_ptr > s_ptr(my_object, d); - //Let's emulate a exception capable operation - //In the second try, throw an exception - if(i == 1){ - throw(my_exception()); - } - //If we have passed the dangerous zone - //we can release the scoped pointer - //to avoid destruction - s_ptr.release(); - } - catch(const my_exception &){} - - //Here, scoped_ptr is destroyed - //so it we haven't thrown an exception - //the object should be there, otherwise, destroyed - if(i == 0){ - //Make sure the object is alive - if(!shmem.find("my_object").first){ - return 1; - } - //Now we can use it and delete it manually - shmem.destroy("my_object"); - } - else{ - //Make sure the object has been deleted - if(shmem.find("my_object").first){ - return 1; - } - } - } - return 0; - } - -[endsect] - -[endsect] - -[section:architecture Boost.Interprocess architecture and internals] - -[section:basic_guidelines Basic guidelines] - -When building [*Boost.Interprocess] architecture, I took some basic guidelines that can be -resumed in these points: - -* [*Boost.Interprocess] should be portable at least in UNIX and Windows systems. That - means unifying not only interfaces but also behaviour. This is why - [*Boost.Interprocess] has chosen kernel or filesystem persistence for shared memory - and named synchronization mechanisms. Process persistence for shared memory is also - desirable but it's difficult to achieve in UNIX systems. - -* [*Boost.Interprocess] inter-process synchronization primitives should be equal to thread - synchronization primitives. [*Boost.Interprocess] aims to define interface as the C++ - standard thread API. - -* [*Boost.Interprocess] architecture should be modular, customizable but efficient. That's - why [*Boost.Interprocess] is based on templates and memory algorithms, index types, - mutex types and other classes are templatizable. - -* [*Boost.Interprocess] architecture should allow the same concurrency as thread based - programming. Different mutual exclusion levels are defined so that a process - can concurrently allocate raw memory when expanding a shared memory vector while another - process can be safely searching a named object. - -* [*Boost.Interprocess] containers know nothing about [*Boost.Interprocess]. All specific - behaviour is contained in the STL-like allocators. That allows STL vendors to slightly - modify (or better said, generalize) their standard container implementations and obtain - a fully std::allocator and boost::interprocess::allocator compatible container. This also - make [*Boost.Interprocess] containers compatible with standard algorithms. - -Interprocess is built above 3 basic classes: a *memory algorithm* a *segment manager* and -a *managed memory segment*: - -[endsect] - -[section:architecture_memory_algorithm The memory algorithm] - -The *memory algorithm* is an object that is placed in the first bytes of a -shared memory/memory mapped file segment. The *memory algorithm* can return -portions of that segment to users marking them as used and the user can return those -portions to the memory manager so that the memory manager mark them as free -again. There is an exception though, some bytes beyond the end of the memory -algorithm object, are reserved and can't be used for this dynamic allocation. -This "reserved" zone will be used to place other additional objects -in a well-known place. - -To sum up, a *memory algorithm* has the same mission as malloc/free of -standard C library, but it just can return portions of the segment -where it is placed. The layout of a memory segment would be: - -[c++] - - Layout of the memory segment: - ____________ __________ ____________________________________________ - | | | | - | memory | reserved | The memory algorithm will return portions | - | algorithm | | of the rest of the segment. | - |____________|__________|____________________________________________| - - -The memory algorithm takes care of memory synchronizations, just like malloc/free -guarantees that two threads can call malloc/free at the same time. This is usually -achieved placing a process-shared mutex as a member of the memory algorithm. Take -in care that the memory algorithm knows *nothing* about the segment (if it is -shared memory, a shared memory file, etc.). For the memory algorithm the segment -is just a fixed size memory buffer. - -The *memory manager* is also a configuration point for the rest of the [*Boost.Interprocess] -framework since it defines two basic types as member typedefs: - -[c++] - - typedef /*implementation dependent*/ void_pointer; - typedef /*implementation dependent*/ mutex_family; - - -The `void_pointer` typedef defines the pointer type that will be used in the -[*Boost.Interprocess] framework (segment manager, allocators, containers). If the memory -algorithm is ready to be placed in a shared memory/mapped file mapped in different base -addresses, this pointer type will be defined as `offset_ptr` or a similar relative -pointer. If the memory algorithm will be used just with fixed address mapping, -`void_pointer` can be defined as `void*`. - -The rest of the interface of a [*Boost.Interprocess] *memory algorithm* is described in -[link interprocess.customizing_boost_interprocess.custom_interprocess_alloc Writing a new shared memory allocation algorithm] -section. As memory algorithm examples, you can see the implementations -[@../../../../boost/interprocess/mem_algo/simple_seq_fit.hpp boost::interprocess::simple_seq_fit] or -[@../../../../boost/interprocess/mem_algo/seq_fit.hpp boost::interprocess::seq_fit] classes. - -[endsect] - -[section:architecture_segment_manager The segment manager] - -The *segment manager*, is an object also placed in the first bytes of the -managed memory segment (shared memory, memory mapped file), that offers more -sofisticated services built above the [*memory algorithm]. How can [*both] the -segment manager and memory algorithm be placed in the beginning of the segment? -That's because the segment manager [*owns] the memory algorithm: The -truth is that the memory algorithm is [*embedded] in the segment manager: - - -[c++] - - The layout of managed memory segment: - _______ _________________ - | | | | - | some | memory | other |<- The memory algorithm considers - |members|algorithm|members| "other members" as reserved memory, so - |_______|_________|_______| it does not use it for dynamic allocation. - |_________________________|____________________________________________ - | | | - | segment manager | The memory algorithm will return portions | - | | of the rest of the segment. | - |_________________________|____________________________________________| - - -The segment manager initializes the memory algorithm and tells the memory -manager that it should not use the memory where the rest of the -segment manager's member are placed for dynamic allocations. The -other members of the [*segment manager] are [*a recursive mutex] -(defined by the memory algorithm's [*mutex_family::recursive_mutex] typedef member), -and [*two indexes (maps)]: one to implement named allocations, and another one to -implement "unique instance" allocations. - -* The first index is a map with a pointer to a c-string (the name of the named object) - as a key and a structure with information of the dynamically allocated object - (the most importants being the address and the size of the object). - -* The second index is used to implement "unique instances" - and is basically the same as the first index, - but the name of the object comes from a `typeid(T).name()` operation. - -The memory needed to store [name pointer, object information] pairs in the index is -allocated also via the *memory algorithm*, so we can tell that internal indexes -are just like ordinary user objects built in the segment. The rest of the memory -to store the name of the object, the object itself, and meta-data for -destruction/deallocation is allocated using the *memory algorithm* in a single -`allocate()` call. - -As seen, the segment manager knows *nothing* about shared memory/memory mapped files. -The segment segment manager itself does not allocate portions of the segment, -it just asks the *memory algorithm* to allocate the needed memory from the rest -of the segment. The *segment manager* is a class built above the memory algorithm -that offers named object construction, unique instance constructions, and many -other services. - -The [*segment manager] is implemented in [*Boost.Interprocess] in -[@../../../../boost/interprocess/detail/segment_manager.hpp boost::interprocess::segment_manager] -class. - -[c++] - - template class IndexType> - class segment_manager; - -As seen, the segment manager is quite generic: we can specify the character type -to be used to identify named objects, we can specify the memory algorithm that will -control dynamically the portions of the memory segment, and we can specify -also the index type that will store the [name pointer, object information] mapping. -We can construct our own index types as explained in -[link interprocess.customizing_boost_interprocess.custom_indexes Building custom indexes] section. - -[endsect] - -[section:architecture_managed_memory Boost.Interprocess managed memory segments] - -The [*Boost.Interprocess] managed memory segments that construct the shared memory/memory -mapped file, place there the segment manager and forward the user requests to the -segment manager. For example, [*boost::interprocess::basic_managed_shared_memory<...>] -is a [*Boost.Interprocess] managed memory segment that works with shared memory. -[*boost::interprocess::basic_managed_mapped_file<...>] works with memory mapped files, etc... - -Basically, the interface of a [*Boost.Interprocess] managed memory segment is the same as -the [*segment manager] but it also offers functions to "open", "create", or "open or create" -shared memory/memory-mapped files segments and initialize all needed resources. -Managed memory segment classes are not built in shared memory or memory mapped files, they -are normal C++ classes that store a pointer to the segment manager (which are built -in shared memory or memory mapped files). - -Apart from this, managed memory segments offer specific functions: `managed_mapped_file` -offers functions to flush memory contents to the file, `managed_heap_memory` offers -functions to expand the memory, etc... - -Most of the functions of [*Boost.Interprocess] managed memory segments can be shared -between all managed memory segments, since many times they just forward the functions -to the segment manager. Because of this, -in [*Boost.Interprocess] all managed memory segments derive from a common class that -implements memory-independent (shared memory, memory mapped files) functions: -[@../../../../boost/interprocess/detail/managed_memory_impl.hpp -boost::interprocess::detail::basic_managed_memory_impl] - -Deriving from this class, [*Boost.Interprocess] implements several managed memory -classes, for different memory backends: - -* [@../../../../boost/interprocess/managed_shared_memory.hpp boost::interprocess::basic_managed_shared_memory] (for shared memory), -* [@../../../../boost/interprocess/managed_mapped_file.hpp boost::interprocess::basic_managed_mapped_file] (for memory mapped files), -* [@../../../../boost/interprocess/managed_heap_memory.hpp boost::interprocess::basic_managed_heap_memory] (for heap allocated memory), -* [@../../../../boost/interprocess/managed_external_buffer.hpp boost::interprocess::basic_managed_external_buffer] (for user provided memory buffer), - -[endsect] - -[section:architecture_allocators Boost.Interprocess allocators] - -The [*Boost.Interprocess] STL-like allocators are fairly simple and follow the usual C++ -allocator approach. Normally, allocators for STL containers are based above new/delete -operators and above those, they implement pools, arenas and other allocation tricks. - -In [*Boost.Interprocess] allocators, the approach is similar, but all allocators are based -on the *segment manager*. The segment manager is the only one that provides from simple -memory allocation to named object creations. [*Boost.Interprocess] allocators always store -a pointer to the segment manager, so that they can obtain memory from the segment or share -a common pool between allocators. - -As you can imagine, the member pointers of the allocator are not a raw pointers, but -pointer types defined by the `segment_manager::void_pointer` type. Apart from this, -the `pointer` typedef of [*Boost.Interprocess] allocators is also of the same type of -`segment_manager::void_pointer`. - -This means that if our allocation algorithm defines `void_pointer` as `offset_ptr`, -`boost::interprocess::allocator` will store an `offset_ptr` -to point to the segment manager and the `boost::interprocess::allocator::pointer` type -will be `offset_ptr`. This way, [*Boost.Interprocess] allocators can be placed in the -memory segment managed by the segment manager, that is, shared memory, memory mapped files, -etc... - -[*Boost.Interprocess] implements basically two allocator approaches: normal and pooled. -All pooled allocators share most of the implementation. This common implementation is in -[@../../../../boost/interprocess/allocators/detail/node_pool.hpp -boost::interprocess::detail::private_node_pool and boost::interprocess::detail::node_pool] -classes. - -[endsect] - -[section:architecture_containers Boost.Interprocess containers] - -[*Boost.Interprocess] containers are standard conforming counterparts of STL containers -in boost::interprocess namespace, but with these little details: - -* [*Boost.Interprocess] STL containers don't assume that memory allocated with - an allocator can be deallocated with other allocator of - the same type. They always compare allocators with `operator==()` - to know if this is possible. - -* The pointers of the internal structures of the [*Boost.Interprocess] containers are - of the same type the `pointer` type defined by the allocator of the container. This - allows placing containers in managed memory segments mapped in different base addresses. - -* All objects are constructed-destroyed via allocator::construct and - allocator::destroy functions. - -[endsect] - -[endsect] - [section:performance Performance of Boost.Interprocess] This section tries to explain the performance characteristics of [*Boost.Interprocess], @@ -7047,8 +5683,8 @@ these alternatives: allocators call `allocate()` only when the pool runs out of nodes. This is pretty efficient (much more than the current default general-purpose algorithm) and this can save a lot of memory. See - [link interprocess.stl_allocators Boost.Interprocess STL compatible allocators] to compare - the [*Boost.Interprocess] node allocators and their trade-offs. + [link interprocess.stl_allocators_segregated_storage Segregated storage node allocators] and + [link interprocess.stl_allocators_adaptive Adaptive node allocators] for more information. * Write your own memory algorithm. If you have experience with memory allocation algorithms and you think another algorithm is better suited than the default one for your application, @@ -7162,21 +5798,6 @@ with POSIX primitives. [endsect] -[section:default_algorithm Default allocation algorithm can be improved] - -The default memory management algorithm used by [*Boost.Interprocess] to manage -the managed memory segment is a "first fit" algorithm. This could be changed -to a "best fit" algorithm to try to minimize fragmentation, but this would -hurt performance if a list is used to mantain the free memory portions. -This can be solved with a tree-like free memory management, so that we can -search the best portion in logarithmic time. And we have to implement the -tree inside the given segment wasting minimum space. This seems complicated, -but with the help of an intrusive tree implementation this can be achieved. - -Suggestions and help from memory management experts are welcome! - -[endsect] - [section:future_objectnames Use of wide character names on Boost.Interprocess basic resources] Currently Interprocess only allows *char* based names for basic named @@ -7227,15 +5848,6 @@ intrusive containers. [endsect] -[section:future_move_semantics Move semantics] - -Move semantics offer a great performance improvement in several areas and -[*Boost.Interprocess] containers and a great place to implement them. This -way, managing vectors of strings in shared memory should be a lot cheaper -than the current copy semantics containers. - -[endsect] - [endsect] [section:thanks_to Thanks to...] @@ -7251,8 +5863,10 @@ thank them: * Thanks to [*Francis Andre] and [*Anders Hybertz] for their ideas and suggestions. Many of them are not implemented yet but I hope to include them when library gets some stability. -* Thanks to [*Hiang Swee Chiang], [*Phil Endecott], [*Rene Rivera], - [*Harold Pirtle], [*Paul Ryan] [*Shumin Wu], [*Michal Wozniak], [*Peter Johnson] +* Thanks to [*Steve LoBasso], [*Glenn Schrader], [*Hiang Swee Chiang], + [*Phil Endecott], [*Rene Rivera], + [*Harold Pirtle], [*Paul Ryan], + [*Shumin Wu], [*Michal Wozniak], [*Peter Johnson], [*Alex Ott], [*Shane Guillory], [*Steven Wooding] and [*Kim Barrett] for their bug fixes and library testing. @@ -7273,7 +5887,7 @@ thank them: help. He is the major supporter of Interprocess library. The library has grown with his many and great advices. -* And finally, thank you to all Boosters. *Long live to C++!* +* And finally, thank you to all Boosters. [*Long live to C++!] [endsect] @@ -7297,16 +5911,122 @@ documentation. Hewlett-Packard Company makes no representations about the suitab of this software for any purpose. It is provided "as is" without express or implied warranty. +[*Boost.Interprocess] atomic integer manipulation functions are based on +Apache Portable Runtime: + +Copyright 2000-2005 The Apache Software Foundation or its licensors, as +applicable. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + [endsect] [endsect] [section:changes Changes...] +[section:changes_interprocess_2007_05_03 Changes in Interprocess 2007-05-03...] + +* Fixed bug in VC-8.0: Broken function inlining in core offset_ptr functions. + +* Code examples changed to use new BoostBook code import features. + +* Added aligned memory allocation function to memory algorithms. + +* Fixed bug in `deque::clear()` and `deque::erase()`, they were declared private. + +* Fixed bug in `deque::erase()`. Thanks to Steve LoBasso. + +* Fixed bug in `atomic_dec32()`. Thanks to Glenn Schrader. + +* Improved (multi)map/(multi)set constructors taking iterators. Now those have + linear time if the iterator range is already sorted. + +* Documented Boost.Interprocess containers. Containers are now documented in the Reference section. + +* [*ABI breaking]: (multi)map/(multi)set now reduce their node size. The color + bit is embedded in the parent pointer. Now, the size of a node is the size of + 3 pointers in most systems. This optimization is activated for raw and `offset_ptr` + pointers. + +* (multi)map/(multi)set now reuse memory from old nodes in the assignment operator. + +* [*ABI breaking]: Implemented node-containers based on intrusive containers. + This saves code size, since many instantiations share the same algorithms. + +* Corrected code to be compilable with Visual C++ 8.0. + +* Added function to zero free memory in memory algorithms and the segment manager. + This function is useful for security reasons and to improve compression ratios + for files created with `managed_mapped_file`. + +* Added support for intrusive index types in managed memory segments. + Intrusive indexes save extra memory allocations to allocate the index + since with just one + allocation, we allocate room for the value, the name and the hook to insert + the object in the index. + +* Created new index type: [*iset_index]. It's an index based on + an intrusive set (rb-tree). + +* Created new index type: [*iunordered_set_index]. It's an index + based on a pseudo-intrusive unordered set (hash table). + +* [*ABI breaking]: The intrusive index [*iset_index] is now the default + index type. + +* Optimized vector to take advantage of `boost::has_trivial_destructor`. + This optimization avoids calling destructors of elements that have a trivial destructor. + +* Optimized vector to take advantage of `boost::intrusive::has_trivial_destructor_after_move` trait. + This optimization avoids calling destructors of elements that have a trivial destructor + if the element has been moved (which is the case of many movable types). This trick + was provided by Howard Hinnant. + +* Added security check to avoid interger overflow bug in allocators and + named construction functions. + +* Added alignment checks to forward and backwards expansion functions. + +* Fixed bug in atomic funtions for PPC. + +* Fixed race-condition error when creating and opening a managed segment. + +* Added adaptive pools. + +* [*Source breaking]: Changed node allocators' template parameter order + to make them more easy to use. + +* Added support for native windows shared memory. + +* Added more tests. + +* Documentation improved and expanded. + +* Corrected the presence of private functions in the reference section. + +* Added function (`deallocate_free_chunks()`) to manually deallocate completely free + chunks from node allocators. + +* Minor bugfixes. + +[endsect] + [section:changes_interprocess_2006_10_13 Changes in Interprocess 2006-10-13...] * Implemented N1780 proposal to LWG issue 233: ['Insertion hints in associative containers] - in interprocess `boost::interprocess::multiset` and `boost::interprocess::multimap` class. + in interprocess [classref boost::interprocess::multiset multiset] and + [classref boost::interprocess::multimap multimap] classes. * [*Source breaking]: A shared memory object is now used including `shared_memory_object.hpp` header instead of `shared memory.hpp`. @@ -7321,7 +6041,7 @@ warranty. redefinition errors when using Interprocess and Asio in windows. * [*ABI breaking]: `mapped_region` constructor no longer requires classes - derived from memory_mappable, but classes the fulfill the MemoryMappable concept. + derived from memory_mappable, but classes must fulfill the MemoryMappable concept. * Added in-place reallocation capabilities to basic_string. @@ -7377,5 +6097,4 @@ allocators and containers, I've used to design Interprocess. [endsect] - -[xinclude interprocess_doxygen.xml] +[xinclude interprocess_doxygen.boostbook] diff --git a/example/Attic/named_alloc_example.cpp b/example/Attic/named_alloc_example.cpp deleted file mode 100644 index 8982ceb..0000000 --- a/example/Attic/named_alloc_example.cpp +++ /dev/null @@ -1,96 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztañaga 2004-2006. Distributed under the Boost -// Software License, Version 1.0. (See accompanying file -// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/interprocess for documentation. -// -////////////////////////////////////////////////////////////////////////////// -#include -#include - -#include -#include - -int main () -{ - using namespace boost::interprocess; - typedef std::pair MyType; - - //Named allocate capable shared mem allocator - //Create shared memory - shared_memory_object::remove("MySharedMemory"); - managed_shared_memory segment - (create_only, - "MySharedMemory",//segment name - 65536); //segment size in bytes - - //Create an object of MyType initialized to {0, 0} - segment.construct - ("MyType instance") /*name of the object*/ - (0 /*ctor first argument*/, - 0 /*ctor second argument*/); - - //Create an array of 10 elements of MyType initialized to {0, 0} - segment.construct - ("MyType array") /*name of the object*/ - [10] /*number of elements*/ - (0 /*ctor first argument*/, - 0 /*ctor second argument*/); - - - //Let's simulate other process - { - using namespace boost::interprocess; - typedef std::pair MyType; - - //Named allocate capable shared mem allocator - //Create shared memory - managed_shared_memory segment - (open_only, "MySharedMemory"); //segment name - - //Find the array and object - std::pair res; - res = segment.find ("MyType array"); - - std::size_t array_len = res.second; - //Length should be 1 - assert(array_len == 10); - - //Find the array and the object - res = segment.find ("MyType instance"); - - std::size_t len = res.second; - - //Length should be 1 - assert(len == 1); - - //Change data - // . . . - - //We're done, delete array from memory - segment.destroy("MyType array"); - //We're done, delete object from memory - segment.destroy("MyType instance"); - } - - MyType *anonymous = segment.construct(anonymous_instance) - [10] //number of elements - (1, //ctor first argument - 1); //ctor second argument - - segment.destroy_ptr(anonymous); - - segment.construct(unique_instance) - [10] //number of elements - (1, //ctor first argument - 1); //ctor second argument - - std::pair ret = segment.find(unique_instance); - - segment.destroy(unique_instance); - return 0; -} - -#include diff --git a/example/Attic/print_container.hpp b/example/Attic/print_container.hpp deleted file mode 100644 index d6c8525..0000000 --- a/example/Attic/print_container.hpp +++ /dev/null @@ -1,38 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztañaga 2004-2006. Distributed under the Boost -// Software License, Version 1.0. (See accompanying file -// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/interprocess for documentation. -// -////////////////////////////////////////////////////////////////////////////// - -#ifndef BOOST_PRINTCONTAINER_HPP -#define BOOST_PRINTCONTAINER_HPP -#include -#include - -#include -#include -#include - -struct PrintValues : public std::unary_function -{ - void operator() (int value) const - { - std::cout << value << " "; - } -}; - -template -void PrintContents(const Container &cont, const char *contName) -{ - std::cout<< "Printing contents of " << contName << std::endl; - std::for_each(cont.begin(), cont.end(), PrintValues()); - std::cout<< std::endl << std::endl; -} - -#include - -#endif //#ifndef BOOST_PRINTCONTAINER_HPP diff --git a/example/Attic/printcontainer.hpp b/example/Attic/printcontainer.hpp deleted file mode 100644 index d6c8525..0000000 --- a/example/Attic/printcontainer.hpp +++ /dev/null @@ -1,38 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztañaga 2004-2006. Distributed under the Boost -// Software License, Version 1.0. (See accompanying file -// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/interprocess for documentation. -// -////////////////////////////////////////////////////////////////////////////// - -#ifndef BOOST_PRINTCONTAINER_HPP -#define BOOST_PRINTCONTAINER_HPP -#include -#include - -#include -#include -#include - -struct PrintValues : public std::unary_function -{ - void operator() (int value) const - { - std::cout << value << " "; - } -}; - -template -void PrintContents(const Container &cont, const char *contName) -{ - std::cout<< "Printing contents of " << contName << std::endl; - std::for_each(cont.begin(), cont.end(), PrintValues()); - std::cout<< std::endl << std::endl; -} - -#include - -#endif //#ifndef BOOST_PRINTCONTAINER_HPP diff --git a/example/Attic/process_a_example.cpp b/example/Attic/process_a_example.cpp deleted file mode 100644 index e978a4a..0000000 --- a/example/Attic/process_a_example.cpp +++ /dev/null @@ -1,81 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztañaga 2004-2006. Distributed under the Boost -// Software License, Version 1.0. (See accompanying file -// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/interprocess for documentation. -// -////////////////////////////////////////////////////////////////////////////// -#include -#include - -#include -#include -#include -#include "print_container.hpp" -#include -#include -#include -#include - -using namespace boost::interprocess; - -int main () -{ - //Shared memory attributes - const int memsize = 65536; - const char *const shMemName = "MySharedMemory"; - - //Create sems for synchronization - named_semaphore semA(open_or_create, "processAsem", 0); - named_semaphore semB(open_or_create, "processBsem", 0); - - //Create shared memory - managed_shared_memory segment(open_or_create, shMemName, memsize); - - //STL compatible allocator object, uses allocate(), deallocate() functions - typedef allocator - shmem_allocator_int_t; - - const int num_elements = 100; - - //Type of shared memory vector - typedef vector MyVect; - - const shmem_allocator_int_t &alloc_ref (segment.get_segment_manager()); - - //Creating the vector in shared memory - std::cout << "Named New of ShmVect\n\n"; - MyVect *shmem_vect = segment.construct ("ShmVect")(alloc_ref); - - offset_ptr shmptr_vect = 0; - offset_ptr other_shmptr_vect = 0; - - //Fill the vector - std::cout << "Filling ShmVect\n\n"; - int i; - for(i = 0; i < num_elements; ++i){ - shmem_vect->push_back(i); - } - - //Printing contents before waiting to second process - PrintContents(*shmem_vect, "ShmVect"); - - //Wake up other process and sleeping until notified - semB.post(); - std::cout << "Waking up processB and waiting sorting\n\n"; - semA.wait(); - - //Notification received, let's see the changes - std::cout << "processB sorting complete\n\n"; - PrintContents(*shmem_vect, "ShmVect"); - - //Let's delete the vector from memory - std::cout << "Deleting the vector with destroy\n\n"; - segment.destroy ("ShmVect"); - std::cout << "vector deleted\n\n"; - return 0; -} - -#include diff --git a/example/Attic/process_a_fixed_example.cpp b/example/Attic/process_a_fixed_example.cpp deleted file mode 100644 index 2b094ff..0000000 --- a/example/Attic/process_a_fixed_example.cpp +++ /dev/null @@ -1,82 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztañaga 2004-2006. Distributed under the Boost -// Software License, Version 1.0. (See accompanying file -// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/interprocess for documentation. -// -////////////////////////////////////////////////////////////////////////////// -#include -#include - -#include -#include -#include -#include -#include "print_container.hpp" -#include -#include -#include -#include - -using namespace boost::interprocess; - -int main () -{ - //Shared memory attributes - const int memsize = 65536; - const char *const shMemName = "MySharedMemory"; - const void *const map_addr = reinterpret_cast(0x30000000); - - //Create sems for synchronization - named_semaphore semA(open_or_create, "processAsem", 0); - named_semaphore semB(open_or_create, "processBsem", 0); - - //Create shared memory - fixed_managed_shared_memory segment(create_only, shMemName, memsize, map_addr); - - //STL compatible allocator object, uses allocate(), deallocate() functions - typedef allocator - shmem_allocator_int_t; - const int num_elements = 100; - - //Type of shared memory vector - typedef std::vector MyVect; - - const shmem_allocator_int_t alloc_inst (segment.get_segment_manager()); - - //Creating the vector in shared memory - std::cout << "Named New of ShmVect\n\n"; - MyVect *shmem_vect = segment.construct ("ShmVect")(alloc_inst); - - offset_ptr shmptr_vect = 0; - offset_ptr other_shmptr_vect = 0; - - //Fill the vector - std::cout << "Filling ShmVect\n\n"; - int i; - for(i = 0; i < num_elements; ++i){ - shmem_vect->push_back(i); - } - - //Printing contents before waiting to second process - PrintContents(*shmem_vect, "ShmVect"); - - //Wake up other process and sleeping until notified - semB.post(); - std::cout << "Waking up processB and waiting sorting\n\n"; - semA.wait(); - - //Notification received, let's see the changes - std::cout << "processB sorting complete\n\n"; - PrintContents(*shmem_vect, "ShmVect"); - - //Let's delete the vector from memory - std::cout << "Deleting the vector with destroy\n\n"; - segment.destroy ("ShmVect"); - std::cout << "vector deleted\n\n"; - return 0; -} - -#include diff --git a/example/Attic/process_b_example.cpp b/example/Attic/process_b_example.cpp deleted file mode 100644 index 01fb495..0000000 --- a/example/Attic/process_b_example.cpp +++ /dev/null @@ -1,71 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztañaga 2004-2006. Distributed under the Boost -// Software License, Version 1.0. (See accompanying file -// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/interprocess for documentation. -// -////////////////////////////////////////////////////////////////////////////// -#include -#include - -#include -#include -#include -#include - -#include "print_container.hpp" -#include - -using namespace boost::interprocess; - -int main () -{ - //Shared memory attributes - const char *const shMemName = "MySharedMemory"; - - //Create sems for synchronization - named_semaphore semA(open_or_create, "processAsem", 0); - named_semaphore semB(open_or_create, "processBsem", 0); - - //Wait until the shared memory is ready - semB.wait(); - - //Create shared memory - managed_shared_memory segment(open_or_create, shMemName, 65536); - - //STL compatible allocator object, uses allocate(), deallocate() functions - typedef allocator - shmem_allocator_int_t; - - //This is the shared memory vector type - typedef vector MyVect; - - //Finding vector in shared memory and printing contents - std::cout << "Connecting to object ShmVect\n\n"; - MyVect *shmem_vect = segment.find("ShmVect").first; - PrintContents(*shmem_vect, "ShmVect"); - - //Reverse sorting the vector with std::sort - std::cout << "Reverse sorting ShmVect\n\n"; - MyVect::reverse_iterator rbeg = - shmem_vect->rbegin(), rend = shmem_vect->rend(); - std::sort(shmem_vect->rbegin(), shmem_vect->rend()); - std::sort(rbeg, rend); - - //Printing values after sorting - std::cout << "Sorting complete\n\n"; - PrintContents(*shmem_vect, "ShmVect"); - - //Waking up process A - std::cout << "Waking up processA\n\n"; - semA.post(); - - //We're done, closing shared memory - std::cout << "Closing shmem segment\n\n"; - - return 0; -} - -#include diff --git a/example/Attic/process_b_fixed_example.cpp b/example/Attic/process_b_fixed_example.cpp deleted file mode 100644 index 1807cf8..0000000 --- a/example/Attic/process_b_fixed_example.cpp +++ /dev/null @@ -1,69 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztañaga 2004-2006. Distributed under the Boost -// Software License, Version 1.0. (See accompanying file -// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/interprocess for documentation. -// -////////////////////////////////////////////////////////////////////////////// -#include -#include - -#include -#include -#include - -#include "print_container.hpp" -#include -#include - -using namespace boost::interprocess; - -int main () -{ - //Shared memory attributes - const char *const shMemName = "MySharedMemory"; - const void *const map_addr = reinterpret_cast(0x30000000); - - //Create sems for synchronization - named_semaphore semA(open_or_create, "processAsem", 1); - named_semaphore semB(open_or_create, "processBsem", 1); - - //Wait until the shared memory is ready - semB.wait(); - - //Create shared memory - fixed_managed_shared_memory segment(open_only, shMemName, map_addr); - - //STL compatible allocator object, uses allocate(), deallocate() functions - typedef allocator - shmem_allocator_int_t; - - //This is the shared memory vector type - typedef std::vector MyVect; - - //Finding vector in shared memory and printing contents - std::cout << "Connecting to object ShmVect\n\n"; - MyVect *shmem_vect = segment.find("ShmVect").first; - PrintContents(*shmem_vect, "ShmVect"); - - //Reverse sorting the vector with std::sort - std::cout << "Reverse sorting ShmVect\n\n"; - std::sort(shmem_vect->rbegin(), shmem_vect->rend()); - - //Printing values after sorting - std::cout << "Sorting complete\n\n"; - PrintContents(*shmem_vect, "ShmVect"); - - //Waking up process A - std::cout << "Waking up processA\n\n"; - semA.post(); - - //We're done, closing shared memory - std::cout << "Closing shmem segment\n\n"; - return 0; -} - -#include - diff --git a/doc/code/Attic/Jamfile.v2 b/example/Jamfile.v2 similarity index 79% rename from doc/code/Attic/Jamfile.v2 rename to example/Jamfile.v2 index 7341f24..eb9d49c 100644 --- a/doc/code/Attic/Jamfile.v2 +++ b/example/Jamfile.v2 @@ -1,6 +1,6 @@ -# Boost Interprocess Library Documentation test Jamfile +# Boost Interprocess Library Example Jamfile -# (C) Copyright Ion Gaztañaga 2006. +# (C) Copyright Ion Gaztañaga 2006. # Use, modification and distribution are subject to the # Boost Software License, Version 1.0. (See accompanying file # LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -21,14 +21,14 @@ rule test_all for local fileb in [ glob *.cpp ] { - all_rules += [ compile $(fileb) + all_rules += [ link $(fileb) /boost/thread//boost_thread : # additional args : # test-files : # requirements - ] ; + ] ; } return $(all_rules) ; } -test-suite interprocess_doc : [ test_all r ] ; \ No newline at end of file +test-suite interprocess_example : [ test_all r ] ; \ No newline at end of file diff --git a/example/doc_adaptive_pool.cpp b/example/doc_adaptive_pool.cpp new file mode 100644 index 0000000..53c96fc --- /dev/null +++ b/example/doc_adaptive_pool.cpp @@ -0,0 +1,64 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2006-2007. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#include +#include +//[doc_adaptive_pool +#include +#include +#include + +using namespace boost::interprocess; + +int main () +{ + shared_memory_object::remove("MySharedMemory"); + + try{ + //Create shared memory + managed_shared_memory segment(create_only, + "MySharedMemory", //segment name + 65536); + + //Create a adaptive_pool that allocates ints from the managed segment + //The number of chunks per segment is the default value + typedef adaptive_pool + adaptive_pool_t; + adaptive_pool_t allocator_instance(segment.get_segment_manager()); + + //Create another adaptive_pool. Since the segment manager address + //is the same, this adaptive_pool will be + //attached to the same pool so "allocator_instance2" can deallocate + //nodes allocated by "allocator_instance" + adaptive_pool_t allocator_instance2(segment.get_segment_manager()); + + //Create another adaptive_pool using copy-constructor. This + //adaptive_pool will also be attached to the same pool + adaptive_pool_t allocator_instance3(allocator_instance2); + + //All allocators are equal + assert(allocator_instance == allocator_instance2); + assert(allocator_instance2 == allocator_instance3); + + //So memory allocated with one can be deallocated with another + allocator_instance2.deallocate(allocator_instance.allocate(1), 1); + allocator_instance3.deallocate(allocator_instance2.allocate(1), 1); + + //The common pool will be destroyed here, since no allocator is + //attached to the pool + } + catch(...){ + shared_memory_object::remove("MySharedMemory"); + throw; + } + shared_memory_object::remove("MySharedMemory"); + return 0; +} +//] +#include diff --git a/example/doc_allocator.cpp b/example/doc_allocator.cpp new file mode 100644 index 0000000..874913f --- /dev/null +++ b/example/doc_allocator.cpp @@ -0,0 +1,43 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2006-2007. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#include +#include +//[doc_allocator +#include +#include +#include + +using namespace boost::interprocess; + +int main () +{ + shared_memory_object::remove("MySharedMemory"); + + //Create shared memory + managed_shared_memory segment(create_only, + "MySharedMemory", //segment name + 65536); + + //Create an allocator that allocates ints from the managed segment + allocator + allocator_instance(segment.get_segment_manager()); + + //Copy constructed allocator is equal + allocator + allocator_instance2(allocator_instance); + assert(allocator_instance2 == allocator_instance); + + //Allocate and deallocate memory for 100 ints + allocator_instance2.deallocate(allocator_instance.allocate(100), 100); + + return 0; +} +//] +#include diff --git a/example/doc_anonymous_conditionA.cpp b/example/doc_anonymous_conditionA.cpp new file mode 100644 index 0000000..926fa05 --- /dev/null +++ b/example/doc_anonymous_conditionA.cpp @@ -0,0 +1,77 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2006-2007. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +//[doc_anonymous_conditionA +#include +#include +#include +#include +#include +#include "doc_anonymous_condition_shared_data.hpp" + +using namespace boost::interprocess; + +int main () +{ + + //Erase previous shared memory + shared_memory_object::remove("shared_memory"); + + //Create a shared memory object. + shared_memory_object shm + (create_only //only create + ,"shared_memory" //name + ,read_write //read-write mode + ); + try{ + //Set size + shm.truncate(sizeof(trace_queue)); + + //Map the whole shared memory in this process + mapped_region region + (shm //What to map + ,read_write //Map it as read-write + ); + + //Get the address of the mapped region + void * addr = region.get_address(); + + //Construct the shared structure in memory + trace_queue * data = new (addr) trace_queue; + + const int NumMsg = 100; + + for(int i = 0; i < NumMsg; ++i){ + scoped_lock lock(data->mutex); + if(data->message_in){ + data->cond_full.wait(lock); + } + if(i == (NumMsg-1)) + std::sprintf(data->items, "%s", "last message"); + else + std::sprintf(data->items, "%s_%d", "my_trace", i); + + //Notify to the other process that there is a message + data->cond_empty.notify_one(); + + //Mark message buffer as full + data->message_in = true; + } + } + catch(interprocess_exception &ex){ + shared_memory_object::remove("shared_memory"); + std::cout << ex.what() << std::endl; + return 1; + } + + //Erase shared memory + shared_memory_object::remove("shared_memory"); + return 0; +} +//] diff --git a/example/doc_anonymous_conditionB.cpp b/example/doc_anonymous_conditionB.cpp new file mode 100644 index 0000000..6aa540d --- /dev/null +++ b/example/doc_anonymous_conditionB.cpp @@ -0,0 +1,72 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2006-2007. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +//[doc_anonymous_conditionB +#include +#include +#include +#include +#include +#include "doc_anonymous_condition_shared_data.hpp" + +using namespace boost::interprocess; + +int main () +{ + //Create a shared memory object. + shared_memory_object shm + (open_only //only create + ,"shared_memory" //name + ,read_write //read-write mode + ); + + try{ + //Map the whole shared memory in this process + mapped_region region + (shm //What to map + ,read_write //Map it as read-write + ); + + //Get the address of the mapped region + void * addr = region.get_address(); + + //Obtain a pointer to the shared structure + trace_queue * data = static_cast(addr); + + //Print messages until the other process marks the end + bool end_loop = false; + do{ + scoped_lock lock(data->mutex); + if(!data->message_in){ + data->cond_empty.wait(lock); + } + if(std::strcmp(data->items, "last message") == 0){ + end_loop = true; + } + else{ + //Print the message + std::cout << data->items << std::endl; + //Notify the other process that the buffer is empty + data->message_in = false; + data->cond_full.notify_one(); + } + } + while(!end_loop); + } + catch(interprocess_exception &ex){ + shared_memory_object::remove("shared_memory"); + std::cout << ex.what() << std::endl; + return 1; + } + + //Erase shared memory + shared_memory_object::remove("shared_memory"); + return 0; +} +//] diff --git a/example/doc_anonymous_condition_shared_data.hpp b/example/doc_anonymous_condition_shared_data.hpp new file mode 100644 index 0000000..258643a --- /dev/null +++ b/example/doc_anonymous_condition_shared_data.hpp @@ -0,0 +1,37 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2006-2007. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +//[doc_anonymous_condition_shared_data +#include +#include + +struct trace_queue +{ + enum { LineSize = 100 }; + + trace_queue() + : message_in(false) + {} + + //Mutex to protect access to the queue + boost::interprocess::interprocess_mutex mutex; + + //Condition to wait when the queue is empty + boost::interprocess::interprocess_condition cond_empty; + + //Condition to wait when the queue is full + boost::interprocess::interprocess_condition cond_full; + + //Items to fill + char items[LineSize]; + + //Is there any message + bool message_in; +}; +//] diff --git a/example/doc_anonymous_mutexA.cpp b/example/doc_anonymous_mutexA.cpp new file mode 100644 index 0000000..8de1f24 --- /dev/null +++ b/example/doc_anonymous_mutexA.cpp @@ -0,0 +1,75 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2006-2007. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +//[doc_anonymous_mutexA +#include +#include +#include +#include "doc_anonymous_mutex_shared_data.hpp" +#include +#include + +using namespace boost::interprocess; + +int main () +{ + try{ + //Erase previous shared memory + shared_memory_object::remove("shared_memory"); + + //Create a shared memory object. + shared_memory_object shm + (create_only //only create + ,"shared_memory" //name + ,read_write //read-write mode + ); + + //Set size + shm.truncate(sizeof(shared_memory_log)); + + //Map the whole shared memory in this process + mapped_region region + (shm //What to map + ,read_write //Map it as read-write + ); + + //Get the address of the mapped region + void * addr = region.get_address(); + + //Construct the shared structure in memory + shared_memory_log * data = new (addr) shared_memory_log; + + //Write some logs + for(int i = 0; i < shared_memory_log::NumItems; ++i){ + //Lock the mutex + scoped_lock lock(data->mutex); + std::sprintf(data->items[(data->current_line++) % shared_memory_log::NumItems] + ,"%s_%d", "process_a", i); + if(i == (shared_memory_log::NumItems-1)) + data->end_a = true; + //Mutex is released here + } + + //Wait until the other process ends + while(1){ + scoped_lock lock(data->mutex); + if(data->end_b) + break; + } + } + catch(interprocess_exception &ex){ + shared_memory_object::remove("shared_memory"); + std::cout << ex.what() << std::endl; + return 1; + } + //Erase shared memory + shared_memory_object::remove("shared_memory"); + return 0; +} +//] diff --git a/example/doc_anonymous_mutexB.cpp b/example/doc_anonymous_mutexB.cpp new file mode 100644 index 0000000..2d3cc15 --- /dev/null +++ b/example/doc_anonymous_mutexB.cpp @@ -0,0 +1,68 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2006-2007. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +//[doc_anonymous_mutexB +#include +#include +#include +#include "doc_anonymous_mutex_shared_data.hpp" +#include +#include + +using namespace boost::interprocess; + +int main () +{ + try{ + //Open the shared memory object. + shared_memory_object shm + (open_only //only create + ,"shared_memory" //name + ,read_write //read-write mode + ); + + //Map the whole shared memory in this process + mapped_region region + (shm //What to map + ,read_write //Map it as read-write + ); + + //Get the address of the mapped region + void * addr = region.get_address(); + + //Construct the shared structure in memory + shared_memory_log * data = static_cast(addr); + + //Write some logs + for(int i = 0; i < 100; ++i){ + //Lock the mutex + scoped_lock lock(data->mutex); + std::sprintf(data->items[(data->current_line++) % shared_memory_log::NumItems] + ,"%s_%d", "process_a", i); + if(i == (shared_memory_log::NumItems-1)) + data->end_b = true; + //Mutex is released here + } + + //Wait until the other process ends + while(1){ + scoped_lock lock(data->mutex); + if(data->end_a) + break; + } + } + catch(interprocess_exception &ex){ + shared_memory_object::remove("shared_memory"); + std::cout << ex.what() << std::endl; + return 1; + } + shared_memory_object::remove("shared_memory"); + return 0; +} +//] diff --git a/example/doc_anonymous_mutex_shared_data.hpp b/example/doc_anonymous_mutex_shared_data.hpp new file mode 100644 index 0000000..107e345 --- /dev/null +++ b/example/doc_anonymous_mutex_shared_data.hpp @@ -0,0 +1,33 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2006-2007. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +//[doc_anonymous_mutex_shared_data +#include + +struct shared_memory_log +{ + enum { NumItems = 100 }; + enum { LineSize = 100 }; + + shared_memory_log() + : current_line(0) + , end_a(false) + , end_b(false) + {} + + //Mutex to protect access to the queue + boost::interprocess::interprocess_mutex mutex; + + //Items to fill + char items[NumItems][LineSize]; + int current_line; + bool end_a; + bool end_b; +}; +//] diff --git a/example/doc_anonymous_semaphoreA.cpp b/example/doc_anonymous_semaphoreA.cpp new file mode 100644 index 0000000..455b93e --- /dev/null +++ b/example/doc_anonymous_semaphoreA.cpp @@ -0,0 +1,68 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2006-2007. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +//[doc_anonymous_semaphoreA +#include +#include +#include +#include "doc_anonymous_semaphore_shared_data.hpp" + +using namespace boost::interprocess; + +int main () +{ + try{ + //Erase previous shared memory + shared_memory_object::remove("shared_memory"); + + //Create a shared memory object. + shared_memory_object shm + (create_only //only create + ,"shared_memory" //name + ,read_write //read-write mode + ); + + //Set size + shm.truncate(sizeof(shared_memory_buffer)); + + //Map the whole shared memory in this process + mapped_region region + (shm //What to map + ,read_write //Map it as read-write + ); + + //Get the address of the mapped region + void * addr = region.get_address(); + + //Construct the shared structure in memory + shared_memory_buffer * data = new (addr) shared_memory_buffer; + + const int NumMsg = 100; + + //Insert data in the array + for(int i = 0; i < NumMsg; ++i){ + data->nempty.wait(); + data->mutex.wait(); + data->items[i % shared_memory_buffer::NumItems] = i; + data->mutex.post(); + data->nstored.post(); + } + } + catch(interprocess_exception &ex){ + shared_memory_object::remove("shared_memory"); + std::cout << ex.what() << std::endl; + return 1; + } + + //Erase shared memory + shared_memory_object::remove("shared_memory"); + + return 0; +} +//] diff --git a/example/doc_anonymous_semaphoreB.cpp b/example/doc_anonymous_semaphoreB.cpp new file mode 100644 index 0000000..767e7d0 --- /dev/null +++ b/example/doc_anonymous_semaphoreB.cpp @@ -0,0 +1,64 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2006-2007. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +//[doc_anonymous_semaphoreB +#include +#include +#include +#include "doc_anonymous_semaphore_shared_data.hpp" + +using namespace boost::interprocess; + +int main () +{ + try{ + //Create a shared memory object. + shared_memory_object shm + (open_only //only create + ,"shared_memory" //name + ,read_write //read-write mode + ); + + //Map the whole shared memory in this process + mapped_region region + (shm //What to map + ,read_write //Map it as read-write + ); + + //Get the address of the mapped region + void * addr = region.get_address(); + + //Obtain the shared structure + shared_memory_buffer * data = static_cast(addr); + + const int NumMsg = 100; + + int extracted_data [NumMsg]; + + //Extract the data + for(int i = 0; i < NumMsg; ++i){ + data->nstored.wait(); + data->mutex.wait(); + extracted_data[i] = data->items[i % shared_memory_buffer::NumItems]; + data->mutex.post(); + data->nempty.post(); + } + } + catch(interprocess_exception &ex){ + shared_memory_object::remove("shared_memory"); + std::cout << ex.what() << std::endl; + return 1; + } + + //Erase shared memory + shared_memory_object::remove("shared_memory"); + + return 0; +} +//] diff --git a/example/doc_anonymous_semaphore_shared_data.hpp b/example/doc_anonymous_semaphore_shared_data.hpp new file mode 100644 index 0000000..1162722 --- /dev/null +++ b/example/doc_anonymous_semaphore_shared_data.hpp @@ -0,0 +1,28 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2006-2007. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +//[doc_anonymous_semaphore_shared_data +#include + +struct shared_memory_buffer +{ + enum { NumItems = 10 }; + + shared_memory_buffer() + : mutex(1), nempty(NumItems), nstored(0) + {} + + //Semaphores to protect and synchronize access + boost::interprocess::interprocess_semaphore + mutex, nempty, nstored; + + //Items to fill + int items[NumItems]; +}; +//] diff --git a/example/doc_anonymous_upgradable_mutexA.cpp b/example/doc_anonymous_upgradable_mutexA.cpp new file mode 100644 index 0000000..1d51e73 --- /dev/null +++ b/example/doc_anonymous_upgradable_mutexA.cpp @@ -0,0 +1,77 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2006-2007. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +//[doc_anonymous_upgradable_mutexA +#include +#include +#include +#include "doc_upgradable_mutex_shared_data.hpp" +#include +#include + +using namespace boost::interprocess; + +int main () +{ + try{ + //Erase previous shared memory + shared_memory_object::remove("shared_memory"); + + //Create a shared memory object. + shared_memory_object shm + (create_only //only create + ,"shared_memory" //name + ,read_write //read-write mode + ); + + //Set size + shm.truncate(sizeof(shared_data)); + + //Map the whole shared memory in this process + mapped_region region + (shm //What to map + ,read_write //Map it as read-write + ); + + //Get the address of the mapped region + void * addr = region.get_address(); + + //Construct the shared structure in memory + shared_data * data = new (addr) shared_data; + + //Write some logs + for(int i = 0; i < shared_data::NumItems; ++i){ + //Lock the upgradable_mutex + scoped_lock lock(data->upgradable_mutex); + std::sprintf(data->items[(data->current_line++) % shared_data::NumItems] + ,"%s_%d", "process_a", i); + if(i == (shared_data::NumItems-1)) + data->end_a = true; + //Mutex is released here + } + + //Wait until the other process ends + while(1){ + scoped_lock lock(data->upgradable_mutex); + if(data->end_b) + break; + } + } + catch(interprocess_exception &ex){ + shared_memory_object::remove("shared_memory"); + std::cout << ex.what() << std::endl; + return 1; + } + + //Erase shared memory + shared_memory_object::remove("shared_memory"); + + return 0; +} +//] \ No newline at end of file diff --git a/example/doc_anonymous_upgradable_mutexB.cpp b/example/doc_anonymous_upgradable_mutexB.cpp new file mode 100644 index 0000000..7bd3bfa --- /dev/null +++ b/example/doc_anonymous_upgradable_mutexB.cpp @@ -0,0 +1,68 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2006-2007. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +//[doc_anonymous_upgradable_mutexB +#include +#include +#include +#include "doc_upgradable_mutex_shared_data.hpp" +#include +#include + +using namespace boost::interprocess; + +int main () +{ + try{ + //Open the shared memory object. + shared_memory_object shm + (open_only //only create + ,"shared_memory" //name + ,read_write //read-write mode + ); + + //Map the whole shared memory in this process + mapped_region region + (shm //What to map + ,read_write //Map it as read-write + ); + + //Get the address of the mapped region + void * addr = region.get_address(); + + //Construct the shared structure in memory + shared_data * data = static_cast(addr); + + //Write some logs + for(int i = 0; i < 100; ++i){ + //Lock the upgradable_mutex + scoped_lock lock(data->upgradable_mutex); + std::sprintf(data->items[(data->current_line++) % shared_data::NumItems] + ,"%s_%d", "process_a", i); + if(i == (shared_data::NumItems-1)) + data->end_b = true; + //Mutex is released here + } + + //Wait until the other process ends + while(1){ + scoped_lock lock(data->upgradable_mutex); + if(data->end_a) + break; + } + } + catch(interprocess_exception &ex){ + shared_memory_object::remove("shared_memory"); + std::cout << ex.what() << std::endl; + return 1; + } + shared_memory_object::remove("shared_memory"); + return 0; +} +//] diff --git a/doc/code/Attic/doc_bufferstream.cpp b/example/doc_bufferstream.cpp similarity index 59% rename from doc/code/Attic/doc_bufferstream.cpp rename to example/doc_bufferstream.cpp index 79fb25e..da32f15 100644 --- a/doc/code/Attic/doc_bufferstream.cpp +++ b/example/doc_bufferstream.cpp @@ -1,20 +1,30 @@ - #include - #include +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2006-2007. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#include +#include +//[doc_bufferstream +#include +#include +#include +#include - #include - #include - #include - #include - - using namespace boost::interprocess; +using namespace boost::interprocess; - int main () - { - shared_memory_object::remove("MySharedMemory"); +int main () +{ + shared_memory_object::remove("MySharedMemory"); + try{ //Create shared memory managed_shared_memory segment(create_only, - "MySharedMemory", //segment name - 65536); + "MySharedMemory", //segment name + 65536); //Fill data std::vector data, data2; @@ -63,8 +73,14 @@ //which means overflow attempt. assert(!mybufstream.good()); assert(mybufstream.bad()); - segment.destroy_ptr(my_cstring); - return 0; + segment.destroy_ptr(my_cstring); } - - #include + catch(...){ + shared_memory_object::remove("MySharedMemory"); + throw; + } + shared_memory_object::remove("MySharedMemory"); + return 0; +} +//] +#include diff --git a/example/doc_cached_adaptive_pool.cpp b/example/doc_cached_adaptive_pool.cpp new file mode 100644 index 0000000..90a39ad --- /dev/null +++ b/example/doc_cached_adaptive_pool.cpp @@ -0,0 +1,72 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2006-2007. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#include +#include +//[doc_cached_adaptive_pool +#include +#include +#include + +using namespace boost::interprocess; + +int main () +{ + shared_memory_object::remove("MySharedMemory"); + try{ + //Create shared memory + managed_shared_memory segment(create_only, + "MySharedMemory", //segment name + 65536); + + //Create a cached_adaptive_pool that allocates ints from the managed segment + //The number of chunks per segment is the default value + typedef cached_adaptive_pool + cached_adaptive_pool_t; + cached_adaptive_pool_t allocator_instance(segment.get_segment_manager()); + + //The max cached nodes are configurable per instance + allocator_instance.set_max_cached_nodes(3); + + //Create another cached_adaptive_pool. Since the segment manager address + //is the same, this cached_adaptive_pool will be + //attached to the same pool so "allocator_instance2" can deallocate + //nodes allocated by "allocator_instance" + cached_adaptive_pool_t allocator_instance2(segment.get_segment_manager()); + + //The max cached nodes are configurable per instance + allocator_instance2.set_max_cached_nodes(5); + + //Create another cached_adaptive_pool using copy-constructor. This + //cached_adaptive_pool will also be attached to the same pool + cached_adaptive_pool_t allocator_instance3(allocator_instance2); + + //We can clear the cache + allocator_instance3.deallocate_cache(); + + //All allocators are equal + assert(allocator_instance == allocator_instance2); + assert(allocator_instance2 == allocator_instance3); + + //So memory allocated with one can be deallocated with another + allocator_instance2.deallocate(allocator_instance.allocate(1), 1); + allocator_instance3.deallocate(allocator_instance2.allocate(1), 1); + + //The common pool will be destroyed here, since no allocator is + //attached to the pool + } + catch(...){ + shared_memory_object::remove("MySharedMemory"); + throw; + } + shared_memory_object::remove("MySharedMemory"); + return 0; +} +//] +#include diff --git a/example/doc_cached_node_allocator.cpp b/example/doc_cached_node_allocator.cpp new file mode 100644 index 0000000..fc562f2 --- /dev/null +++ b/example/doc_cached_node_allocator.cpp @@ -0,0 +1,72 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2006-2007. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#include +#include +//[doc_cached_node_allocator +#include +#include +#include + +using namespace boost::interprocess; + +int main () +{ + shared_memory_object::remove("MySharedMemory"); + try{ + //Create shared memory + managed_shared_memory segment(create_only, + "MySharedMemory", //segment name + 65536); + + //Create a cached_node_allocator that allocates ints from the managed segment + //The number of chunks per segment is the default value + typedef cached_node_allocator + cached_node_allocator_t; + cached_node_allocator_t allocator_instance(segment.get_segment_manager()); + + //The max cached nodes are configurable per instance + allocator_instance.set_max_cached_nodes(3); + + //Create another cached_node_allocator. Since the segment manager address + //is the same, this cached_node_allocator will be + //attached to the same pool so "allocator_instance2" can deallocate + //nodes allocated by "allocator_instance" + cached_node_allocator_t allocator_instance2(segment.get_segment_manager()); + + //The max cached nodes are configurable per instance + allocator_instance2.set_max_cached_nodes(5); + + //Create another cached_node_allocator using copy-constructor. This + //cached_node_allocator will also be attached to the same pool + cached_node_allocator_t allocator_instance3(allocator_instance2); + + //We can clear the cache + allocator_instance3.deallocate_cache(); + + //All allocators are equal + assert(allocator_instance == allocator_instance2); + assert(allocator_instance2 == allocator_instance3); + + //So memory allocated with one can be deallocated with another + allocator_instance2.deallocate(allocator_instance.allocate(1), 1); + allocator_instance3.deallocate(allocator_instance2.allocate(1), 1); + + //The common pool will be destroyed here, since no allocator is + //attached to the pool + } + catch(...){ + shared_memory_object::remove("MySharedMemory"); + throw; + } + shared_memory_object::remove("MySharedMemory"); + return 0; +} +//] +#include diff --git a/doc/code/Attic/doc_cont.cpp b/example/doc_cont.cpp similarity index 53% rename from doc/code/Attic/doc_cont.cpp rename to example/doc_cont.cpp index 5b6f3f9..4739244 100644 --- a/doc/code/Attic/doc_cont.cpp +++ b/example/doc_cont.cpp @@ -1,20 +1,28 @@ - #include - #include +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2006-2007. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#include +#include +//[doc_cont +#include +#include - #include - #include - #include - - int main () - { - using namespace boost::interprocess; - - shared_memory_object::remove("MySharedMemory"); +int main () +{ + using namespace boost::interprocess; + shared_memory_object::remove("MySharedMemory"); + try{ //A managed shared memory where we can construct objects //associated with a c-string managed_shared_memory segment(create_only, - "MySharedMemory", //segment name - 65536); + "MySharedMemory", //segment name + 65536); //Alias an STL-like allocator of ints that allocates ints from the segment typedef allocator @@ -34,8 +42,8 @@ //from a range of iterators MyVector *myvector = segment.construct - ("MyVector")/*object name*/ - (begVal /*first ctor parameter*/, + ("MyVector")/*object name*/ + (begVal /*first ctor parameter*/, endVal /*second ctor parameter*/, alloc_inst /*third ctor parameter*/); @@ -44,7 +52,13 @@ // . . . //When done, destroy and delete vector from the segment segment.destroy("MyVector"); - return 0; } - - #include + catch(...){ + shared_memory_object::remove("MySharedMemory"); + throw; + } + shared_memory_object::remove("MySharedMemory"); + return 0; +} +//] +#include diff --git a/doc/code/Attic/doc_contA.cpp b/example/doc_contA.cpp similarity index 55% rename from doc/code/Attic/doc_contA.cpp rename to example/doc_contA.cpp index f8da9eb..52efce5 100644 --- a/doc/code/Attic/doc_contA.cpp +++ b/example/doc_contA.cpp @@ -1,13 +1,23 @@ - #include - #include +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2006-2007. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#include +#include +//[doc_contA +#include +#include +#include - #include - #include - #include - - int main () - { - using namespace boost::interprocess; +int main () +{ + using namespace boost::interprocess; + try{ //Shared memory front-end that is able to construct objects //associated with a c-string. Erase previous shared memory with the name //to be used and create the memory segment at the specified address and initialize resources @@ -29,7 +39,7 @@ //Initialize shared memory STL-compatible allocator const ShmemAllocator alloc_inst (segment.get_segment_manager()); - //Construct a shared memory vector vector + //Construct a shared memory MyVector *myvector = segment.construct("MyVector") //object name (alloc_inst);//first ctor parameter @@ -38,8 +48,13 @@ for(int i = 0; i < 100; ++i){ myvector->push_back(i); } - - return 0; } - - #include + catch(...){ + shared_memory_object::remove("MySharedMemory"); + throw; + } + shared_memory_object::remove("MySharedMemory"); + return 0; +} +//] +#include diff --git a/doc/code/Attic/doc_contB.cpp b/example/doc_contB.cpp similarity index 51% rename from doc/code/Attic/doc_contB.cpp rename to example/doc_contB.cpp index 5a422eb..43eed90 100644 --- a/doc/code/Attic/doc_contB.cpp +++ b/example/doc_contB.cpp @@ -1,15 +1,24 @@ - #include - #include - - #include - #include - #include - #include - - int main () - { - using namespace boost::interprocess; +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2006-2007. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#include +#include +//[doc_contB +#include +#include +#include +#include +int main () +{ + using namespace boost::interprocess; + try{ //An special shared memory where we can //construct objects associated with a name. //Connect to the already created shared memory segment @@ -36,7 +45,13 @@ //When done, destroy the vector from the segment segment.destroy("MyVector"); - return 0; } - - #include + catch(...){ + shared_memory_object::remove("MySharedMemory"); + throw; + } + shared_memory_object::remove("MySharedMemory"); + return 0; +} +//] +#include diff --git a/example/doc_file_mapping.cpp b/example/doc_file_mapping.cpp new file mode 100644 index 0000000..79ffa1e --- /dev/null +++ b/example/doc_file_mapping.cpp @@ -0,0 +1,60 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2006-2007. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +//[doc_file_mapping +#include +#include +#include +#include +#include +#include + +int main () +{ + using namespace boost::interprocess; + try{ + //Create a file + std::filebuf fbuf; + fbuf.open("file.bin", std::ios_base::in | std::ios_base::out + | std::ios_base::trunc | std::ios_base::binary); + + //Set the size + fbuf.pubseekoff(9999, std::ios_base::beg); + fbuf.sputc(0); + fbuf.close(); + + //Create a file mapping. + file_mapping m_file("file.bin", read_write); + + //Map the whole file in this process + mapped_region region + (m_file //What to map + ,read_write //Map it as read-write + ); + + if(region.get_size() != 10000) + return 1; + + //Get the address of the mapped region + void * addr = region.get_address(); + std::size_t size = region.get_size(); + + //Write all the memory to 1 + std::memset(addr, 1, size); + + } + catch(interprocess_exception &ex){ + std::remove("file.bin"); + std::cout << ex.what() << std::endl; + return 1; + } + std::remove("file.bin"); + return 0; +} +//] diff --git a/example/doc_file_mapping2.cpp b/example/doc_file_mapping2.cpp new file mode 100644 index 0000000..977c088 --- /dev/null +++ b/example/doc_file_mapping2.cpp @@ -0,0 +1,71 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2006-2007. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +//[doc_file_mapping2 +#include +#include +#include +#include +#include +#include + +int main () +{ + using namespace boost::interprocess; + try{ + //Open the file mapping + file_mapping m_file ("file.bin", read_only); + + //Map the whole file in this process + mapped_region region + (m_file //What to map + ,read_only //Map it as read-only + ); + + //Get the address of the mapped region + void * addr = region.get_address(); + std::size_t size = region.get_size(); + + //Check that memory was initialized to 1 + const char *mem = static_cast(addr); + for(std::size_t i = 0; i < size; ++i){ + if(*mem++ != 1){ + std::cout << "Error checking memory!" << std::endl; + return 1; + } + } + + //Now test it reading the file + std::filebuf fbuf; + fbuf.open("file.bin", std::ios_base::in | std::ios_base::binary); + + //Read it to memory + std::vector vect(region.get_size(), 0); + fbuf.sgetn(&vect[0], std::streamsize(vect.size())); + + //Check that memory was initialized to 1 + mem = static_cast(&vect[0]); + for(std::size_t i = 0; i < size; ++i){ + if(*mem++ != 1){ + std::cout << "Error checking memory!" << std::endl; + return 1; + } + } + + std::cout << "Test successful!" << std::endl; + } + catch(interprocess_exception &ex){ + std::remove("file.bin"); + std::cout << "Unexpected exception: " << ex.what() << std::endl; + return 1; + } + std::remove("file.bin"); + return 0; +} +//] diff --git a/example/doc_intrusive.cpp b/example/doc_intrusive.cpp new file mode 100644 index 0000000..7df97b0 --- /dev/null +++ b/example/doc_intrusive.cpp @@ -0,0 +1,111 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2006-2007. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#include +#include +//[doc_intrusive +#include +#include + +using namespace boost::interprocess; + +namespace N { + +//A class that has an internal reference count +class reference_counted_class +{ + private: + //Non-copyable + reference_counted_class(const reference_counted_class &); + //Non-assignable + reference_counted_class & operator=(const reference_counted_class &); + //A typedef to save typing + typedef managed_shared_memory::segment_manager segment_manager; + //This is the reference count + unsigned int m_use_count; + //The segment manager allows deletion from shared memory segment + offset_ptr mp_segment_manager; + + public: + //Constructor + reference_counted_class(segment_manager *s_mngr) + : m_use_count(0), mp_segment_manager(s_mngr){} + //Destructor + ~reference_counted_class(){} + + public: + //Returns the reference count + unsigned int use_count() const + { return m_use_count; } + + //Adds a reference + inline friend void intrusive_ptr_add_ref(reference_counted_class * p) + { ++p->m_use_count; } + + //Releases a reference + inline friend void intrusive_ptr_release(reference_counted_class * p) + { if(--p->m_use_count == 0) p->mp_segment_manager->destroy_ptr(p); } +}; + +} //namespace N { + +//A class that has an intrusive pointer to reference_counted_class +class intrusive_ptr_owner +{ + typedef intrusive_ptr > intrusive_ptr_t; + intrusive_ptr_t m_intrusive_ptr; + + public: + //Takes a pointer to the reference counted class + intrusive_ptr_owner(N::reference_counted_class *ptr) + : m_intrusive_ptr(ptr){} +}; + +int main () +{ + shared_memory_object::remove("my_shmem"); + + try{ + //Create shared memory + managed_shared_memory shmem(create_only, "my_shmem", 10000); + + //Create the unique reference counted object in shared memory + N::reference_counted_class *ref_counted = + shmem.construct + ("ref_counted")(shmem.get_segment_manager()); + + //Create an array of ten intrusive pointer owners in shared memory + intrusive_ptr_owner *intrusive_owner_array = + shmem.construct + (anonymous_instance)[10](ref_counted); + + //Now test that reference count is ten + if(ref_counted->use_count() != 10) + return 1; + + //Now destroy the array of intrusive pointer owners + //This should destroy every intrusive_ptr and because of + //that reference_counted_class will be destroyed + shmem.destroy_ptr(intrusive_owner_array); + + //Now the reference counted object should have been destroyed + if(shmem.find("ref_counted").first) + return 1; + } + catch(...){ + shared_memory_object::remove("my_shmem"); + throw; + } + shared_memory_object::remove("my_shmem"); + //Success! + return 0; +} +//] +#include diff --git a/example/doc_ipc_messageA.cpp b/example/doc_ipc_messageA.cpp new file mode 100644 index 0000000..fc9b7b2 --- /dev/null +++ b/example/doc_ipc_messageA.cpp @@ -0,0 +1,55 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2006-2007. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#include +#include +//[doc_ipc_messageA +#include + +int main () +{ + using namespace boost::interprocess; + + //An special shared memory from which we are + //able to allocate raw memory buffers. + //First remove any old shared memory of the same name, create + //the shared memory segment and initialize needed resources + shared_memory_object::remove("MySharedMemory"); + try{ + managed_shared_memory segment + (create_only, + "MySharedMemory", //segment name + 65536); //segment size in bytes + + //Allocate a portion of the segment + void * shptr = segment.allocate(1024/*bytes to allocate*/); + + //An handle from the base address can identify any byte of the shared + //memory segment even if it is mapped in different base addresses + managed_shared_memory::handle_t handle = segment.get_handle_from_address(shptr); + (void)handle; + // Copy message to buffer + // . . . + // Send handle to other process + // . . . + // Wait response from other process + // . . . + + //Deallocate the portion previously allocated + segment.deallocate(shptr); + } + catch(...){ + shared_memory_object::remove("MySharedMemory"); + throw; + } + shared_memory_object::remove("MySharedMemory"); + return 0; +} +//] +#include diff --git a/example/Attic/alloc_example.cpp b/example/doc_ipc_messageB.cpp similarity index 54% rename from example/Attic/alloc_example.cpp rename to example/doc_ipc_messageB.cpp index 6054887..a654170 100644 --- a/example/Attic/alloc_example.cpp +++ b/example/doc_ipc_messageB.cpp @@ -1,65 +1,47 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztañaga 2004. Distributed under the Boost +// (C) Copyright Ion Gaztañaga 2006-2007. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // // See http://www.boost.org/libs/interprocess for documentation. // ////////////////////////////////////////////////////////////////////////////// - #include #include - +//[doc_ipc_messageB #include -#include int main () { using namespace boost::interprocess; - shared_memory_object::remove("MySharedMemory"); - - //Create managed shared memory - managed_shared_memory segment(create_only, - "MySharedMemory",//segment name - 65536); //segment size in bytes; - - //Allocate a portion of the segment - void * shptr = segment.allocate(1024); - managed_shared_memory::handle_t handle = segment.get_handle_from_address(shptr); - (void)handle; - - // Copy message to buffer - // . . . - // Send handle to other process - // . . . - // Wait response from other process - // . . . - - { - using namespace boost::interprocess; - - //Named allocate capable shared memory allocator - managed_shared_memory segment(open_only, "MySharedMemory"); + try{ + //An special shared memory from which we are + //able to allocate raw memory buffers. + //Connect to the already created shared memory segment + //and initialize needed resources + managed_shared_memory segment(open_only, "MySharedMemory"); //segment name + //An handle from the base address can identify any byte of the shared + //memory segment even if it is mapped in different base addresses managed_shared_memory::handle_t handle = 0; - (void)handle; - //Wait handle msg from other process and put it in + //Wait handle msg from the other process and put it in //"handle" local variable - //Get buffer local address from handle void *msg = segment.get_address_from_handle(handle); (void)msg; - //Do anything with msg //. . . //Send ack to sender process } - - segment.deallocate(shptr); + catch(...){ + shared_memory_object::remove("MySharedMemory"); + throw; + } + shared_memory_object::remove("MySharedMemory"); return 0; } - +//] #include diff --git a/example/doc_managed_aligned_allocation.cpp b/example/doc_managed_aligned_allocation.cpp new file mode 100644 index 0000000..cf98d97 --- /dev/null +++ b/example/doc_managed_aligned_allocation.cpp @@ -0,0 +1,67 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2006-2007. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +//[doc_managed_aligned_allocation +#include +#include + +int main() +{ + using namespace boost::interprocess; + + //Managed memory segment that allocates portions of a shared memory + //segment with the default management algorithm + shared_memory_object::remove("MyManagedShm"); + + try{ + managed_shared_memory managed_shm(create_only, "MyManagedShm", 65536); + + const std::size_t Alignment = 128; + + //Allocate 100 bytes aligned to Alignment from segment, throwing version + void *ptr = managed_shm.allocate_aligned(100, Alignment); + + //Check alignment + assert(((char*)ptr-(char*)0) % Alignment == 0); + + //Deallocate it + managed_shm.deallocate(ptr); + + //Non throwing version + ptr = managed_shm.allocate_aligned(100, Alignment, std::nothrow); + + //Check alignment + assert(((char*)ptr-(char*)0) % Alignment == 0); + + //Deallocate it + managed_shm.deallocate(ptr); + + //If we want to efficiently allocate aligned blocks of memory + //use managed_shared_memory::PayloadPerAllocation value + assert(Alignment > managed_shared_memory::PayloadPerAllocation); + + //This allocation will maximize the size of the aligned memory + //and will increase the possibility of finding more aligned memory + ptr = managed_shm.allocate_aligned + (Alignment - managed_shared_memory::PayloadPerAllocation, Alignment); + + //Check alignment + assert(((char*)ptr-(char*)0) % Alignment == 0); + + //Deallocate it + managed_shm.deallocate(ptr); + } + catch(...){ + shared_memory_object::remove("MyManagedShm"); + throw; + } + shared_memory_object::remove("MyManagedShm"); + return 0; +} +//] diff --git a/example/doc_managed_external_buffer.cpp b/example/doc_managed_external_buffer.cpp new file mode 100644 index 0000000..6546485 --- /dev/null +++ b/example/doc_managed_external_buffer.cpp @@ -0,0 +1,66 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2006-2007. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +//[doc_managed_external_buffer +#include +#include +#include +#include + +int main() +{ + using namespace boost::interprocess; + + //Create the static memory who will store all objects + const int memsize = 65536; + static char static_buffer [memsize]; + + //This managed memory will construct objects associated with + //a wide string in the static buffer + wmanaged_external_buffer objects_in_static_memory + (create_only, static_buffer, memsize); + + //We optimize resources to create 100 named objects in the static buffer + objects_in_static_memory.reserve_named_objects(100); + + //Alias a integer node allocator type + //This allocator will allocate memory inside the static buffer + typedef allocator + allocator_t; + + //Alias a STL compatible list to be constructed in the static buffer + typedef list MyBufferList; + + //The list must be initialized with the allocator + //All objects created with objects_in_static_memory will + //be stored in the static_buffer! + MyBufferList *list = objects_in_static_memory.construct(L"MyList") + (objects_in_static_memory.get_segment_manager()); + + //Since the allocation algorithm from wmanaged_external_buffer uses relative + //pointers and all the pointers constructed int the static memory point + //to objects in the same segment, we can create another static buffer + //from the first one and duplicate all the data. + static char static_buffer2 [memsize]; + std::memcpy(static_buffer2, static_buffer, memsize); + + //Now open the duplicated managed memory passing the memory as argument + wmanaged_external_buffer objects_in_static_memory2 + (open_only, static_buffer2, memsize); + + //Check that "MyList" has been duplicated in the second buffer + if(!objects_in_static_memory2.find(L"MyList").first) + return 1; + + //Destroy the lists from the static buffers + objects_in_static_memory.destroy(L"MyList"); + objects_in_static_memory2.destroy(L"MyList"); + return 0; +} +//] diff --git a/example/doc_managed_heap_memory.cpp b/example/doc_managed_heap_memory.cpp new file mode 100644 index 0000000..4bd02f8 --- /dev/null +++ b/example/doc_managed_heap_memory.cpp @@ -0,0 +1,75 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2006-2007. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#include +#include +//[doc_managed_heap_memory +#include +#include +#include +#include + +using namespace boost::interprocess; +typedef list > + MyList; + +int main () +{ + //We will create a buffer of 1000 bytes to store a list + managed_heap_memory heap_memory(1000); + + MyList * mylist = heap_memory.construct("MyList") + (heap_memory.get_segment_manager()); + + //Obtain handle, that identifies the list in the buffer + managed_heap_memory::handle_t list_handle = heap_memory.get_handle_from_address(mylist); + + //Fill list until there is no more memory in the buffer + try{ + while(1) { + mylist->insert(mylist->begin(), 0); + } + } + catch(const bad_alloc &){ + //memory is full + } + //Let's obtain the size of the list + std::size_t old_size = mylist->size(); + + //To make the list bigger, let's increase the heap buffer + //in 1000 bytes more. + heap_memory.grow(1000); + + //If memory has been reallocated, the old pointer is invalid, so + //use previously obtained handle to find the new pointer. + mylist = static_cast + (heap_memory.get_address_from_handle(list_handle)); + + //Fill list until there is no more memory in the buffer + try{ + while(1) { + mylist->insert(mylist->begin(), 0); + } + } + catch(const bad_alloc &){ + //memory is full + } + + //Let's obtain the new size of the list + std::size_t new_size = mylist->size(); + + assert(new_size > old_size); + + //Destroy list + heap_memory.destroy_ptr(mylist); + + return 0; +} +//] +#include diff --git a/doc/code/Attic/doc_managed_mapped_file.cpp b/example/doc_managed_mapped_file.cpp similarity index 56% rename from doc/code/Attic/doc_managed_mapped_file.cpp rename to example/doc_managed_mapped_file.cpp index f34a163..f8349ac 100644 --- a/doc/code/Attic/doc_managed_mapped_file.cpp +++ b/example/doc_managed_mapped_file.cpp @@ -1,21 +1,31 @@ - #include - #include +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2006-2007. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#include +#include - #include - #include - #include - #include - #include +#include +#include +#include +#include +#include - using namespace boost::interprocess; - typedef list > - MyList; +using namespace boost::interprocess; +typedef list > + MyList; - int main () - { - const char *FileName = "file_mapping"; - const std::size_t FileSize = 1000; - std::remove(FileName); +int main () +{ + const char *FileName = "file_mapping"; + const std::size_t FileSize = 1000; + std::remove(FileName); + try{ managed_mapped_file mfile_memory(create_only, FileName, FileSize); MyList * mylist = mfile_memory.construct("MyList") (mfile_memory.get_segment_manager()); @@ -37,7 +47,7 @@ //To make the list bigger, let's increase the mapped file //in FileSize bytes more. -// mfile_memory.grow(FileSize); + //mfile_memory.grow(FileSize); //If mapping address has changed, the old pointer is invalid, //so use previously obtained handle to find the new pointer. @@ -61,8 +71,13 @@ //Destroy list mfile_memory.destroy_ptr(mylist); - - return 0; } + catch(...){ + std::remove(FileName); + throw; + } + std::remove(FileName); + return 0; +} - #include +#include diff --git a/example/doc_managed_raw_allocation.cpp b/example/doc_managed_raw_allocation.cpp new file mode 100644 index 0000000..e55954a --- /dev/null +++ b/example/doc_managed_raw_allocation.cpp @@ -0,0 +1,42 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2006-2007. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +//[doc_managed_raw_allocation +#include + +int main() +{ + using namespace boost::interprocess; + + //Managed memory segment that allocates portions of a shared memory + //segment with the default management algorithm + shared_memory_object::remove("MyManagedShm"); + try{ + managed_shared_memory managed_shm(create_only, "MyManagedShm", 65536); + + //Allocate 100 bytes of memory from segment, throwing version + void *ptr = managed_shm.allocate(100); + + //Deallocate it + managed_shm.deallocate(ptr); + + //Non throwing version + ptr = managed_shm.allocate(100, std::nothrow); + + //Deallocate it + managed_shm.deallocate(ptr); + } + catch(...){ + shared_memory_object::remove("MyManagedShm"); + throw; + } + shared_memory_object::remove("MyManagedShm"); + return 0; +} +//] diff --git a/example/doc_map.cpp b/example/doc_map.cpp new file mode 100644 index 0000000..4594ecf --- /dev/null +++ b/example/doc_map.cpp @@ -0,0 +1,75 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2006-2007. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#include +#include +//[doc_map +#include +#include +#include +#include +#include + +int main () +{ + using namespace boost::interprocess; + //Shared memory front-end that is able to construct objects + //associated with a c-string. Erase previous shared memory with the name + //to be used and create the memory segment at the specified address and initialize resources + shared_memory_object::remove("MySharedMemory"); + + try{ + managed_shared_memory segment + (create_only + ,"MySharedMemory" //segment name + ,65536); //segment size in bytes + + //Note that map's value_type is std::pair, + //so the allocator must allocate that pair. + typedef int KeyType; + typedef float MappedType; + typedef std::pair ValueType; + + //Alias an STL compatible allocator of for the map. + //This allocator will allow to place containers + //in managed shared memory segments + typedef allocator + ShmemAllocator; + + //Alias a map of ints that uses the previous STL-like allocator. + //Note that the third parameter argument is the ordering function + //of the map, just like with std::map, used to compare the keys. + typedef map, ShmemAllocator> MyMap; + + //Initialize the shared memory STL-compatible allocator + ShmemAllocator alloc_inst (segment.get_segment_manager()); + + //Construct a shared memory map. + //Note that the first parameter is the comparison function, + //and the second one the allocator. + //This the same signature as std::map's constructor taking an allocator + MyMap *mymap = + segment.construct("MyMap") //object name + (std::less() //first ctor parameter + ,alloc_inst); //second ctor parameter + + //Insert data in the map + for(int i = 0; i < 100; ++i){ + mymap->insert(std::pair(i, (float)i)); + } + } + catch(...){ + shared_memory_object::remove("MySharedMemory"); + throw; + } + shared_memory_object::remove("MySharedMemory"); + return 0; +} +//] +#include diff --git a/example/doc_message_queueA.cpp b/example/doc_message_queueA.cpp new file mode 100644 index 0000000..966d051 --- /dev/null +++ b/example/doc_message_queueA.cpp @@ -0,0 +1,45 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2006-2007. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +//[doc_message_queueA +#include +#include +#include + +using namespace boost::interprocess; + +int main () +{ + try{ + //Erase previous message queue + message_queue::remove("message_queue"); + + //Create a message_queue. + message_queue mq + (create_only //only create + ,"message_queue" //name + ,100 //max message number + ,sizeof(int) //max message size + ); + + //Send 100 numbers + for(int i = 0; i < 100; ++i){ + mq.send(&i, sizeof(i), 0); + } + } + catch(interprocess_exception &ex){ + message_queue::remove("message_queue"); + std::cout << ex.what() << std::endl; + return 1; + } + message_queue::remove("message_queue"); + + return 0; +} +//] diff --git a/example/doc_message_queueB.cpp b/example/doc_message_queueB.cpp new file mode 100644 index 0000000..7dc46cd --- /dev/null +++ b/example/doc_message_queueB.cpp @@ -0,0 +1,45 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2006-2007. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +//[doc_message_queueB +#include +#include +#include + +using namespace boost::interprocess; + +int main () +{ + try{ + //Open a message queue. + message_queue mq + (open_only //only create + ,"message_queue" //name + ); + + unsigned int priority; + unsigned int recvd_size; + + //Receive 100 numbers + for(int i = 0; i < 100; ++i){ + int number; + mq.receive(&number, sizeof(number), recvd_size, priority); + if(number != i || recvd_size != sizeof(number)) + return 1; + } + } + catch(interprocess_exception &ex){ + message_queue::remove("message_queue"); + std::cout << ex.what() << std::endl; + return 1; + } + message_queue::remove("message_queue"); + return 0; +} +//] diff --git a/doc/code/Attic/doc_move_containers.cpp b/example/doc_move_containers.cpp similarity index 53% rename from doc/code/Attic/doc_move_containers.cpp rename to example/doc_move_containers.cpp index 6c0006e..dc338df 100644 --- a/doc/code/Attic/doc_move_containers.cpp +++ b/example/doc_move_containers.cpp @@ -1,26 +1,36 @@ - #include - #include +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2006-2007. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#include +#include +//[doc_move_containers +#include +#include +#include +#include +#include - #include - #include - #include - #include - #include +int main () +{ + using namespace boost::interprocess; - int main () - { - using namespace boost::interprocess; + //Typedefs + typedef managed_shared_memory::segment_manager SegmentManager; + typedef allocator CharAllocator; + typedef basic_string + ,CharAllocator> MyShmString; + typedef allocator StringAllocator; + typedef vector MyShmStringVector; - //Typedefs - typedef managed_shared_memory::segment_manager SegmentManager; - typedef allocator CharAllocator; - typedef basic_string - ,CharAllocator> MyShmString; - typedef allocator StringAllocator; - typedef vector MyShmStringVector; - - //Remove old shared memory and create new one - shared_memory_object::remove("myshm"); + //Remove old shared memory and create new one + shared_memory_object::remove("myshm"); + try{ managed_shared_memory shm(create_only, "myshm", 10000); //Create allocators @@ -63,7 +73,13 @@ //Destroy vector. This will free all strings that the vector contains shm.destroy_ptr(myshmvector); - return 0; } - - #include + catch(...){ + shared_memory_object::remove("myshmvector"); + throw; + } + shared_memory_object::remove("myshmvector"); + return 0; +} +//] +#include diff --git a/example/doc_named_allocA.cpp b/example/doc_named_allocA.cpp new file mode 100644 index 0000000..4f1f52e --- /dev/null +++ b/example/doc_named_allocA.cpp @@ -0,0 +1,50 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2006-2007. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#include +#include +//[doc_named_allocA +#include +#include + +int main () +{ + using namespace boost::interprocess; + typedef std::pair MyType; + + try{ + //An special shared memory where we can + //construct objects associated with a name. + //First remove any old shared memory of the same name, create + //the shared memory segment and initialize needed resources + shared_memory_object::remove("MySharedMemory"); + managed_shared_memory segment + //create segment name segment size + (create_only, "MySharedMemory", 65536); + + //Create an object of MyType initialized to {0.0, 0} + MyType *instance = segment.construct + ("MyType instance") //name of the object + (0.0, 0); //ctor second argument + + //Create an array of 10 elements of MyType initialized to {0.0, 0} + MyType *array = segment.construct + ("MyType array") //name of the object + [10] //number of elements + (0.0, 0); //ctor second argument + } + catch(...){ + shared_memory_object::remove("MySharedMemory"); + throw; + } + shared_memory_object::remove("MySharedMemory"); + return 0; +} +//] +#include diff --git a/example/doc_named_allocB.cpp b/example/doc_named_allocB.cpp new file mode 100644 index 0000000..8e12263 --- /dev/null +++ b/example/doc_named_allocB.cpp @@ -0,0 +1,63 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2006-2007. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#include +#include +//[doc_named_allocB +#include +#include +#include +#include + +int main () +{ + using namespace boost::interprocess; + typedef std::pair MyType; + + try{ + //An special shared memory where we can + //construct objects associated with a name. + //Connect to the already created shared memory segment + //and initialize needed resources + managed_shared_memory segment(open_only, "MySharedMemory"); + + //Find the array and object + std::pair res; + res = segment.find ("MyType array"); + + std::size_t array_len = res.second; + //Length should be 10 + assert(array_len == 10); + + //Find the array and the object + res = segment.find ("MyType instance"); + + std::size_t len = res.second; + + //Length should be 1 + assert(len == 1); + + //Use data + // . . . + + //We're done, delete array from memory + segment.destroy("MyType array"); + + //We're done, delete object from memory + segment.destroy("MyType instance"); + } + catch(...){ + shared_memory_object::remove("MySharedMemory"); + throw; + } + shared_memory_object::remove("MySharedMemory"); + return 0; +} +//] +#include diff --git a/example/doc_named_conditionA.cpp b/example/doc_named_conditionA.cpp new file mode 100644 index 0000000..9fff67b --- /dev/null +++ b/example/doc_named_conditionA.cpp @@ -0,0 +1,76 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2006-2007. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include +#include "doc_anonymous_condition_shared_data.hpp" + +using namespace boost::interprocess; + +int main () +{ + try{ + //Erase previous shared memory + shared_memory_object::remove("shared_memory"); + + //Create a shared memory object. + shared_memory_object shm + (create_only //only create + ,"shared_memory" //name + ,read_write //read-write mode + ); + + //Set size + shm.truncate(sizeof(trace_queue)); + + //Map the whole shared memory in this process + mapped_region region + (shm //What to map + ,read_write //Map it as read-write + ); + + //Get the address of the mapped region + void * addr = region.get_address(); + + //Construct the shared structure in memory + trace_queue * data = new (addr) trace_queue; + + const int NumMsg = 100; + + for(int i = 0; i < NumMsg; ++i){ + scoped_lock lock(data->mutex); + if(data->message_in){ + data->cond_full.wait(lock); + } + if(i == (NumMsg-1)) + std::sprintf(data->items, "%s", "last message"); + else + std::sprintf(data->items, "%s_%d", "my_trace", i); + + //Notify to the other process that there is a message + data->cond_empty.notify_one(); + + //Mark message buffer as full + data->message_in = true; + } + } + catch(interprocess_exception &ex){ + shared_memory_object::remove("shared_memory"); + std::cout << ex.what() << std::endl; + return 1; + } + + //Erase shared memory + shared_memory_object::remove("shared_memory"); + + return 0; +} diff --git a/example/doc_named_conditionB.cpp b/example/doc_named_conditionB.cpp new file mode 100644 index 0000000..7704a25 --- /dev/null +++ b/example/doc_named_conditionB.cpp @@ -0,0 +1,73 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2006-2007. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include +#include "doc_anonymous_condition_shared_data.hpp" + +using namespace boost::interprocess; + +int main () +{ + try{ + //Erase previous shared memory + shared_memory_object::remove("shared_memory"); + + //Create a shared memory object. + shared_memory_object shm + (open_only //only create + ,"shared_memory" //name + ,read_write //read-write mode + ); + + //Map the whole shared memory in this process + mapped_region region + (shm //What to map + ,read_write //Map it as read-write + ); + + //Get the address of the mapped region + void * addr = region.get_address(); + + //Obtain a pointer to the shared structure + trace_queue * data = static_cast(addr); + + //Print messages until the other process marks the end + bool end_loop = false; + do{ + scoped_lock lock(data->mutex); + if(!data->message_in){ + data->cond_empty.wait(lock); + } + if(std::strcmp(data->items, "last message") == 0){ + end_loop = true; + } + else{ + //Print the message + std::cout << data->items << std::endl; + //Notify the other process that the buffer is empty + data->message_in = false; + data->cond_full.notify_one(); + } + } + while(!end_loop); + } + catch(interprocess_exception &ex){ + shared_memory_object::remove("MySharedMemory"); + std::cout << ex.what() << std::endl; + return 1; + } + + //Erase shared memory + shared_memory_object::remove("shared_memory"); + return 0; +} diff --git a/doc/code/Attic/doc_named_condition_shared_data.hpp b/example/doc_named_condition_shared_data.hpp similarity index 61% rename from doc/code/Attic/doc_named_condition_shared_data.hpp rename to example/doc_named_condition_shared_data.hpp index d61934f..03dd16c 100644 --- a/doc/code/Attic/doc_named_condition_shared_data.hpp +++ b/example/doc_named_condition_shared_data.hpp @@ -1,3 +1,12 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2006-2007. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// #include #include diff --git a/example/doc_named_mutex.cpp b/example/doc_named_mutex.cpp new file mode 100644 index 0000000..e6d4044 --- /dev/null +++ b/example/doc_named_mutex.cpp @@ -0,0 +1,44 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2006-2007. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +//[doc_named_mutex +#include +#include +#include + +int main () +{ + using namespace boost::interprocess; + try{ + + //Open or create the named mutex + named_mutex mutex(open_or_create, "fstream_named_mutex"); + + std::ofstream file("file_name"); + + for(int i = 0; i < 10; ++i){ + + //Do some operations... + + //Write to file atomically + scoped_lock lock(mutex); + file << "Process name, "; + file << "This is iteration #" << i; + file << std::endl; + } + } + catch(interprocess_exception &ex){ + named_mutex::remove("fstream_named_mutex"); + std::cout << ex.what() << std::endl; + return 1; + } + named_mutex::remove("fstream_named_mutex"); + return 0; +} +//] diff --git a/example/doc_node_allocator.cpp b/example/doc_node_allocator.cpp new file mode 100644 index 0000000..4ee2460 --- /dev/null +++ b/example/doc_node_allocator.cpp @@ -0,0 +1,64 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2006-2007. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#include +#include +//[doc_node_allocator +#include +#include +#include + +using namespace boost::interprocess; + +int main () +{ + shared_memory_object::remove("MySharedMemory"); + + try{ + //Create shared memory + managed_shared_memory segment(create_only, + "MySharedMemory", //segment name + 65536); + + //Create a node_allocator that allocates ints from the managed segment + //The number of chunks per segment is the default value + typedef node_allocator + node_allocator_t; + node_allocator_t allocator_instance(segment.get_segment_manager()); + + //Create another node_allocator. Since the segment manager address + //is the same, this node_allocator will be + //attached to the same pool so "allocator_instance2" can deallocate + //nodes allocated by "allocator_instance" + node_allocator_t allocator_instance2(segment.get_segment_manager()); + + //Create another node_allocator using copy-constructor. This + //node_allocator will also be attached to the same pool + node_allocator_t allocator_instance3(allocator_instance2); + + //All allocators are equal + assert(allocator_instance == allocator_instance2); + assert(allocator_instance2 == allocator_instance3); + + //So memory allocated with one can be deallocated with another + allocator_instance2.deallocate(allocator_instance.allocate(1), 1); + allocator_instance3.deallocate(allocator_instance2.allocate(1), 1); + + //The common pool will be destroyed here, since no allocator is + //attached to the pool + } + catch(...){ + shared_memory_object::remove("MySharedMemory"); + throw; + } + shared_memory_object::remove("MySharedMemory"); + return 0; +} +//] +#include diff --git a/example/doc_offset_ptr.cpp b/example/doc_offset_ptr.cpp new file mode 100644 index 0000000..c17d11e --- /dev/null +++ b/example/doc_offset_ptr.cpp @@ -0,0 +1,69 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2006-2007. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#include +#include +//[doc_offset_ptr +#include +#include + +using namespace boost::interprocess; + +//Shared memory linked list node +struct list_node +{ + offset_ptr next; + int value; +}; + +int main () +{ + //Destroy any previous shared memory with the name to be used. + //Create an special shared memory from which we can + //allocate buffers of raw memory. + shared_memory_object::remove("MySharedMemory"); + try{ + managed_shared_memory segment( + create_only, + "MySharedMemory",//segment name + 65536); //segment size in bytes + + //Create linked list with 10 nodes in shared memory + offset_ptr prev = 0, current, first; + + int i; + for(i = 0; i < 10; ++i, prev = current){ + current = static_cast(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()); + } + } + catch(...){ + shared_memory_object::remove("MySharedMemory"); + throw; + } + shared_memory_object::remove("MySharedMemory"); + return 0; +} +//] +#include diff --git a/example/doc_private_adaptive_pool.cpp b/example/doc_private_adaptive_pool.cpp new file mode 100644 index 0000000..827bb6e --- /dev/null +++ b/example/doc_private_adaptive_pool.cpp @@ -0,0 +1,60 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2006-2007. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#include +#include +//[doc_private_adaptive_pool +#include +#include +#include + +using namespace boost::interprocess; + +int main () +{ + shared_memory_object::remove("MySharedMemory"); + + try{ + //Create shared memory + managed_shared_memory segment(create_only, + "MySharedMemory", //segment name + 65536); + + //Create a private_adaptive_pool that allocates ints from the managed segment + //The number of chunks per segment is the default value + typedef private_adaptive_pool + private_adaptive_pool_t; + private_adaptive_pool_t allocator_instance(segment.get_segment_manager()); + + //Create another private_adaptive_pool. + private_adaptive_pool_t allocator_instance2(segment.get_segment_manager()); + + //Although the segment manager address + //is the same, this private_adaptive_pool will have its own pool so + //"allocator_instance2" CAN'T deallocate nodes allocated by "allocator_instance". + //"allocator_instance2" is NOT equal to "allocator_instance" + assert(allocator_instance != allocator_instance2); + + //Create another adaptive_pool using copy-constructor. + private_adaptive_pool_t allocator_instance3(allocator_instance2); + + //This allocator is also unequal to allocator_instance2 + assert(allocator_instance2 != allocator_instance3); + + //Pools are destroyed with the allocators + } + catch(...){ + shared_memory_object::remove("MySharedMemory"); + throw; + } + shared_memory_object::remove("MySharedMemory"); + return 0; +} +//] +#include diff --git a/example/doc_private_node_allocator.cpp b/example/doc_private_node_allocator.cpp new file mode 100644 index 0000000..d569f89 --- /dev/null +++ b/example/doc_private_node_allocator.cpp @@ -0,0 +1,60 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2006-2007. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#include +#include +//[doc_private_node_allocator +#include +#include +#include + +using namespace boost::interprocess; + +int main () +{ + shared_memory_object::remove("MySharedMemory"); + + try{ + //Create shared memory + managed_shared_memory segment(create_only, + "MySharedMemory", //segment name + 65536); + + //Create a private_node_allocator that allocates ints from the managed segment + //The number of chunks per segment is the default value + typedef private_node_allocator + private_node_allocator_t; + private_node_allocator_t allocator_instance(segment.get_segment_manager()); + + //Create another private_node_allocator. + private_node_allocator_t allocator_instance2(segment.get_segment_manager()); + + //Although the segment manager address + //is the same, this private_node_allocator will have its own pool so + //"allocator_instance2" CAN'T deallocate nodes allocated by "allocator_instance". + //"allocator_instance2" is NOT equal to "allocator_instance" + assert(allocator_instance != allocator_instance2); + + //Create another node_allocator using copy-constructor. + private_node_allocator_t allocator_instance3(allocator_instance2); + + //This allocator is also unequal to allocator_instance2 + assert(allocator_instance2 != allocator_instance3); + + //Pools are destroyed with the allocators + } + catch(...){ + shared_memory_object::remove("MySharedMemory"); + throw; + } + shared_memory_object::remove("MySharedMemory"); + return 0; +} +//] +#include diff --git a/doc/code/Attic/doc_scoped_ptr.cpp b/example/doc_scoped_ptr.cpp similarity index 51% rename from doc/code/Attic/doc_scoped_ptr.cpp rename to example/doc_scoped_ptr.cpp index 625fc36..973bafc 100644 --- a/doc/code/Attic/doc_scoped_ptr.cpp +++ b/example/doc_scoped_ptr.cpp @@ -1,44 +1,54 @@ - #include - #include +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2006-2007. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#include +#include +//[doc_scoped_ptr +#include +#include - #include - #include +using namespace boost::interprocess; - using namespace boost::interprocess; +class my_class +{}; - class my_class - {}; +class my_exception +{}; - class my_exception - {}; +//A functor that destroys the shared memory object +template +class my_deleter +{ + private: + //A typedef to save typing + typedef managed_shared_memory::segment_manager segment_manager; + //This my_deleter is created in the stack, not in shared memory, + //so we can use raw pointers + segment_manager *mp_segment_manager; - //A functor that destroys the shared memory object - template - class my_deleter - { - private: - //A typedef to save typing - typedef managed_shared_memory::segment_manager segment_manager; - //This my_deleter is created in the stack, not in shared memory, - //so we can use raw pointers - segment_manager *mp_segment_manager; - - public: - //This typedef will specify the pointer type that - //scoped_ptr will store - typedef T *pointer; - //Constructor - my_deleter(segment_manager *s_mngr) - : mp_segment_manager(s_mngr){} + public: + //This typedef will specify the pointer type that + //scoped_ptr will store + typedef T *pointer; + //Constructor + my_deleter(segment_manager *s_mngr) + : mp_segment_manager(s_mngr){} - void operator()(pointer object_to_delete) - { mp_segment_manager->destroy_ptr(object_to_delete); } - }; + void operator()(pointer object_to_delete) + { mp_segment_manager->destroy_ptr(object_to_delete); } +}; - int main () - { - //Create shared memory - shared_memory_object::remove("my_shmem"); +int main () +{ + //Create shared memory + shared_memory_object::remove("my_shmem"); + try{ managed_shared_memory shmem(create_only, "my_shmem", 10000); //In the first try, there will be no exceptions @@ -65,7 +75,6 @@ s_ptr.release(); } catch(const my_exception &){} - //Here, scoped_ptr is destroyed //so it we haven't thrown an exception //the object should be there, otherwise, destroyed @@ -84,7 +93,13 @@ } } } - return 0; } - - #include + catch(...){ + shared_memory_object::remove("my_shmem"); + throw; + } + shared_memory_object::remove("my_shmem"); + return 0; +} +//] +#include diff --git a/example/doc_shared_memory.cpp b/example/doc_shared_memory.cpp new file mode 100644 index 0000000..6fc5c3c --- /dev/null +++ b/example/doc_shared_memory.cpp @@ -0,0 +1,43 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2006-2007. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +//[doc_shared_memory +#include +#include +#include +#include + +int main () +{ + using namespace boost::interprocess; + try{ + //Erase previous shared memory + shared_memory_object::remove("shared_memory"); + + //Create a shared memory object. + shared_memory_object shm (create_only, "shared_memory", read_write); + + //Set size + shm.truncate(1000); + + //Map the whole shared memory in this process + mapped_region region(shm, read_write); + + //Write all the memory to 1 + std::memset(region.get_address(), 1, region.get_size()); + } + catch(interprocess_exception &ex){ + shared_memory_object::remove("shared_memory"); + std::cout << ex.what() << std::endl; + return 1; + } + shared_memory_object::remove("shared_memory"); + return 0; +} +//] diff --git a/example/doc_shared_memory2.cpp b/example/doc_shared_memory2.cpp new file mode 100644 index 0000000..f4642be --- /dev/null +++ b/example/doc_shared_memory2.cpp @@ -0,0 +1,43 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2006-2007. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +//[doc_shared_memory2 +#include +#include +#include +#include + +int main () +{ + using namespace boost::interprocess; + try{ + //Open already created shared memory object. + shared_memory_object shm (open_only, "shared_memory", read_only); + + //Map the whole shared memory in this process + mapped_region region(shm, read_only); + + //Check that memory was initialized to 1 + const char *mem = static_cast(region.get_address()); + for(std::size_t i = 0; i < region.get_size(); ++i){ + if(*mem++ != 1){ + std::cout << "Error checking memory!" << std::endl; + return 1; + } + } + std::cout << "Test successful!" << std::endl; + } + catch(interprocess_exception &ex){ + std::cout << "Unexpected exception: " << ex.what() << std::endl; + return 1; + } + + return 0; +} +//] diff --git a/doc/code/Attic/doc_upgradable_mutex_shared_data.hpp b/example/doc_upgradable_mutex_shared_data.hpp similarity index 55% rename from doc/code/Attic/doc_upgradable_mutex_shared_data.hpp rename to example/doc_upgradable_mutex_shared_data.hpp index 1744c58..39f4f3b 100644 --- a/doc/code/Attic/doc_upgradable_mutex_shared_data.hpp +++ b/example/doc_upgradable_mutex_shared_data.hpp @@ -1,3 +1,12 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2006-2007. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// #include struct shared_data diff --git a/doc/code/Attic/doc_vectorstream.cpp b/example/doc_vectorstream.cpp similarity index 63% rename from doc/code/Attic/doc_vectorstream.cpp rename to example/doc_vectorstream.cpp index 39ba2b9..5f623e2 100644 --- a/doc/code/Attic/doc_vectorstream.cpp +++ b/example/doc_vectorstream.cpp @@ -1,27 +1,37 @@ - #include - #include +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2006-2007. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#include +#include +//[doc_vectorstream +#include +#include +#include +#include +#include - #include - #include - #include - #include - #include - - using namespace boost::interprocess; +using namespace boost::interprocess; - typedef allocator - IntAllocator; - typedef allocator - CharAllocator; - typedef vector MyVector; - typedef basic_string - , CharAllocator> MyString; - typedef basic_vectorstream MyVectorStream; +typedef allocator + IntAllocator; +typedef allocator + CharAllocator; +typedef vector MyVector; +typedef basic_string + , CharAllocator> MyString; +typedef basic_vectorstream MyVectorStream; - int main () - { - //Create shared memory - shared_memory_object::remove("MySharedMemory"); +int main () +{ + //Create shared memory + shared_memory_object::remove("MySharedMemory"); + try{ managed_shared_memory segment( create_only, "MySharedMemory",//segment name @@ -76,7 +86,7 @@ MyString *mystring = segment.construct("MyString") (CharAllocator(segment.get_segment_manager())); - + //...and we swap vectorstream's internal string //with the new one: after this statement mystring //will be the owner of the formatted data. @@ -90,7 +100,13 @@ segment.destroy_ptr(myvector2); segment.destroy_ptr(myvector); segment.destroy_ptr(mystring); - return 0; } - - #include + catch(...){ + shared_memory_object::remove("MySharedMemory"); + throw; + } + shared_memory_object::remove("MySharedMemory"); + return 0; +} +//] +#include diff --git a/doc/code/Attic/doc_where_allocate.cpp b/example/doc_where_allocate.cpp similarity index 53% rename from doc/code/Attic/doc_where_allocate.cpp rename to example/doc_where_allocate.cpp index 02d570a..ada534e 100644 --- a/doc/code/Attic/doc_where_allocate.cpp +++ b/example/doc_where_allocate.cpp @@ -1,26 +1,36 @@ - #include - #include +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2006-2007. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#include +#include +//[doc_where_allocate +#include +#include +#include +#include - #include - #include - #include - #include +int main () +{ + using namespace boost::interprocess; + //Typedefs + typedef allocator + CharAllocator; + typedef basic_string, CharAllocator> + MyShmString; + typedef allocator + StringAllocator; + typedef vector + MyShmStringVector; - int main () - { - using namespace boost::interprocess; - //Typedefs - typedef allocator - CharAllocator; - typedef basic_string, CharAllocator> - MyShmString; - typedef allocator - StringAllocator; - typedef vector - MyShmStringVector; - - //Open shared memory - shared_memory_object::remove("myshm"); + //Open shared memory + shared_memory_object::remove("myshm"); + try{ managed_shared_memory shm(create_only, "myshm", 10000); //Create allocators @@ -52,7 +62,13 @@ //Destroy vector. This will free all strings that the vector contains shm.destroy_ptr(myshmvector); - return 0; } - - #include + catch(...){ + shared_memory_object::remove("myshm"); + throw; + } + shared_memory_object::remove("myshm"); + return 0; +} +//] +#include diff --git a/example/doc_windows_shared_memory.cpp b/example/doc_windows_shared_memory.cpp new file mode 100644 index 0000000..8ee8e84 --- /dev/null +++ b/example/doc_windows_shared_memory.cpp @@ -0,0 +1,48 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2006-2007. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#include +#include + +#ifdef BOOST_WINDOWS +//[doc_windows_shared_memory +#include +#include +#include +#include + +int main () +{ + using namespace boost::interprocess; + try{ + //Create a native windows shared memory object. + windows_shared_memory shm (create_only, "shared_memory", read_write, 1000); + + //Map the whole shared memory in this process + mapped_region region(shm, read_write); + + //Write all the memory to 1 + std::memset(region.get_address(), 1, 1000); + + //Launch the client process and wait until finishes... + //... + } + catch(interprocess_exception &ex){ + std::cout << ex.what() << std::endl; + return 1; + } + return 0; +} +//] +#else //#ifdef BOOST_WINDOWS +int main() +{ return 0; } +#endif//#ifdef BOOST_WINDOWS + +#include diff --git a/example/doc_windows_shared_memory2.cpp b/example/doc_windows_shared_memory2.cpp new file mode 100644 index 0000000..1036fcf --- /dev/null +++ b/example/doc_windows_shared_memory2.cpp @@ -0,0 +1,44 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2006-2007. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +//[doc_windows_shared_memory2 +#include +#include +#include +#include + +int main () +{ + using namespace boost::interprocess; + try{ + //Open already created shared memory object. + windows_shared_memory shm(open_only, "shared_memory", read_only); + + //Map the whole shared memory in this process + mapped_region region (shm, read_only); + + //Check that memory was initialized to 1 + const char *mem = static_cast(region.get_address()); + for(std::size_t i = 0; i < 1000; ++i){ + if(*mem++ != 1){ + std::cout << "Error checking memory!" << std::endl; + return 1; + } + } + + std::cout << "Test successful!" << std::endl; + } + catch(interprocess_exception &ex){ + std::cout << "Unexpected exception: " << ex.what() << std::endl; + return 1; + } + + return 0; +} +//] diff --git a/index.html b/index.html index 3d7cec6..f1a6b2d 100644 --- a/index.html +++ b/index.html @@ -3,10 +3,6 @@ -Automatic redirection failed, please go to doc/html/interprocess.html 
-

© Copyright Beman Dawes, 2001

-

Distributed under the Boost Software License, Version 1.0. (See accompanying -file LICENSE_1_0.txt or copy -at www.boost.org/LICENSE_1_0.txt)

+Automatic redirection failed, please go to doc/html/interprocess.html - \ No newline at end of file + diff --git a/proj/conceptgcc/MakeAll b/proj/conceptgcc/MakeAll new file mode 100644 index 0000000..1c15f24 --- /dev/null +++ b/proj/conceptgcc/MakeAll @@ -0,0 +1,35 @@ + +ifndef CC +CC=i686-pc-cygwin-gcc.exe +endif + +BOOST_ROOT=../../../.. + +INTERPROCESS_CPP := $(wildcard ../../src/*.cpp) +INTERPROCESS_OBJ := $(patsubst ../../src/%.cpp, lib_%.o, $(INTERPROCESS_CPP)) + +INTERPROCESSTEST_CPP := $(wildcard ../../test/*.cpp) +INTERPROCESSTEST_OUT := $(patsubst ../../test/%.cpp, ../../bin/conceptgcc/test_%.out, $(INTERPROCESSTEST_CPP)) + +INTERPROCESSDOC_CPP := $(wildcard ../../example/*.cpp) +INTERPROCESSDOC_OUT := $(patsubst ../../example/%.cpp, ../../bin/conceptgcc/ex_%.out, $(INTERPROCESSDOC_CPP)) + +LIBDIR:= ../../../../stage/lib + +.PHONY: createdir clean + +all: createdir $(INTERPROCESSTEST_OUT) $(INTERPROCESSDOC_OUT) + @cd . + +createdir: + @mkdir -p ../../bin/conceptgcc + +../../bin/conceptgcc/test_%.out: ../../test/%.cpp + $(CC) $< -Wall -DBOOST_DATE_TIME_NO_LIB -L$(LIBDIR) -lboost_thread-mgw-mt -I$(BOOST_ROOT) -lstdc++ -o $@ + +../../bin/conceptgcc/ex_%.out: ../../example/%.cpp + $(CC) $< -Wall -DBOOST_DATE_TIME_NO_LIB -L$(LIBDIR)-lboost_thread-mgw-mt -I$(BOOST_ROOT) -lstdc++ -o $@ + +clean: + rm -f *.o + rm -f ../../bin/conceptgcc/* diff --git a/proj/cygwin/MakeAll b/proj/cygwin/MakeAll index 8278d67..71e4be6 100644 --- a/proj/cygwin/MakeAll +++ b/proj/cygwin/MakeAll @@ -14,14 +14,14 @@ INTERPROCESSTEST_OUT := $(patsubst ../../test/%.cpp, ../../bin/cygwin/test_%.out INTERPROCESSEXAMPLE_CPP := $(wildcard ../../example/*.cpp) INTERPROCESSEXAMPLE_OUT := $(patsubst ../../example/%.cpp, ../../bin/cygwin/ex_%.out, $(INTERPROCESSEXAMPLE_CPP)) -INTERPROCESSDOC_CPP := $(wildcard ../../doc/code/*.cpp) -INTERPROCESSDOC_OUT := $(patsubst ../../doc/code/%.cpp, ../../bin/cygwin/doc_%.out, $(INTERPROCESSDOC_CPP)) +INTERPROCESSEXAMPLE_CPP := $(wildcard ../../example/*.cpp) +INTERPROCESSEXAMPLE_OUT := $(patsubst ../../example/%.cpp, ../../bin/cygwin/ex__%.out, $(INTERPROCESSEXAMPLE_CPP)) LIBDIR:= ../../../../stage/lib .PHONY: createdir clean -all: createdir $(INTERPROCESSEXAMPLE_OUT) $(INTERPROCESSTEST_OUT) $(INTERPROCESSDOC_OUT) +all: createdir $(INTERPROCESSEXAMPLE_OUT) $(INTERPROCESSTEST_OUT) $(INTERPROCESSEXAMPLE_OUT) @cd . createdir: @@ -33,8 +33,6 @@ createdir: ../../bin/cygwin/ex_%.out: ../../example/%.cpp $(CC) -g $< -Wall -DBOOST_DATE_TIME_NO_LIB -L$(LIBDIR)-lboost_thread-gcc-mt -I$(BOOST_ROOT) -lstdc++ -o $@ -../../bin/cygwin/doc_%.out: ../../doc/code/%.cpp - $(CC) -g $< -Wall -DBOOST_DATE_TIME_NO_LIB -L$(LIBDIR)-lboost_thread-gcc-mt -I$(BOOST_ROOT) -lstdc++ -o $@ clean: rm -f *.o diff --git a/proj/linux/MakeAll b/proj/linux/MakeAll index 87b248c..9f0962f 100644 --- a/proj/linux/MakeAll +++ b/proj/linux/MakeAll @@ -13,12 +13,9 @@ INTERPROCESS_OUT := $(patsubst ../../test/%.cpp, ../../bin/linux/test_%.out, $(I INTERPROCESSEXAMPLE_CPP := $(wildcard ../../example/*.cpp) INTERPROCESSEXAMPLE_OUT := $(patsubst ../../example/%.cpp, ../../bin/linux/ex_%.out, $(INTERPROCESSEXAMPLE_CPP)) -INTERPROCESSDOC_CPP := $(wildcard ../../doc/code/*.cpp) -INTERPROCESSDOC_OUT := $(patsubst ../../doc/code/%.cpp, ../../bin/linux/doc_%.out, $(INTERPROCESSDOC_CPP)) - .PHONY: createdir clean -all: createdir $(INTERPROCESSEXAMPLE_OUT) $(INTERPROCESS_OUT) $(INTERPROCESSDOC_OUT) +all: createdir $(INTERPROCESS_OUT) $(INTERPROCESSEXAMPLE_OUT) @cd . createdir: @@ -30,9 +27,6 @@ createdir: ../../bin/linux/ex_%.out: ../../example/%.cpp $(CC) $< -Wall -pedantic -g -pthread -DBOOST_DATE_TIME_NO_LIB -lstdc++ -lrt -lboost_thread-gcc-mt -I$(BOOST_ROOT) -L$(BOOST_LIBS) -o $@ -../../bin/linux/doc_%.out: ../../doc/code/%.cpp - $(CC) $< -Wall -pedantic -g -pthread -DBOOST_DATE_TIME_NO_LIB -lstdc++ -lrt -lboost_thread-gcc-mt -I$(BOOST_ROOT) -L$(BOOST_LIBS) -o $@ - clean: rm -f *.o rm -f ../../bin/linux/* diff --git a/proj/mingw/MakeAll b/proj/mingw/MakeAll index c50565b..0b23825 100644 --- a/proj/mingw/MakeAll +++ b/proj/mingw/MakeAll @@ -14,14 +14,11 @@ INTERPROCESSTEST_OUT := $(patsubst ../../test/%.cpp, ../../bin/mingw/test_%.out, INTERPROCESSEXAMPLE_CPP := $(wildcard ../../example/*.cpp) INTERPROCESSEXAMPLE_OUT := $(patsubst ../../example/%.cpp, ../../bin/mingw/ex_%.out, $(INTERPROCESSEXAMPLE_CPP)) -INTERPROCESSDOC_CPP := $(wildcard ../../doc/code/*.cpp) -INTERPROCESSDOC_OUT := $(patsubst ../../doc/code/%.cpp, ../../bin/mingw/doc_%.out, $(INTERPROCESSDOC_CPP)) - LIBDIR:= ../../../../stage/lib .PHONY: createdir clean -all: createdir $(INTERPROCESSEXAMPLE_OUT) $(INTERPROCESSTEST_OUT) $(INTERPROCESSDOC_OUT) +all: createdir $(INTERPROCESSTEST_OUT) $(INTERPROCESSEXAMPLE_OUT) @cd . createdir: @@ -33,9 +30,6 @@ createdir: ../../bin/mingw/ex_%.out: ../../example/%.cpp $(CC) $< -Wall -DBOOST_DATE_TIME_NO_LIB -L$(LIBDIR)-lboost_thread-mgw-mt -I$(BOOST_ROOT) -lstdc++ -o $@ -../../bin/mingw/doc_%.out: ../../doc/code/%.cpp - $(CC) $< -Wall -DBOOST_DATE_TIME_NO_LIB -L$(LIBDIR)-lboost_thread-mgw-mt -I$(BOOST_ROOT) -lstdc++ -o $@ - clean: rm -f *.o rm -f ../../bin/mingw/* diff --git a/proj/qnx/MakeAll b/proj/qnx/MakeAll index 2836184..b98dc49 100644 --- a/proj/qnx/MakeAll +++ b/proj/qnx/MakeAll @@ -14,12 +14,9 @@ INTERPROCESSTEST_OUT := $(patsubst ../../test/%.cpp, ../../bin/qnx/test_%.out, $ INTERPROCESSEXAMPLE_CPP := $(wildcard ../../example/*.cpp) INTERPROCESSEXAMPLE_OUT := $(patsubst ../../example/%.cpp, ../../bin/qnx/ex_%.out, $(INTERPROCESSEXAMPLE_CPP)) -INTERPROCESSDOC_CPP := $(wildcard ../../doc/code/*.cpp) -INTERPROCESSDOC_OUT := $(patsubst ../../doc/code/%.cpp, ../../bin/qnx/doc_%.out, $(INTERPROCESSDOC_CPP)) - .PHONY: createdir clean - -all: createdir $(INTERPROCESSEXAMPLE_OUT) $(INTERPROCESSTEST_OUT) $(INTERPROCESSDOC_OUT) + +all: createdir $(INTERPROCESSTEST_OUT) $(INTERPROCESSEXAMPLE_OUT) @cd . createdir: @@ -31,9 +28,6 @@ createdir: ../../bin/qnx/ex_%.out: ../../example/%.cpp $(CC) $< -Wall -DBOOST_DATE_TIME_NO_LIB -lboost_thread-gcc-mt-s -I$(BOOST_ROOT) -o $@ -../../bin/qnx/doc_%.out: ../../doc/code/%.cpp - $(CC) $< -Wall -DBOOST_DATE_TIME_NO_LIB -lboost_thread-gcc-mt-s -I$(BOOST_ROOT) -o $@ - clean: rm -f *.o rm -f ../../bin/qnx/* diff --git a/proj/vc7ide/Attic/ProcessA.vcproj b/proj/vc7ide/Attic/ProcessA.vcproj index 9c1a498..18884ba 100644 --- a/proj/vc7ide/Attic/ProcessA.vcproj +++ b/proj/vc7ide/Attic/ProcessA.vcproj @@ -1,133 +1,133 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="ProcessA" + ProjectGUID="{58CCE183-6092-48FE-A4F7-BA0D3A792619}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/Attic/ProcessAFixed.vcproj b/proj/vc7ide/Attic/ProcessAFixed.vcproj index 7591015..4026bf9 100644 --- a/proj/vc7ide/Attic/ProcessAFixed.vcproj +++ b/proj/vc7ide/Attic/ProcessAFixed.vcproj @@ -1,133 +1,133 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="ProcessAFixed" + ProjectGUID="{58CCE183-6092-48FE-A4F7-BA0D3A792618}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/Attic/ProcessB.vcproj b/proj/vc7ide/Attic/ProcessB.vcproj index 516afca..f7fa6f8 100644 --- a/proj/vc7ide/Attic/ProcessB.vcproj +++ b/proj/vc7ide/Attic/ProcessB.vcproj @@ -1,132 +1,132 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="ProcessB" + ProjectGUID="{58CCE183-6092-48FE-A4F7-BA0D3A792617}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/Attic/ProcessBFixed.vcproj b/proj/vc7ide/Attic/ProcessBFixed.vcproj index fd73075..f6ca6ac 100644 --- a/proj/vc7ide/Attic/ProcessBFixed.vcproj +++ b/proj/vc7ide/Attic/ProcessBFixed.vcproj @@ -1,132 +1,132 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="ProcessBFixed" + ProjectGUID="{58CCE183-6092-48FE-A4F7-BA0D3A792616}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/Attic/allocate_ex.vcproj b/proj/vc7ide/Attic/allocate_ex.vcproj index 265f92e..c43dea2 100644 --- a/proj/vc7ide/Attic/allocate_ex.vcproj +++ b/proj/vc7ide/Attic/allocate_ex.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="allocate_ex" + ProjectGUID="{58CCE183-6092-48FE-A4F7-BA0D3A792663}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/Attic/file_lock_test.vcproj b/proj/vc7ide/Attic/file_lock_test.vcproj index e8d4541..3e311dc 100644 --- a/proj/vc7ide/Attic/file_lock_test.vcproj +++ b/proj/vc7ide/Attic/file_lock_test.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="file_lock_test" + ProjectGUID="{58CCE183-6092-48FE-A4F7-BA0D3A792639}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/Attic/hash_table_ex.vcproj b/proj/vc7ide/Attic/hash_table_ex.vcproj index 685a060..430ecf8 100644 --- a/proj/vc7ide/Attic/hash_table_ex.vcproj +++ b/proj/vc7ide/Attic/hash_table_ex.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="hash_table_test" + ProjectGUID="{58CCE183-6092-48FE-A4F7-BA0D3A792636}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/Attic/intersegment_ptr_test.vcproj b/proj/vc7ide/Attic/intersegment_ptr_test.vcproj index 852b46d..ea0de1f 100644 --- a/proj/vc7ide/Attic/intersegment_ptr_test.vcproj +++ b/proj/vc7ide/Attic/intersegment_ptr_test.vcproj @@ -1,137 +1,137 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="intersegment_ptr_test" + ProjectGUID="{58CCE183-6092-12FE-A4F7-BA0D3A767634}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/Attic/named_allocate_ex.vcproj b/proj/vc7ide/Attic/named_allocate_ex.vcproj index 52a974c..1c71de3 100644 --- a/proj/vc7ide/Attic/named_allocate_ex.vcproj +++ b/proj/vc7ide/Attic/named_allocate_ex.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="named_allocate_ex" + ProjectGUID="{58CCE183-6092-48FE-A4F7-BA0D3A792626}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/Attic/read_write_mutex_test.vcproj b/proj/vc7ide/Attic/read_write_mutex_test.vcproj index 2e3adc4..7e507b6 100644 --- a/proj/vc7ide/Attic/read_write_mutex_test.vcproj +++ b/proj/vc7ide/Attic/read_write_mutex_test.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="read_write_mutex_test" + ProjectGUID="{58CCE183-6092-48FE-A4F7-BA0D3A792615}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/Attic/sharable_mutex.vcproj b/proj/vc7ide/Attic/sharable_mutex.vcproj index 550ce7e..b821bcf 100644 --- a/proj/vc7ide/Attic/sharable_mutex.vcproj +++ b/proj/vc7ide/Attic/sharable_mutex.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="sharable_mutex_test" + ProjectGUID="{5E188CC3-0962-F7A4-8F4E-A0D3B606A712}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/Attic/shared_memory_mapping_test.vcproj b/proj/vc7ide/Attic/shared_memory_mapping_test.vcproj deleted file mode 100644 index 98cec8c..0000000 --- a/proj/vc7ide/Attic/shared_memory_mapping_test.vcproj +++ /dev/null @@ -1,135 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/proj/vc7ide/Interprocess.sln b/proj/vc7ide/Interprocess.sln index f014521..30ca319 100644 --- a/proj/vc7ide/Interprocess.sln +++ b/proj/vc7ide/Interprocess.sln @@ -1,184 +1,4 @@ Microsoft Visual Studio Solution File, Format Version 8.00 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "allocate_ex", "allocate_ex.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792663}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "allocexcept_test", "allocexcept_test.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792662}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "barrier_test", "barrier_test.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792661}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bufferstream_test", "bufferstream_test.vcproj", "{58C183CE-6203-FE12-A237-BA8976695960}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cached_node_allocator_test", "cached_node_allocator_test.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792659}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "condition_test", "condition_test.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792658}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "data_test", "data_test.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792657}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "deque_test", "deque_test.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792655}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_bufferstream", "doc_bufferstream.vcproj", "{58C1B183-9026-4E12-00F2-001200540054}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_intrusive", "doc_intrusive.vcproj", "{5E18CC83-6092-48FE-A677-B832A0D3A650}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_ipc_messageA", "doc_ipc_messageA.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792649}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_ipc_messageB", "doc_ipc_messageB.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792648}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_managed_heap_memory", "doc_managed_heap_memory.vcproj", "{58CCE183-6092-48FE-A4FC-BA0D3A792647}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_managed_mapped_file", "doc_managed_mapped_file.vcproj", "{58CCE183-5091-48FE-A4FC-BA0D3A792446}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_named_allocA", "doc_named_allocA.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792645}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_named_allocB", "doc_named_allocB.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792644}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_offset_ptr", "doc_offset_ptr.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792643}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_scoped_ptr", "doc_scoped_ptr.vcproj", "{58CC8E13-0962-8F4E-77A6-BD3A6832A042}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_vectorstream", "doc_vectorstream.vcproj", "{58C1B183-9260-4E8F-F200-000000000041}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_where_allocate", "doc_where_allocate.vcproj", "{58CCE183-6092-48FE-A677-BA0D3A832640}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "file_lock_test", "file_lock_test.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792639}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "file_mapping_test", "file_mapping_test.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792638}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "flat_tree_test", "flat_tree_test.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792637}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_interprocesslib", "interprocesslib.vcproj", "{FFAA56F1-32EC-4B22-B6BD-95A311A67C35}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "intersegment_ptr_test", "intersegment_ptr_test.vcproj", "{58CCE183-6092-12FE-A4F7-BA0D3A767634}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "intrusive_ptr_test", "intrusive_ptr_test.vcproj", "{5821C383-6092-12FE-A877-BA0D33467633}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "list_test", "list_ex.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792632}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "managed_mapped_file_test", "managed_mapped_file_test.vcproj", "{5CCE1883-0926-F7A4-8FE4-BA0606D92331}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mapped_file_test", "mapped_file_test.vcproj", "{5C6D9CE1-2609-F7A4-8FE4-BA0883602330}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "memory_algorithm_test", "memory_algorithm_test.vcproj", "{58E18CC3-6092-8F4E-A3E7-A792230D3629}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "message_queue_test", "message_queue.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792628}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mutex_test", "mutex_test.vcproj", "{83581CCE-487E-3292-A4E7-BA07926D3A27}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "named_allocate_ex", "named_allocate_ex.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792626}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "named_mutex_test", "named_mutex_test.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792625}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "named_recursive_mutex_test", "named_recursive_mutex_test.vcproj", "{5C83CE18-4F48-A7FE-6092-B7920AD3A624}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "named_semaphore_test", "named_semaphore_test.vcproj", "{58CCE283-1609-48FE-A4F7-BA0D3A793523}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "node_allocator_test", "node_allocator_test.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792622}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "null_index_test", "null_index_test.vcproj", "{0000058C-0000-0000-0000-000000000021}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "private_node_allocator_test", "private_node_allocator_test.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792620}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ProcessA", "ProcessA.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792619}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ProcessAFixed", "ProcessAFixed.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792618}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ProcessB", "ProcessB.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792617}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ProcessBFixed", "ProcessBFixed.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792616}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "recursive_mutex_test", "recursive_mutex_test.vcproj", "{83581CCE-487E-3292-A4E7-BA07926D3A14}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "semaphore_test", "semaphore_test.vcproj", "{5CE28C83-48FE-1676-4FA7-B50D3A76A013}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shared_memory_mapping_test", "shared_memory_mappable_test.vcproj", "{5CE18C83-6025-36FE-A4F7-BA09176D3A11}" ProjectSection(ProjectDependencies) = postProject EndProjectSection @@ -303,192 +123,314 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_move_containers", "doc_ ProjectSection(ProjectDependencies) = postProject EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "map_index_allocation_test", "map_index_allocation_test.vcproj", "{588CCD13-2962-83FE-F4B7-92230DB73629}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "flat_map_index_allocation_test", "flat_map_index_allocation_test.vcproj", "{51D8E9C3-2D65-48FE-3AA7-7922C0E36329}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "iset_index_allocation_test", "iset_index_allocation_test.vcproj", "{58BD1CC3-6972-F3F7-84BE-0DB736035922}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "iunordered_set_index_allocation_test", "iunordered_set_index_allocation_test.vcproj", "{5BD1C7C3-3F7F-6972-84BE-B731D9236035}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_shared_memory2", "doc_shared_memory2.vcproj", "{58CE1D83-F31E-4FD7-6132-8A79F6307B61}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_file_mapping2", "doc_file_mapping2.vcproj", "{5CE19883-F413-7EFD-6342-B79639F7B611}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_file_mapping", "doc_file_mapping.vcproj", "{58DE18C3-3261-2F3E-FD47-83760B9FA761}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_map", "doc_map.vcproj", "{59CEC183-8192-8F6D-4FB7-BA260A79D352}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "windows_shared_memory_test", "windows_shared_memory_test.vcproj", "{E385C28C-0691-4FA7-F48E-935BA0D06310}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "windows_shared_memory_mapping_test", "windows_shared_memory_mapping_test.vcproj", "{518CE8C3-6512-FA75-46EF-B917A3A116D1}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "managed_windows_shared_memory_test", "managed_windows_shared_memory.vcproj", "{5D18CE83-1926-7AE4-FE94-B606D9B23131}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "adaptive_pool_test", "adaptive_pool_test.vcproj", "{58CE1D84-1962-4FE9-BA0D-A4F7973A4652}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cached_adaptive_pool_test", "cached_adaptive_pool_test.vcproj", "{5188E3CE-2964-F43E-FB87-B037AC692D59}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "private_adaptive_pool_test", "private_adaptive_pool_test.vcproj", "{5CE14C83-4962-8F5E-4FA7-B0D3A7B93635}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_allocator", "doc_allocator.vcproj", "{581B1C83-4E12-9526-020F-012482540054}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_node_allocator", "doc_node_allocator.vcproj", "{51B17C83-E172-5396-0FA2-825472008554}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_private_node_allocator", "doc_private_node_allocator.vcproj", "{2B75C833-17D2-4956-A23F-820854254175}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_cached_node_allocator", "doc_cached_node_allocator.vcproj", "{283AD375-7D12-5866-23BF-854308651275}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_adaptive_pool", "doc_adaptive_pool.vcproj", "{57C832B1-17D2-9537-FA12-827220448554}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_cached_adaptive_pool", "doc_cached_adaptive_pool.vcproj", "{536C8251-7E12-9537-A1E2-822073258554}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_private_adaptive_pool", "doc_private_adaptive_pool.vcproj", "{83258CB1-127E-9375-F872-8324A1054454}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_managed_raw_allocation", "doc_managed_raw_allocation.vcproj", "{5198EFC3-2731-F34E-4FD8-1859AC94F761}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_managed_aligned_allocation", "doc_managed_aligned_allocation.vcproj", "{58DE18C3-3261-2F3E-FD47-83760B9FA761}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_interprocesslib", "interprocesslib.vcproj", "{FFAA56F1-32EC-4B22-B6BD-95A311A67C35}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_windows_shared_memory", "doc_windows_shared_memory.vcproj", "{5E17C9C3-1362-2E1E-C84F-8A76B6739F21}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_windows_shared_memory2", "doc_windows_shared_memory2.vcproj", "{5E1D6C83-31DE-4F6F-6132-87A9FB663041}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "adaptive_node_pool_test", "adaptive_node_pool_test.vcproj", "{CD57C283-1862-42FE-BF87-B96D3A2A7912}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "node_pool_test", "node_pool_test.vcproj", "{8A519DC3-6092-A4FE-F748-BA91328D6522}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "deque_test", "deque_test.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792655}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "barrier_test", "barrier_test.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792661}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bufferstream_test", "bufferstream_test.vcproj", "{58C183CE-6203-FE12-A237-BA8976695960}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cached_node_allocator_test", "cached_node_allocator_test.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792659}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "private_node_allocator_test", "private_node_allocator_test.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792620}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "node_allocator_test", "node_allocator_test.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792622}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "named_mutex_test", "named_mutex_test.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792625}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "named_recursive_mutex_test", "named_recursive_mutex_test.vcproj", "{5C83CE18-4F48-A7FE-6092-B7920AD3A624}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "named_semaphore_test", "named_semaphore_test.vcproj", "{58CCE283-1609-48FE-A4F7-BA0D3A793523}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_managed_heap_memory", "doc_managed_heap_memory.vcproj", "{58CCE183-6092-48FE-A4FC-BA0D3A792647}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "allocate_ex", "allocate_ex.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792663}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "allocexcept_test", "allocexcept_test.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792662}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "condition_test", "condition_test.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792658}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "data_test", "data_test.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792657}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_bufferstream", "doc_bufferstream.vcproj", "{58C1B183-9026-4E12-00F2-001200540054}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_intrusive", "doc_intrusive.vcproj", "{5E18CC83-6092-48FE-A677-B832A0D3A650}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_ipc_messageA", "doc_ipc_messageA.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792649}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_ipc_messageB", "doc_ipc_messageB.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792648}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_managed_mapped_file", "doc_managed_mapped_file.vcproj", "{58CCE183-5091-48FE-A4FC-BA0D3A792446}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_named_allocA", "doc_named_allocA.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792645}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_named_allocB", "doc_named_allocB.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792644}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_offset_ptr", "doc_offset_ptr.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792643}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_scoped_ptr", "doc_scoped_ptr.vcproj", "{58CC8E13-0962-8F4E-77A6-BD3A6832A042}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_vectorstream", "doc_vectorstream.vcproj", "{58C1B183-9260-4E8F-F200-000000000041}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "doc_where_allocate", "doc_where_allocate.vcproj", "{58CCE183-6092-48FE-A677-BA0D3A832640}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "file_lock_test", "file_lock_test.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792639}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "file_mapping_test", "file_mapping_test.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792638}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "flat_tree_test", "flat_tree_test.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792637}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hash_table_test", "hash_table_ex.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792636}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "intersegment_ptr_test", "intersegment_ptr_test.vcproj", "{58CCE183-6092-12FE-A4F7-BA0D3A767634}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "intrusive_ptr_test", "intrusive_ptr_test.vcproj", "{5821C383-6092-12FE-A877-BA0D33467633}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "list_test", "list_ex.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792632}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "managed_mapped_file_test", "managed_mapped_file_test.vcproj", "{5CCE1883-0926-F7A4-8FE4-BA0606D92331}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mapped_file_test", "mapped_file_test.vcproj", "{5C6D9CE1-2609-F7A4-8FE4-BA0883602330}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "memory_algorithm_test", "memory_algorithm_test.vcproj", "{58E18CC3-6092-8F4E-A3E7-A792230D3629}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "message_queue_test", "message_queue.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792628}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mutex_test", "mutex_test.vcproj", "{83581CCE-487E-3292-A4E7-BA07926D3A27}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "named_allocate_ex", "named_allocate_ex.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792626}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "null_index_test", "null_index_test.vcproj", "{0000058C-0000-0000-0000-000000000021}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ProcessA", "ProcessA.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792619}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ProcessAFixed", "ProcessAFixed.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792618}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ProcessB", "ProcessB.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792617}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ProcessBFixed", "ProcessBFixed.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792616}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "read_write_mutex_test", "read_write_mutex_test.vcproj", "{58CCE183-6092-48FE-A4F7-BA0D3A792615}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "recursive_mutex_test", "recursive_mutex_test.vcproj", "{83581CCE-487E-3292-A4E7-BA07926D3A14}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "semaphore_test", "semaphore_test.vcproj", "{5CE28C83-48FE-1676-4FA7-B50D3A76A013}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sharable_mutex_test", "sharable_mutex.vcproj", "{5E188CC3-0962-F7A4-8F4E-A0D3B606A712}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject Global GlobalSection(SolutionConfiguration) = preSolution Debug = Debug Release = Release EndGlobalSection + GlobalSection(ProjectDependencies) = postSolution + EndGlobalSection GlobalSection(ProjectConfiguration) = postSolution - {58CCE183-6092-48FE-A4F7-BA0D3A792663}.Debug.ActiveCfg = Debug|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792663}.Debug.Build.0 = Debug|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792663}.Release.ActiveCfg = Release|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792663}.Release.Build.0 = Release|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792662}.Debug.ActiveCfg = Debug|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792662}.Debug.Build.0 = Debug|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792662}.Release.ActiveCfg = Release|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792662}.Release.Build.0 = Release|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792661}.Debug.ActiveCfg = Debug|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792661}.Debug.Build.0 = Debug|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792661}.Release.ActiveCfg = Release|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792661}.Release.Build.0 = Release|Win32 - {58C183CE-6203-FE12-A237-BA8976695960}.Debug.ActiveCfg = Debug|Win32 - {58C183CE-6203-FE12-A237-BA8976695960}.Debug.Build.0 = Debug|Win32 - {58C183CE-6203-FE12-A237-BA8976695960}.Release.ActiveCfg = Release|Win32 - {58C183CE-6203-FE12-A237-BA8976695960}.Release.Build.0 = Release|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792659}.Debug.ActiveCfg = Debug|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792659}.Debug.Build.0 = Debug|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792659}.Release.ActiveCfg = Release|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792659}.Release.Build.0 = Release|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792658}.Debug.ActiveCfg = Debug|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792658}.Debug.Build.0 = Debug|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792658}.Release.ActiveCfg = Release|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792658}.Release.Build.0 = Release|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792657}.Debug.ActiveCfg = Debug|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792657}.Debug.Build.0 = Debug|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792657}.Release.ActiveCfg = Release|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792657}.Release.Build.0 = Release|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792655}.Debug.ActiveCfg = Debug|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792655}.Debug.Build.0 = Debug|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792655}.Release.ActiveCfg = Release|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792655}.Release.Build.0 = Release|Win32 - {58C1B183-9026-4E12-00F2-001200540054}.Debug.ActiveCfg = Debug|Win32 - {58C1B183-9026-4E12-00F2-001200540054}.Debug.Build.0 = Debug|Win32 - {58C1B183-9026-4E12-00F2-001200540054}.Release.ActiveCfg = Release|Win32 - {58C1B183-9026-4E12-00F2-001200540054}.Release.Build.0 = Release|Win32 - {5E18CC83-6092-48FE-A677-B832A0D3A650}.Debug.ActiveCfg = Debug|Win32 - {5E18CC83-6092-48FE-A677-B832A0D3A650}.Debug.Build.0 = Debug|Win32 - {5E18CC83-6092-48FE-A677-B832A0D3A650}.Release.ActiveCfg = Release|Win32 - {5E18CC83-6092-48FE-A677-B832A0D3A650}.Release.Build.0 = Release|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792649}.Debug.ActiveCfg = Debug|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792649}.Debug.Build.0 = Debug|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792649}.Release.ActiveCfg = Release|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792649}.Release.Build.0 = Release|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792648}.Debug.ActiveCfg = Debug|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792648}.Debug.Build.0 = Debug|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792648}.Release.ActiveCfg = Release|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792648}.Release.Build.0 = Release|Win32 - {58CCE183-6092-48FE-A4FC-BA0D3A792647}.Debug.ActiveCfg = Debug|Win32 - {58CCE183-6092-48FE-A4FC-BA0D3A792647}.Debug.Build.0 = Debug|Win32 - {58CCE183-6092-48FE-A4FC-BA0D3A792647}.Release.ActiveCfg = Release|Win32 - {58CCE183-6092-48FE-A4FC-BA0D3A792647}.Release.Build.0 = Release|Win32 - {58CCE183-5091-48FE-A4FC-BA0D3A792446}.Debug.ActiveCfg = Debug|Win32 - {58CCE183-5091-48FE-A4FC-BA0D3A792446}.Debug.Build.0 = Debug|Win32 - {58CCE183-5091-48FE-A4FC-BA0D3A792446}.Release.ActiveCfg = Release|Win32 - {58CCE183-5091-48FE-A4FC-BA0D3A792446}.Release.Build.0 = Release|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792645}.Debug.ActiveCfg = Debug|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792645}.Debug.Build.0 = Debug|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792645}.Release.ActiveCfg = Release|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792645}.Release.Build.0 = Release|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792644}.Debug.ActiveCfg = Debug|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792644}.Debug.Build.0 = Debug|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792644}.Release.ActiveCfg = Release|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792644}.Release.Build.0 = Release|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792643}.Debug.ActiveCfg = Debug|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792643}.Debug.Build.0 = Debug|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792643}.Release.ActiveCfg = Release|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792643}.Release.Build.0 = Release|Win32 - {58CC8E13-0962-8F4E-77A6-BD3A6832A042}.Debug.ActiveCfg = Debug|Win32 - {58CC8E13-0962-8F4E-77A6-BD3A6832A042}.Debug.Build.0 = Debug|Win32 - {58CC8E13-0962-8F4E-77A6-BD3A6832A042}.Release.ActiveCfg = Release|Win32 - {58CC8E13-0962-8F4E-77A6-BD3A6832A042}.Release.Build.0 = Release|Win32 - {58C1B183-9260-4E8F-F200-000000000041}.Debug.ActiveCfg = Debug|Win32 - {58C1B183-9260-4E8F-F200-000000000041}.Debug.Build.0 = Debug|Win32 - {58C1B183-9260-4E8F-F200-000000000041}.Release.ActiveCfg = Release|Win32 - {58C1B183-9260-4E8F-F200-000000000041}.Release.Build.0 = Release|Win32 - {58CCE183-6092-48FE-A677-BA0D3A832640}.Debug.ActiveCfg = Debug|Win32 - {58CCE183-6092-48FE-A677-BA0D3A832640}.Debug.Build.0 = Debug|Win32 - {58CCE183-6092-48FE-A677-BA0D3A832640}.Release.ActiveCfg = Release|Win32 - {58CCE183-6092-48FE-A677-BA0D3A832640}.Release.Build.0 = Release|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792639}.Debug.ActiveCfg = Debug|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792639}.Debug.Build.0 = Debug|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792639}.Release.ActiveCfg = Release|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792639}.Release.Build.0 = Release|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792638}.Debug.ActiveCfg = Debug|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792638}.Debug.Build.0 = Debug|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792638}.Release.ActiveCfg = Release|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792638}.Release.Build.0 = Release|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792637}.Debug.ActiveCfg = Debug|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792637}.Debug.Build.0 = Debug|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792637}.Release.ActiveCfg = Release|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792637}.Release.Build.0 = Release|Win32 - {FFAA56F1-32EC-4B22-B6BD-95A311A67C35}.Debug.ActiveCfg = Debug|Win32 - {FFAA56F1-32EC-4B22-B6BD-95A311A67C35}.Debug.Build.0 = Debug|Win32 - {FFAA56F1-32EC-4B22-B6BD-95A311A67C35}.Release.ActiveCfg = Release|Win32 - {FFAA56F1-32EC-4B22-B6BD-95A311A67C35}.Release.Build.0 = Release|Win32 - {58CCE183-6092-12FE-A4F7-BA0D3A767634}.Debug.ActiveCfg = Debug|Win32 - {58CCE183-6092-12FE-A4F7-BA0D3A767634}.Debug.Build.0 = Debug|Win32 - {58CCE183-6092-12FE-A4F7-BA0D3A767634}.Release.ActiveCfg = Release|Win32 - {58CCE183-6092-12FE-A4F7-BA0D3A767634}.Release.Build.0 = Release|Win32 - {5821C383-6092-12FE-A877-BA0D33467633}.Debug.ActiveCfg = Debug|Win32 - {5821C383-6092-12FE-A877-BA0D33467633}.Debug.Build.0 = Debug|Win32 - {5821C383-6092-12FE-A877-BA0D33467633}.Release.ActiveCfg = Release|Win32 - {5821C383-6092-12FE-A877-BA0D33467633}.Release.Build.0 = Release|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792632}.Debug.ActiveCfg = Debug|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792632}.Debug.Build.0 = Debug|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792632}.Release.ActiveCfg = Release|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792632}.Release.Build.0 = Release|Win32 - {5CCE1883-0926-F7A4-8FE4-BA0606D92331}.Debug.ActiveCfg = Debug|Win32 - {5CCE1883-0926-F7A4-8FE4-BA0606D92331}.Debug.Build.0 = Debug|Win32 - {5CCE1883-0926-F7A4-8FE4-BA0606D92331}.Release.ActiveCfg = Release|Win32 - {5CCE1883-0926-F7A4-8FE4-BA0606D92331}.Release.Build.0 = Release|Win32 - {5C6D9CE1-2609-F7A4-8FE4-BA0883602330}.Debug.ActiveCfg = Debug|Win32 - {5C6D9CE1-2609-F7A4-8FE4-BA0883602330}.Debug.Build.0 = Debug|Win32 - {5C6D9CE1-2609-F7A4-8FE4-BA0883602330}.Release.ActiveCfg = Release|Win32 - {5C6D9CE1-2609-F7A4-8FE4-BA0883602330}.Release.Build.0 = Release|Win32 - {58E18CC3-6092-8F4E-A3E7-A792230D3629}.Debug.ActiveCfg = Debug|Win32 - {58E18CC3-6092-8F4E-A3E7-A792230D3629}.Debug.Build.0 = Debug|Win32 - {58E18CC3-6092-8F4E-A3E7-A792230D3629}.Release.ActiveCfg = Release|Win32 - {58E18CC3-6092-8F4E-A3E7-A792230D3629}.Release.Build.0 = Release|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792628}.Debug.ActiveCfg = Debug|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792628}.Debug.Build.0 = Debug|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792628}.Release.ActiveCfg = Release|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792628}.Release.Build.0 = Release|Win32 - {83581CCE-487E-3292-A4E7-BA07926D3A27}.Debug.ActiveCfg = Debug|Win32 - {83581CCE-487E-3292-A4E7-BA07926D3A27}.Debug.Build.0 = Debug|Win32 - {83581CCE-487E-3292-A4E7-BA07926D3A27}.Release.ActiveCfg = Release|Win32 - {83581CCE-487E-3292-A4E7-BA07926D3A27}.Release.Build.0 = Release|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792626}.Debug.ActiveCfg = Debug|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792626}.Debug.Build.0 = Debug|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792626}.Release.ActiveCfg = Release|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792626}.Release.Build.0 = Release|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792625}.Debug.ActiveCfg = Debug|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792625}.Debug.Build.0 = Debug|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792625}.Release.ActiveCfg = Release|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792625}.Release.Build.0 = Release|Win32 - {5C83CE18-4F48-A7FE-6092-B7920AD3A624}.Debug.ActiveCfg = Debug|Win32 - {5C83CE18-4F48-A7FE-6092-B7920AD3A624}.Debug.Build.0 = Debug|Win32 - {5C83CE18-4F48-A7FE-6092-B7920AD3A624}.Release.ActiveCfg = Release|Win32 - {5C83CE18-4F48-A7FE-6092-B7920AD3A624}.Release.Build.0 = Release|Win32 - {58CCE283-1609-48FE-A4F7-BA0D3A793523}.Debug.ActiveCfg = Debug|Win32 - {58CCE283-1609-48FE-A4F7-BA0D3A793523}.Debug.Build.0 = Debug|Win32 - {58CCE283-1609-48FE-A4F7-BA0D3A793523}.Release.ActiveCfg = Release|Win32 - {58CCE283-1609-48FE-A4F7-BA0D3A793523}.Release.Build.0 = Release|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792622}.Debug.ActiveCfg = Debug|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792622}.Debug.Build.0 = Debug|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792622}.Release.ActiveCfg = Release|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792622}.Release.Build.0 = Release|Win32 - {0000058C-0000-0000-0000-000000000021}.Debug.ActiveCfg = Debug|Win32 - {0000058C-0000-0000-0000-000000000021}.Debug.Build.0 = Debug|Win32 - {0000058C-0000-0000-0000-000000000021}.Release.ActiveCfg = Release|Win32 - {0000058C-0000-0000-0000-000000000021}.Release.Build.0 = Release|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792620}.Debug.ActiveCfg = Debug|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792620}.Debug.Build.0 = Debug|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792620}.Release.ActiveCfg = Release|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792620}.Release.Build.0 = Release|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792619}.Debug.ActiveCfg = Debug|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792619}.Debug.Build.0 = Debug|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792619}.Release.ActiveCfg = Release|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792619}.Release.Build.0 = Release|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792618}.Debug.ActiveCfg = Debug|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792618}.Debug.Build.0 = Debug|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792618}.Release.ActiveCfg = Release|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792618}.Release.Build.0 = Release|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792617}.Debug.ActiveCfg = Debug|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792617}.Debug.Build.0 = Debug|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792617}.Release.ActiveCfg = Release|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792617}.Release.Build.0 = Release|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792616}.Debug.ActiveCfg = Debug|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792616}.Debug.Build.0 = Debug|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792616}.Release.ActiveCfg = Release|Win32 - {58CCE183-6092-48FE-A4F7-BA0D3A792616}.Release.Build.0 = Release|Win32 - {83581CCE-487E-3292-A4E7-BA07926D3A14}.Debug.ActiveCfg = Debug|Win32 - {83581CCE-487E-3292-A4E7-BA07926D3A14}.Debug.Build.0 = Debug|Win32 - {83581CCE-487E-3292-A4E7-BA07926D3A14}.Release.ActiveCfg = Release|Win32 - {83581CCE-487E-3292-A4E7-BA07926D3A14}.Release.Build.0 = Release|Win32 - {5CE28C83-48FE-1676-4FA7-B50D3A76A013}.Debug.ActiveCfg = Debug|Win32 - {5CE28C83-48FE-1676-4FA7-B50D3A76A013}.Debug.Build.0 = Debug|Win32 - {5CE28C83-48FE-1676-4FA7-B50D3A76A013}.Release.ActiveCfg = Release|Win32 - {5CE28C83-48FE-1676-4FA7-B50D3A76A013}.Release.Build.0 = Release|Win32 {5CE18C83-6025-36FE-A4F7-BA09176D3A11}.Debug.ActiveCfg = Debug|Win32 {5CE18C83-6025-36FE-A4F7-BA09176D3A11}.Debug.Build.0 = Debug|Win32 {5CE18C83-6025-36FE-A4F7-BA09176D3A11}.Release.ActiveCfg = Release|Win32 @@ -613,6 +555,306 @@ Global {58C1B183-0296-EA42-EF04-005120054104}.Debug.Build.0 = Debug|Win32 {58C1B183-0296-EA42-EF04-005120054104}.Release.ActiveCfg = Release|Win32 {58C1B183-0296-EA42-EF04-005120054104}.Release.Build.0 = Release|Win32 + {588CCD13-2962-83FE-F4B7-92230DB73629}.Debug.ActiveCfg = Debug|Win32 + {588CCD13-2962-83FE-F4B7-92230DB73629}.Debug.Build.0 = Debug|Win32 + {588CCD13-2962-83FE-F4B7-92230DB73629}.Release.ActiveCfg = Release|Win32 + {588CCD13-2962-83FE-F4B7-92230DB73629}.Release.Build.0 = Release|Win32 + {51D8E9C3-2D65-48FE-3AA7-7922C0E36329}.Debug.ActiveCfg = Debug|Win32 + {51D8E9C3-2D65-48FE-3AA7-7922C0E36329}.Debug.Build.0 = Debug|Win32 + {51D8E9C3-2D65-48FE-3AA7-7922C0E36329}.Release.ActiveCfg = Release|Win32 + {51D8E9C3-2D65-48FE-3AA7-7922C0E36329}.Release.Build.0 = Release|Win32 + {58BD1CC3-6972-F3F7-84BE-0DB736035922}.Debug.ActiveCfg = Debug|Win32 + {58BD1CC3-6972-F3F7-84BE-0DB736035922}.Debug.Build.0 = Debug|Win32 + {58BD1CC3-6972-F3F7-84BE-0DB736035922}.Release.ActiveCfg = Release|Win32 + {58BD1CC3-6972-F3F7-84BE-0DB736035922}.Release.Build.0 = Release|Win32 + {5BD1C7C3-3F7F-6972-84BE-B731D9236035}.Debug.ActiveCfg = Debug|Win32 + {5BD1C7C3-3F7F-6972-84BE-B731D9236035}.Debug.Build.0 = Debug|Win32 + {5BD1C7C3-3F7F-6972-84BE-B731D9236035}.Release.ActiveCfg = Release|Win32 + {5BD1C7C3-3F7F-6972-84BE-B731D9236035}.Release.Build.0 = Release|Win32 + {58CE1D83-F31E-4FD7-6132-8A79F6307B61}.Debug.ActiveCfg = Debug|Win32 + {58CE1D83-F31E-4FD7-6132-8A79F6307B61}.Debug.Build.0 = Debug|Win32 + {58CE1D83-F31E-4FD7-6132-8A79F6307B61}.Release.ActiveCfg = Release|Win32 + {58CE1D83-F31E-4FD7-6132-8A79F6307B61}.Release.Build.0 = Release|Win32 + {5CE19883-F413-7EFD-6342-B79639F7B611}.Debug.ActiveCfg = Debug|Win32 + {5CE19883-F413-7EFD-6342-B79639F7B611}.Debug.Build.0 = Debug|Win32 + {5CE19883-F413-7EFD-6342-B79639F7B611}.Release.ActiveCfg = Release|Win32 + {5CE19883-F413-7EFD-6342-B79639F7B611}.Release.Build.0 = Release|Win32 + {58DE18C3-3261-2F3E-FD47-83760B9FA761}.Debug.ActiveCfg = Debug|Win32 + {58DE18C3-3261-2F3E-FD47-83760B9FA761}.Debug.Build.0 = Debug|Win32 + {58DE18C3-3261-2F3E-FD47-83760B9FA761}.Release.ActiveCfg = Release|Win32 + {58DE18C3-3261-2F3E-FD47-83760B9FA761}.Release.Build.0 = Release|Win32 + {59CEC183-8192-8F6D-4FB7-BA260A79D352}.Debug.ActiveCfg = Debug|Win32 + {59CEC183-8192-8F6D-4FB7-BA260A79D352}.Debug.Build.0 = Debug|Win32 + {59CEC183-8192-8F6D-4FB7-BA260A79D352}.Release.ActiveCfg = Release|Win32 + {59CEC183-8192-8F6D-4FB7-BA260A79D352}.Release.Build.0 = Release|Win32 + {E385C28C-0691-4FA7-F48E-935BA0D06310}.Debug.ActiveCfg = Debug|Win32 + {E385C28C-0691-4FA7-F48E-935BA0D06310}.Debug.Build.0 = Debug|Win32 + {E385C28C-0691-4FA7-F48E-935BA0D06310}.Release.ActiveCfg = Release|Win32 + {E385C28C-0691-4FA7-F48E-935BA0D06310}.Release.Build.0 = Release|Win32 + {518CE8C3-6512-FA75-46EF-B917A3A116D1}.Debug.ActiveCfg = Debug|Win32 + {518CE8C3-6512-FA75-46EF-B917A3A116D1}.Debug.Build.0 = Debug|Win32 + {518CE8C3-6512-FA75-46EF-B917A3A116D1}.Release.ActiveCfg = Release|Win32 + {518CE8C3-6512-FA75-46EF-B917A3A116D1}.Release.Build.0 = Release|Win32 + {5D18CE83-1926-7AE4-FE94-B606D9B23131}.Debug.ActiveCfg = Debug|Win32 + {5D18CE83-1926-7AE4-FE94-B606D9B23131}.Debug.Build.0 = Debug|Win32 + {5D18CE83-1926-7AE4-FE94-B606D9B23131}.Release.ActiveCfg = Release|Win32 + {5D18CE83-1926-7AE4-FE94-B606D9B23131}.Release.Build.0 = Release|Win32 + {58CE1D84-1962-4FE9-BA0D-A4F7973A4652}.Debug.ActiveCfg = Debug|Win32 + {58CE1D84-1962-4FE9-BA0D-A4F7973A4652}.Debug.Build.0 = Debug|Win32 + {58CE1D84-1962-4FE9-BA0D-A4F7973A4652}.Release.ActiveCfg = Release|Win32 + {58CE1D84-1962-4FE9-BA0D-A4F7973A4652}.Release.Build.0 = Release|Win32 + {5188E3CE-2964-F43E-FB87-B037AC692D59}.Debug.ActiveCfg = Debug|Win32 + {5188E3CE-2964-F43E-FB87-B037AC692D59}.Debug.Build.0 = Debug|Win32 + {5188E3CE-2964-F43E-FB87-B037AC692D59}.Release.ActiveCfg = Release|Win32 + {5188E3CE-2964-F43E-FB87-B037AC692D59}.Release.Build.0 = Release|Win32 + {5CE14C83-4962-8F5E-4FA7-B0D3A7B93635}.Debug.ActiveCfg = Debug|Win32 + {5CE14C83-4962-8F5E-4FA7-B0D3A7B93635}.Debug.Build.0 = Debug|Win32 + {5CE14C83-4962-8F5E-4FA7-B0D3A7B93635}.Release.ActiveCfg = Release|Win32 + {5CE14C83-4962-8F5E-4FA7-B0D3A7B93635}.Release.Build.0 = Release|Win32 + {581B1C83-4E12-9526-020F-012482540054}.Debug.ActiveCfg = Debug|Win32 + {581B1C83-4E12-9526-020F-012482540054}.Debug.Build.0 = Debug|Win32 + {581B1C83-4E12-9526-020F-012482540054}.Release.ActiveCfg = Release|Win32 + {581B1C83-4E12-9526-020F-012482540054}.Release.Build.0 = Release|Win32 + {51B17C83-E172-5396-0FA2-825472008554}.Debug.ActiveCfg = Debug|Win32 + {51B17C83-E172-5396-0FA2-825472008554}.Debug.Build.0 = Debug|Win32 + {51B17C83-E172-5396-0FA2-825472008554}.Release.ActiveCfg = Release|Win32 + {51B17C83-E172-5396-0FA2-825472008554}.Release.Build.0 = Release|Win32 + {2B75C833-17D2-4956-A23F-820854254175}.Debug.ActiveCfg = Debug|Win32 + {2B75C833-17D2-4956-A23F-820854254175}.Debug.Build.0 = Debug|Win32 + {2B75C833-17D2-4956-A23F-820854254175}.Release.ActiveCfg = Release|Win32 + {2B75C833-17D2-4956-A23F-820854254175}.Release.Build.0 = Release|Win32 + {283AD375-7D12-5866-23BF-854308651275}.Debug.ActiveCfg = Debug|Win32 + {283AD375-7D12-5866-23BF-854308651275}.Debug.Build.0 = Debug|Win32 + {283AD375-7D12-5866-23BF-854308651275}.Release.ActiveCfg = Release|Win32 + {283AD375-7D12-5866-23BF-854308651275}.Release.Build.0 = Release|Win32 + {57C832B1-17D2-9537-FA12-827220448554}.Debug.ActiveCfg = Debug|Win32 + {57C832B1-17D2-9537-FA12-827220448554}.Debug.Build.0 = Debug|Win32 + {57C832B1-17D2-9537-FA12-827220448554}.Release.ActiveCfg = Release|Win32 + {57C832B1-17D2-9537-FA12-827220448554}.Release.Build.0 = Release|Win32 + {536C8251-7E12-9537-A1E2-822073258554}.Debug.ActiveCfg = Debug|Win32 + {536C8251-7E12-9537-A1E2-822073258554}.Debug.Build.0 = Debug|Win32 + {536C8251-7E12-9537-A1E2-822073258554}.Release.ActiveCfg = Release|Win32 + {536C8251-7E12-9537-A1E2-822073258554}.Release.Build.0 = Release|Win32 + {83258CB1-127E-9375-F872-8324A1054454}.Debug.ActiveCfg = Debug|Win32 + {83258CB1-127E-9375-F872-8324A1054454}.Debug.Build.0 = Debug|Win32 + {83258CB1-127E-9375-F872-8324A1054454}.Release.ActiveCfg = Release|Win32 + {83258CB1-127E-9375-F872-8324A1054454}.Release.Build.0 = Release|Win32 + {5198EFC3-2731-F34E-4FD8-1859AC94F761}.Debug.ActiveCfg = Debug|Win32 + {5198EFC3-2731-F34E-4FD8-1859AC94F761}.Debug.Build.0 = Debug|Win32 + {5198EFC3-2731-F34E-4FD8-1859AC94F761}.Release.ActiveCfg = Release|Win32 + {5198EFC3-2731-F34E-4FD8-1859AC94F761}.Release.Build.0 = Release|Win32 + {58DE18C3-3261-2F3E-FD47-83760B9FA761}.Debug.ActiveCfg = Debug|Win32 + {58DE18C3-3261-2F3E-FD47-83760B9FA761}.Debug.Build.0 = Debug|Win32 + {58DE18C3-3261-2F3E-FD47-83760B9FA761}.Release.ActiveCfg = Release|Win32 + {58DE18C3-3261-2F3E-FD47-83760B9FA761}.Release.Build.0 = Release|Win32 + {FFAA56F1-32EC-4B22-B6BD-95A311A67C35}.Debug.ActiveCfg = Debug|Win32 + {FFAA56F1-32EC-4B22-B6BD-95A311A67C35}.Debug.Build.0 = Debug|Win32 + {FFAA56F1-32EC-4B22-B6BD-95A311A67C35}.Release.ActiveCfg = Release|Win32 + {FFAA56F1-32EC-4B22-B6BD-95A311A67C35}.Release.Build.0 = Release|Win32 + {5E17C9C3-1362-2E1E-C84F-8A76B6739F21}.Debug.ActiveCfg = Debug|Win32 + {5E17C9C3-1362-2E1E-C84F-8A76B6739F21}.Debug.Build.0 = Debug|Win32 + {5E17C9C3-1362-2E1E-C84F-8A76B6739F21}.Release.ActiveCfg = Release|Win32 + {5E17C9C3-1362-2E1E-C84F-8A76B6739F21}.Release.Build.0 = Release|Win32 + {5E1D6C83-31DE-4F6F-6132-87A9FB663041}.Debug.ActiveCfg = Debug|Win32 + {5E1D6C83-31DE-4F6F-6132-87A9FB663041}.Debug.Build.0 = Debug|Win32 + {5E1D6C83-31DE-4F6F-6132-87A9FB663041}.Release.ActiveCfg = Release|Win32 + {5E1D6C83-31DE-4F6F-6132-87A9FB663041}.Release.Build.0 = Release|Win32 + {CD57C283-1862-42FE-BF87-B96D3A2A7912}.Debug.ActiveCfg = Debug|Win32 + {CD57C283-1862-42FE-BF87-B96D3A2A7912}.Debug.Build.0 = Debug|Win32 + {CD57C283-1862-42FE-BF87-B96D3A2A7912}.Release.ActiveCfg = Release|Win32 + {CD57C283-1862-42FE-BF87-B96D3A2A7912}.Release.Build.0 = Release|Win32 + {8A519DC3-6092-A4FE-F748-BA91328D6522}.Debug.ActiveCfg = Debug|Win32 + {8A519DC3-6092-A4FE-F748-BA91328D6522}.Debug.Build.0 = Debug|Win32 + {8A519DC3-6092-A4FE-F748-BA91328D6522}.Release.ActiveCfg = Release|Win32 + {8A519DC3-6092-A4FE-F748-BA91328D6522}.Release.Build.0 = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792655}.Debug.ActiveCfg = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792655}.Debug.Build.0 = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792655}.Release.ActiveCfg = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792655}.Release.Build.0 = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792661}.Debug.ActiveCfg = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792661}.Debug.Build.0 = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792661}.Release.ActiveCfg = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792661}.Release.Build.0 = Release|Win32 + {58C183CE-6203-FE12-A237-BA8976695960}.Debug.ActiveCfg = Debug|Win32 + {58C183CE-6203-FE12-A237-BA8976695960}.Debug.Build.0 = Debug|Win32 + {58C183CE-6203-FE12-A237-BA8976695960}.Release.ActiveCfg = Release|Win32 + {58C183CE-6203-FE12-A237-BA8976695960}.Release.Build.0 = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792659}.Debug.ActiveCfg = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792659}.Debug.Build.0 = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792659}.Release.ActiveCfg = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792659}.Release.Build.0 = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792620}.Debug.ActiveCfg = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792620}.Debug.Build.0 = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792620}.Release.ActiveCfg = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792620}.Release.Build.0 = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792622}.Debug.ActiveCfg = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792622}.Debug.Build.0 = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792622}.Release.ActiveCfg = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792622}.Release.Build.0 = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792625}.Debug.ActiveCfg = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792625}.Debug.Build.0 = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792625}.Release.ActiveCfg = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792625}.Release.Build.0 = Release|Win32 + {5C83CE18-4F48-A7FE-6092-B7920AD3A624}.Debug.ActiveCfg = Debug|Win32 + {5C83CE18-4F48-A7FE-6092-B7920AD3A624}.Debug.Build.0 = Debug|Win32 + {5C83CE18-4F48-A7FE-6092-B7920AD3A624}.Release.ActiveCfg = Release|Win32 + {5C83CE18-4F48-A7FE-6092-B7920AD3A624}.Release.Build.0 = Release|Win32 + {58CCE283-1609-48FE-A4F7-BA0D3A793523}.Debug.ActiveCfg = Debug|Win32 + {58CCE283-1609-48FE-A4F7-BA0D3A793523}.Debug.Build.0 = Debug|Win32 + {58CCE283-1609-48FE-A4F7-BA0D3A793523}.Release.ActiveCfg = Release|Win32 + {58CCE283-1609-48FE-A4F7-BA0D3A793523}.Release.Build.0 = Release|Win32 + {58CCE183-6092-48FE-A4FC-BA0D3A792647}.Debug.ActiveCfg = Debug|Win32 + {58CCE183-6092-48FE-A4FC-BA0D3A792647}.Debug.Build.0 = Debug|Win32 + {58CCE183-6092-48FE-A4FC-BA0D3A792647}.Release.ActiveCfg = Release|Win32 + {58CCE183-6092-48FE-A4FC-BA0D3A792647}.Release.Build.0 = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792663}.Debug.ActiveCfg = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792663}.Debug.Build.0 = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792663}.Release.ActiveCfg = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792663}.Release.Build.0 = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792662}.Debug.ActiveCfg = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792662}.Debug.Build.0 = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792662}.Release.ActiveCfg = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792662}.Release.Build.0 = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792658}.Debug.ActiveCfg = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792658}.Debug.Build.0 = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792658}.Release.ActiveCfg = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792658}.Release.Build.0 = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792657}.Debug.ActiveCfg = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792657}.Debug.Build.0 = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792657}.Release.ActiveCfg = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792657}.Release.Build.0 = Release|Win32 + {58C1B183-9026-4E12-00F2-001200540054}.Debug.ActiveCfg = Debug|Win32 + {58C1B183-9026-4E12-00F2-001200540054}.Debug.Build.0 = Debug|Win32 + {58C1B183-9026-4E12-00F2-001200540054}.Release.ActiveCfg = Release|Win32 + {58C1B183-9026-4E12-00F2-001200540054}.Release.Build.0 = Release|Win32 + {5E18CC83-6092-48FE-A677-B832A0D3A650}.Debug.ActiveCfg = Debug|Win32 + {5E18CC83-6092-48FE-A677-B832A0D3A650}.Debug.Build.0 = Debug|Win32 + {5E18CC83-6092-48FE-A677-B832A0D3A650}.Release.ActiveCfg = Release|Win32 + {5E18CC83-6092-48FE-A677-B832A0D3A650}.Release.Build.0 = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792649}.Debug.ActiveCfg = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792649}.Debug.Build.0 = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792649}.Release.ActiveCfg = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792649}.Release.Build.0 = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792648}.Debug.ActiveCfg = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792648}.Debug.Build.0 = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792648}.Release.ActiveCfg = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792648}.Release.Build.0 = Release|Win32 + {58CCE183-5091-48FE-A4FC-BA0D3A792446}.Debug.ActiveCfg = Debug|Win32 + {58CCE183-5091-48FE-A4FC-BA0D3A792446}.Debug.Build.0 = Debug|Win32 + {58CCE183-5091-48FE-A4FC-BA0D3A792446}.Release.ActiveCfg = Release|Win32 + {58CCE183-5091-48FE-A4FC-BA0D3A792446}.Release.Build.0 = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792645}.Debug.ActiveCfg = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792645}.Debug.Build.0 = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792645}.Release.ActiveCfg = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792645}.Release.Build.0 = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792644}.Debug.ActiveCfg = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792644}.Debug.Build.0 = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792644}.Release.ActiveCfg = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792644}.Release.Build.0 = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792643}.Debug.ActiveCfg = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792643}.Debug.Build.0 = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792643}.Release.ActiveCfg = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792643}.Release.Build.0 = Release|Win32 + {58CC8E13-0962-8F4E-77A6-BD3A6832A042}.Debug.ActiveCfg = Debug|Win32 + {58CC8E13-0962-8F4E-77A6-BD3A6832A042}.Debug.Build.0 = Debug|Win32 + {58CC8E13-0962-8F4E-77A6-BD3A6832A042}.Release.ActiveCfg = Release|Win32 + {58CC8E13-0962-8F4E-77A6-BD3A6832A042}.Release.Build.0 = Release|Win32 + {58C1B183-9260-4E8F-F200-000000000041}.Debug.ActiveCfg = Debug|Win32 + {58C1B183-9260-4E8F-F200-000000000041}.Debug.Build.0 = Debug|Win32 + {58C1B183-9260-4E8F-F200-000000000041}.Release.ActiveCfg = Release|Win32 + {58C1B183-9260-4E8F-F200-000000000041}.Release.Build.0 = Release|Win32 + {58CCE183-6092-48FE-A677-BA0D3A832640}.Debug.ActiveCfg = Debug|Win32 + {58CCE183-6092-48FE-A677-BA0D3A832640}.Debug.Build.0 = Debug|Win32 + {58CCE183-6092-48FE-A677-BA0D3A832640}.Release.ActiveCfg = Release|Win32 + {58CCE183-6092-48FE-A677-BA0D3A832640}.Release.Build.0 = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792639}.Debug.ActiveCfg = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792639}.Debug.Build.0 = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792639}.Release.ActiveCfg = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792639}.Release.Build.0 = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792638}.Debug.ActiveCfg = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792638}.Debug.Build.0 = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792638}.Release.ActiveCfg = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792638}.Release.Build.0 = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792637}.Debug.ActiveCfg = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792637}.Debug.Build.0 = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792637}.Release.ActiveCfg = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792637}.Release.Build.0 = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792636}.Debug.ActiveCfg = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792636}.Debug.Build.0 = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792636}.Release.ActiveCfg = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792636}.Release.Build.0 = Release|Win32 + {58CCE183-6092-12FE-A4F7-BA0D3A767634}.Debug.ActiveCfg = Debug|Win32 + {58CCE183-6092-12FE-A4F7-BA0D3A767634}.Debug.Build.0 = Debug|Win32 + {58CCE183-6092-12FE-A4F7-BA0D3A767634}.Release.ActiveCfg = Release|Win32 + {58CCE183-6092-12FE-A4F7-BA0D3A767634}.Release.Build.0 = Release|Win32 + {5821C383-6092-12FE-A877-BA0D33467633}.Debug.ActiveCfg = Debug|Win32 + {5821C383-6092-12FE-A877-BA0D33467633}.Debug.Build.0 = Debug|Win32 + {5821C383-6092-12FE-A877-BA0D33467633}.Release.ActiveCfg = Release|Win32 + {5821C383-6092-12FE-A877-BA0D33467633}.Release.Build.0 = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792632}.Debug.ActiveCfg = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792632}.Debug.Build.0 = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792632}.Release.ActiveCfg = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792632}.Release.Build.0 = Release|Win32 + {5CCE1883-0926-F7A4-8FE4-BA0606D92331}.Debug.ActiveCfg = Debug|Win32 + {5CCE1883-0926-F7A4-8FE4-BA0606D92331}.Debug.Build.0 = Debug|Win32 + {5CCE1883-0926-F7A4-8FE4-BA0606D92331}.Release.ActiveCfg = Release|Win32 + {5CCE1883-0926-F7A4-8FE4-BA0606D92331}.Release.Build.0 = Release|Win32 + {5C6D9CE1-2609-F7A4-8FE4-BA0883602330}.Debug.ActiveCfg = Debug|Win32 + {5C6D9CE1-2609-F7A4-8FE4-BA0883602330}.Debug.Build.0 = Debug|Win32 + {5C6D9CE1-2609-F7A4-8FE4-BA0883602330}.Release.ActiveCfg = Release|Win32 + {5C6D9CE1-2609-F7A4-8FE4-BA0883602330}.Release.Build.0 = Release|Win32 + {58E18CC3-6092-8F4E-A3E7-A792230D3629}.Debug.ActiveCfg = Debug|Win32 + {58E18CC3-6092-8F4E-A3E7-A792230D3629}.Debug.Build.0 = Debug|Win32 + {58E18CC3-6092-8F4E-A3E7-A792230D3629}.Release.ActiveCfg = Release|Win32 + {58E18CC3-6092-8F4E-A3E7-A792230D3629}.Release.Build.0 = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792628}.Debug.ActiveCfg = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792628}.Debug.Build.0 = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792628}.Release.ActiveCfg = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792628}.Release.Build.0 = Release|Win32 + {83581CCE-487E-3292-A4E7-BA07926D3A27}.Debug.ActiveCfg = Debug|Win32 + {83581CCE-487E-3292-A4E7-BA07926D3A27}.Debug.Build.0 = Debug|Win32 + {83581CCE-487E-3292-A4E7-BA07926D3A27}.Release.ActiveCfg = Release|Win32 + {83581CCE-487E-3292-A4E7-BA07926D3A27}.Release.Build.0 = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792626}.Debug.ActiveCfg = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792626}.Debug.Build.0 = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792626}.Release.ActiveCfg = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792626}.Release.Build.0 = Release|Win32 + {0000058C-0000-0000-0000-000000000021}.Debug.ActiveCfg = Debug|Win32 + {0000058C-0000-0000-0000-000000000021}.Debug.Build.0 = Debug|Win32 + {0000058C-0000-0000-0000-000000000021}.Release.ActiveCfg = Release|Win32 + {0000058C-0000-0000-0000-000000000021}.Release.Build.0 = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792619}.Debug.ActiveCfg = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792619}.Debug.Build.0 = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792619}.Release.ActiveCfg = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792619}.Release.Build.0 = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792618}.Debug.ActiveCfg = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792618}.Debug.Build.0 = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792618}.Release.ActiveCfg = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792618}.Release.Build.0 = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792617}.Debug.ActiveCfg = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792617}.Debug.Build.0 = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792617}.Release.ActiveCfg = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792617}.Release.Build.0 = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792616}.Debug.ActiveCfg = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792616}.Debug.Build.0 = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792616}.Release.ActiveCfg = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792616}.Release.Build.0 = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792615}.Debug.ActiveCfg = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792615}.Debug.Build.0 = Debug|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792615}.Release.ActiveCfg = Release|Win32 + {58CCE183-6092-48FE-A4F7-BA0D3A792615}.Release.Build.0 = Release|Win32 + {83581CCE-487E-3292-A4E7-BA07926D3A14}.Debug.ActiveCfg = Debug|Win32 + {83581CCE-487E-3292-A4E7-BA07926D3A14}.Debug.Build.0 = Debug|Win32 + {83581CCE-487E-3292-A4E7-BA07926D3A14}.Release.ActiveCfg = Release|Win32 + {83581CCE-487E-3292-A4E7-BA07926D3A14}.Release.Build.0 = Release|Win32 + {5CE28C83-48FE-1676-4FA7-B50D3A76A013}.Debug.ActiveCfg = Debug|Win32 + {5CE28C83-48FE-1676-4FA7-B50D3A76A013}.Debug.Build.0 = Debug|Win32 + {5CE28C83-48FE-1676-4FA7-B50D3A76A013}.Release.ActiveCfg = Release|Win32 + {5CE28C83-48FE-1676-4FA7-B50D3A76A013}.Release.Build.0 = Release|Win32 + {5E188CC3-0962-F7A4-8F4E-A0D3B606A712}.Debug.ActiveCfg = Debug|Win32 + {5E188CC3-0962-F7A4-8F4E-A0D3B606A712}.Debug.Build.0 = Debug|Win32 + {5E188CC3-0962-F7A4-8F4E-A0D3B606A712}.Release.ActiveCfg = Release|Win32 + {5E188CC3-0962-F7A4-8F4E-A0D3B606A712}.Release.Build.0 = Release|Win32 EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution EndGlobalSection diff --git a/proj/vc7ide/adaptive_node_pool_test.vcproj b/proj/vc7ide/adaptive_node_pool_test.vcproj new file mode 100644 index 0000000..391b2bd --- /dev/null +++ b/proj/vc7ide/adaptive_node_pool_test.vcproj @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/adaptive_pool_test.vcproj b/proj/vc7ide/adaptive_pool_test.vcproj new file mode 100644 index 0000000..0eca59d --- /dev/null +++ b/proj/vc7ide/adaptive_pool_test.vcproj @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/allocexcept_test.vcproj b/proj/vc7ide/allocexcept_test.vcproj index 9e519d8..1db5fff 100644 --- a/proj/vc7ide/allocexcept_test.vcproj +++ b/proj/vc7ide/allocexcept_test.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="allocexcept_test" + ProjectGUID="{58CCE183-6092-48FE-A4F7-BA0D3A792662}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/barrier_test.vcproj b/proj/vc7ide/barrier_test.vcproj index 4a8c2b3..da9854c 100644 --- a/proj/vc7ide/barrier_test.vcproj +++ b/proj/vc7ide/barrier_test.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="barrier_test" + ProjectGUID="{58CCE183-6092-48FE-A4F7-BA0D3A792661}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/bufferstream_test.vcproj b/proj/vc7ide/bufferstream_test.vcproj index 0fbc99c..ff96eed 100644 --- a/proj/vc7ide/bufferstream_test.vcproj +++ b/proj/vc7ide/bufferstream_test.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="bufferstream_test" + ProjectGUID="{58C183CE-6203-FE12-A237-BA8976695960}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/cached_adaptive_pool_test.vcproj b/proj/vc7ide/cached_adaptive_pool_test.vcproj new file mode 100644 index 0000000..4c652a8 --- /dev/null +++ b/proj/vc7ide/cached_adaptive_pool_test.vcproj @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/cached_node_allocator_test.vcproj b/proj/vc7ide/cached_node_allocator_test.vcproj index ac9c375..8ed8120 100644 --- a/proj/vc7ide/cached_node_allocator_test.vcproj +++ b/proj/vc7ide/cached_node_allocator_test.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="cached_node_allocator_test" + ProjectGUID="{58CCE183-6092-48FE-A4F7-BA0D3A792659}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/condition_test.vcproj b/proj/vc7ide/condition_test.vcproj index a6222ac..2d02e00 100644 --- a/proj/vc7ide/condition_test.vcproj +++ b/proj/vc7ide/condition_test.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="condition_test" + ProjectGUID="{58CCE183-6092-48FE-A4F7-BA0D3A792658}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/data_test.vcproj b/proj/vc7ide/data_test.vcproj index 79d04a8..68d2f15 100644 --- a/proj/vc7ide/data_test.vcproj +++ b/proj/vc7ide/data_test.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="data_test" + ProjectGUID="{58CCE183-6092-48FE-A4F7-BA0D3A792657}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/deque_test.vcproj b/proj/vc7ide/deque_test.vcproj index f4f6070..b0779df 100644 --- a/proj/vc7ide/deque_test.vcproj +++ b/proj/vc7ide/deque_test.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="deque_test" + ProjectGUID="{58CCE183-6092-48FE-A4F7-BA0D3A792655}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/doc_adaptive_pool.vcproj b/proj/vc7ide/doc_adaptive_pool.vcproj new file mode 100644 index 0000000..558121c --- /dev/null +++ b/proj/vc7ide/doc_adaptive_pool.vcproj @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/doc_allocator.vcproj b/proj/vc7ide/doc_allocator.vcproj new file mode 100644 index 0000000..a0e353b --- /dev/null +++ b/proj/vc7ide/doc_allocator.vcproj @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/doc_anonymous_conditionA.vcproj b/proj/vc7ide/doc_anonymous_conditionA.vcproj index 99b01db..03757b0 100644 --- a/proj/vc7ide/doc_anonymous_conditionA.vcproj +++ b/proj/vc7ide/doc_anonymous_conditionA.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="doc_anonymous_conditionA" + ProjectGUID="{5C1B8183-0296-4F83-1F22-001005220544}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/doc_anonymous_conditionB.vcproj b/proj/vc7ide/doc_anonymous_conditionB.vcproj index efe9713..ae21556 100644 --- a/proj/vc7ide/doc_anonymous_conditionB.vcproj +++ b/proj/vc7ide/doc_anonymous_conditionB.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="doc_anonymous_conditionB" + ProjectGUID="{58C1FE83-2906-E643-2F12-024410052254}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/doc_anonymous_mutexA.vcproj b/proj/vc7ide/doc_anonymous_mutexA.vcproj index 91530b3..a34c0ea 100644 --- a/proj/vc7ide/doc_anonymous_mutexA.vcproj +++ b/proj/vc7ide/doc_anonymous_mutexA.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="doc_anonymous_mutexA" + ProjectGUID="{58C1B183-9026-4E63-12F2-005412200054}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/doc_anonymous_mutexB.vcproj b/proj/vc7ide/doc_anonymous_mutexB.vcproj index 2cf7332..cbd3873 100644 --- a/proj/vc7ide/doc_anonymous_mutexB.vcproj +++ b/proj/vc7ide/doc_anonymous_mutexB.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="doc_anonymous_mutexB" + ProjectGUID="{58C1B183-9026-4E63-12F2-005202441254}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/doc_anonymous_semaphoreA.vcproj b/proj/vc7ide/doc_anonymous_semaphoreA.vcproj index 2a8de77..6497b6d 100644 --- a/proj/vc7ide/doc_anonymous_semaphoreA.vcproj +++ b/proj/vc7ide/doc_anonymous_semaphoreA.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="doc_anonymous_semaphoreA" + ProjectGUID="{5CB81183-29FB-F843-24FF-022050100544}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/doc_anonymous_semaphoreB.vcproj b/proj/vc7ide/doc_anonymous_semaphoreB.vcproj index 80cf476..9ca14b9 100644 --- a/proj/vc7ide/doc_anonymous_semaphoreB.vcproj +++ b/proj/vc7ide/doc_anonymous_semaphoreB.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="doc_anonymous_semaphoreB" + ProjectGUID="{58FBE8C3-9026-FAB2-E643-000522441254}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/doc_anonymous_upgradable_mutexA.vcproj b/proj/vc7ide/doc_anonymous_upgradable_mutexA.vcproj index 8d066ba..cdace3d 100644 --- a/proj/vc7ide/doc_anonymous_upgradable_mutexA.vcproj +++ b/proj/vc7ide/doc_anonymous_upgradable_mutexA.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="doc_anonymous_upgradable_mutexA" + ProjectGUID="{5C18831B-F162-FA96-E6C3-FA5122040054}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/doc_anonymous_upgradable_mutexB.vcproj b/proj/vc7ide/doc_anonymous_upgradable_mutexB.vcproj index 9ff9615..46eb23f 100644 --- a/proj/vc7ide/doc_anonymous_upgradable_mutexB.vcproj +++ b/proj/vc7ide/doc_anonymous_upgradable_mutexB.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="doc_anonymous_upgradable_mutexB" + ProjectGUID="{5C1B1043-1EFF-2793-4E63-245241283054}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/doc_bufferstream.vcproj b/proj/vc7ide/doc_bufferstream.vcproj index c54a7c6..2f91e2e 100644 --- a/proj/vc7ide/doc_bufferstream.vcproj +++ b/proj/vc7ide/doc_bufferstream.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="doc_bufferstream" + ProjectGUID="{58C1B183-9026-4E12-00F2-001200540054}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/doc_cached_adaptive_pool.vcproj b/proj/vc7ide/doc_cached_adaptive_pool.vcproj new file mode 100644 index 0000000..7435660 --- /dev/null +++ b/proj/vc7ide/doc_cached_adaptive_pool.vcproj @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/doc_cached_node_allocator.vcproj b/proj/vc7ide/doc_cached_node_allocator.vcproj new file mode 100644 index 0000000..eed1a67 --- /dev/null +++ b/proj/vc7ide/doc_cached_node_allocator.vcproj @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/doc_cont.vcproj b/proj/vc7ide/doc_cont.vcproj index 86a7659..8f0ab55 100644 --- a/proj/vc7ide/doc_cont.vcproj +++ b/proj/vc7ide/doc_cont.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="doc_cont" + ProjectGUID="{58CCE183-6092-48FE-A4F7-BA0D3A792653}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/doc_contA.vcproj b/proj/vc7ide/doc_contA.vcproj index ed2bb56..6894ec8 100644 --- a/proj/vc7ide/doc_contA.vcproj +++ b/proj/vc7ide/doc_contA.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="doc_contA" + ProjectGUID="{58CCE183-6092-48FE-A4F7-BA0D3A792652}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/doc_contB.vcproj b/proj/vc7ide/doc_contB.vcproj index b177eda..ad92c09 100644 --- a/proj/vc7ide/doc_contB.vcproj +++ b/proj/vc7ide/doc_contB.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="doc_contB" + ProjectGUID="{58CCE183-6092-48FE-A4F7-BA0D3A792651}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/doc_file_mapping.vcproj b/proj/vc7ide/doc_file_mapping.vcproj new file mode 100644 index 0000000..0af092a --- /dev/null +++ b/proj/vc7ide/doc_file_mapping.vcproj @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/doc_file_mapping2.vcproj b/proj/vc7ide/doc_file_mapping2.vcproj new file mode 100644 index 0000000..159ab3f --- /dev/null +++ b/proj/vc7ide/doc_file_mapping2.vcproj @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/doc_intrusive.vcproj b/proj/vc7ide/doc_intrusive.vcproj index a7f383f..d0527cf 100644 --- a/proj/vc7ide/doc_intrusive.vcproj +++ b/proj/vc7ide/doc_intrusive.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="doc_intrusive" + ProjectGUID="{5E18CC83-6092-48FE-A677-B832A0D3A650}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/doc_ipc_messageA.vcproj b/proj/vc7ide/doc_ipc_messageA.vcproj index 595e24e..c501afc 100644 --- a/proj/vc7ide/doc_ipc_messageA.vcproj +++ b/proj/vc7ide/doc_ipc_messageA.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="doc_ipc_messageA" + ProjectGUID="{58CCE183-6092-48FE-A4F7-BA0D3A792649}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/doc_ipc_messageB.vcproj b/proj/vc7ide/doc_ipc_messageB.vcproj index e55bc5a..12f39d6 100644 --- a/proj/vc7ide/doc_ipc_messageB.vcproj +++ b/proj/vc7ide/doc_ipc_messageB.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="doc_ipc_messageB" + ProjectGUID="{58CCE183-6092-48FE-A4F7-BA0D3A792648}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/doc_managed_aligned_allocation.vcproj b/proj/vc7ide/doc_managed_aligned_allocation.vcproj new file mode 100644 index 0000000..fd9c603 --- /dev/null +++ b/proj/vc7ide/doc_managed_aligned_allocation.vcproj @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/doc_managed_heap_memory.vcproj b/proj/vc7ide/doc_managed_heap_memory.vcproj index aa474b4..a1f93be 100644 --- a/proj/vc7ide/doc_managed_heap_memory.vcproj +++ b/proj/vc7ide/doc_managed_heap_memory.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="doc_managed_heap_memory" + ProjectGUID="{58CCE183-6092-48FE-A4FC-BA0D3A792647}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/doc_managed_mapped_file.vcproj b/proj/vc7ide/doc_managed_mapped_file.vcproj index 5deaa0a..beb1668 100644 --- a/proj/vc7ide/doc_managed_mapped_file.vcproj +++ b/proj/vc7ide/doc_managed_mapped_file.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="doc_managed_mapped_file" + ProjectGUID="{58CCE183-5091-48FE-A4FC-BA0D3A792446}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/doc_managed_raw_allocation.vcproj b/proj/vc7ide/doc_managed_raw_allocation.vcproj new file mode 100644 index 0000000..dfce7b0 --- /dev/null +++ b/proj/vc7ide/doc_managed_raw_allocation.vcproj @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/doc_map.vcproj b/proj/vc7ide/doc_map.vcproj new file mode 100644 index 0000000..6f2ce4b --- /dev/null +++ b/proj/vc7ide/doc_map.vcproj @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/doc_message_queueA.vcproj b/proj/vc7ide/doc_message_queueA.vcproj index 6987c7c..51b5290 100644 --- a/proj/vc7ide/doc_message_queueA.vcproj +++ b/proj/vc7ide/doc_message_queueA.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="doc_message_queueA" + ProjectGUID="{51B189C3-4E63-9026-12F2-12200AF54054}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/doc_message_queueB.vcproj b/proj/vc7ide/doc_message_queueB.vcproj index b05d307..556a701 100644 --- a/proj/vc7ide/doc_message_queueB.vcproj +++ b/proj/vc7ide/doc_message_queueB.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="doc_message_queueB" + ProjectGUID="{5C1B1813-12C2-0296-4E63-244549126520}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/doc_move_containers.vcproj b/proj/vc7ide/doc_move_containers.vcproj index 2560b28..7069d71 100644 --- a/proj/vc7ide/doc_move_containers.vcproj +++ b/proj/vc7ide/doc_move_containers.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="doc_move_containers" + ProjectGUID="{58C1B183-0296-EA42-EF04-005120054104}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/doc_named_allocA.vcproj b/proj/vc7ide/doc_named_allocA.vcproj index b5f3ae7..9657649 100644 --- a/proj/vc7ide/doc_named_allocA.vcproj +++ b/proj/vc7ide/doc_named_allocA.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="doc_named_allocA" + ProjectGUID="{58CCE183-6092-48FE-A4F7-BA0D3A792645}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/doc_named_allocB.vcproj b/proj/vc7ide/doc_named_allocB.vcproj index 7c4824f..71fec55 100644 --- a/proj/vc7ide/doc_named_allocB.vcproj +++ b/proj/vc7ide/doc_named_allocB.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="doc_named_allocB" + ProjectGUID="{58CCE183-6092-48FE-A4F7-BA0D3A792644}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/doc_named_conditionA.vcproj b/proj/vc7ide/doc_named_conditionA.vcproj index d020168..b6ea04f 100644 --- a/proj/vc7ide/doc_named_conditionA.vcproj +++ b/proj/vc7ide/doc_named_conditionA.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="doc_named_conditionA" + ProjectGUID="{58EB1CB3-1354-364E-12F2-154356612054}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/doc_named_conditionB.vcproj b/proj/vc7ide/doc_named_conditionB.vcproj index fbae7e9..da90753 100644 --- a/proj/vc7ide/doc_named_conditionB.vcproj +++ b/proj/vc7ide/doc_named_conditionB.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="doc_named_conditionB" + ProjectGUID="{58181CB3-5134-634E-12F2-155435622054}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/doc_named_mutex.vcproj b/proj/vc7ide/doc_named_mutex.vcproj index 0b8f313..4071422 100644 --- a/proj/vc7ide/doc_named_mutex.vcproj +++ b/proj/vc7ide/doc_named_mutex.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="doc_named_mutex" + ProjectGUID="{58C181B3-9516-463E-2F12-122155400054}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/doc_node_allocator.vcproj b/proj/vc7ide/doc_node_allocator.vcproj new file mode 100644 index 0000000..53d527a --- /dev/null +++ b/proj/vc7ide/doc_node_allocator.vcproj @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/doc_offset_ptr.vcproj b/proj/vc7ide/doc_offset_ptr.vcproj index 1b03242..76769a6 100644 --- a/proj/vc7ide/doc_offset_ptr.vcproj +++ b/proj/vc7ide/doc_offset_ptr.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="doc_offset_ptr" + ProjectGUID="{58CCE183-6092-48FE-A4F7-BA0D3A792643}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/doc_private_adaptive_pool.vcproj b/proj/vc7ide/doc_private_adaptive_pool.vcproj new file mode 100644 index 0000000..690a203 --- /dev/null +++ b/proj/vc7ide/doc_private_adaptive_pool.vcproj @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/doc_private_node_allocator.vcproj b/proj/vc7ide/doc_private_node_allocator.vcproj new file mode 100644 index 0000000..91499f9 --- /dev/null +++ b/proj/vc7ide/doc_private_node_allocator.vcproj @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/doc_scoped_ptr.vcproj b/proj/vc7ide/doc_scoped_ptr.vcproj index dfaa91a..16acbc4 100644 --- a/proj/vc7ide/doc_scoped_ptr.vcproj +++ b/proj/vc7ide/doc_scoped_ptr.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="doc_scoped_ptr" + ProjectGUID="{58CC8E13-0962-8F4E-77A6-BD3A6832A042}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/doc_shared_memory.vcproj b/proj/vc7ide/doc_shared_memory.vcproj index 6c74b9f..c31a947 100644 --- a/proj/vc7ide/doc_shared_memory.vcproj +++ b/proj/vc7ide/doc_shared_memory.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="doc_shared_memory" + ProjectGUID="{58CCE183-6032-12FE-4FC7-83A79F760B61}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/doc_shared_memory2.vcproj b/proj/vc7ide/doc_shared_memory2.vcproj new file mode 100644 index 0000000..ee1d764 --- /dev/null +++ b/proj/vc7ide/doc_shared_memory2.vcproj @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/doc_vectorstream.vcproj b/proj/vc7ide/doc_vectorstream.vcproj index 3c65c36..c15b046 100644 --- a/proj/vc7ide/doc_vectorstream.vcproj +++ b/proj/vc7ide/doc_vectorstream.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="doc_vectorstream" + ProjectGUID="{58C1B183-9260-4E8F-F200-000000000041}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/doc_where_allocate.vcproj b/proj/vc7ide/doc_where_allocate.vcproj index 7338cb8..2d3d9a0 100644 --- a/proj/vc7ide/doc_where_allocate.vcproj +++ b/proj/vc7ide/doc_where_allocate.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="doc_where_allocate" + ProjectGUID="{58CCE183-6092-48FE-A677-BA0D3A832640}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/doc_windows_shared_memory.vcproj b/proj/vc7ide/doc_windows_shared_memory.vcproj new file mode 100644 index 0000000..45fa5a8 --- /dev/null +++ b/proj/vc7ide/doc_windows_shared_memory.vcproj @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/doc_windows_shared_memory2.vcproj b/proj/vc7ide/doc_windows_shared_memory2.vcproj new file mode 100644 index 0000000..a06b524 --- /dev/null +++ b/proj/vc7ide/doc_windows_shared_memory2.vcproj @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/file_mapping_test.vcproj b/proj/vc7ide/file_mapping_test.vcproj index 9bba543..bf60f1a 100644 --- a/proj/vc7ide/file_mapping_test.vcproj +++ b/proj/vc7ide/file_mapping_test.vcproj @@ -1,135 +1,135 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="file_mapping_test" + ProjectGUID="{58CCE183-6092-48FE-A4F7-BA0D3A792638}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/flat_map_index_allocation_test.vcproj b/proj/vc7ide/flat_map_index_allocation_test.vcproj new file mode 100644 index 0000000..129f309 --- /dev/null +++ b/proj/vc7ide/flat_map_index_allocation_test.vcproj @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/flat_tree_test.vcproj b/proj/vc7ide/flat_tree_test.vcproj index 1bc63f4..1a4e520 100644 --- a/proj/vc7ide/flat_tree_test.vcproj +++ b/proj/vc7ide/flat_tree_test.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="flat_tree_test" + ProjectGUID="{58CCE183-6092-48FE-A4F7-BA0D3A792637}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/interprocesslib.vcproj b/proj/vc7ide/interprocesslib.vcproj index a06747b..8d937cf 100644 --- a/proj/vc7ide/interprocesslib.vcproj +++ b/proj/vc7ide/interprocesslib.vcproj @@ -102,9 +102,6 @@ - - @@ -132,6 +129,9 @@ + + @@ -180,24 +180,24 @@ RelativePath="..\..\..\..\boost\interprocess\containers\detail\flat_tree.hpp"> - - + RelativePath="..\..\..\..\boost\interprocess\containers\detail\tree.hpp"> + + + + - - + RelativePath="..\..\..\..\boost\interprocess\allocators\cached_adaptive_pool.hpp"> @@ -205,15 +205,24 @@ + + + + + + + + @@ -327,6 +340,9 @@ + + @@ -366,6 +382,9 @@ + + @@ -375,6 +394,9 @@ + + - - @@ -403,9 +422,6 @@ - - @@ -421,9 +437,6 @@ - - @@ -439,6 +452,9 @@ + + @@ -475,6 +491,12 @@ + + + + @@ -495,17 +517,6 @@ RelativePath="..\..\test\Jamfile.v2"> - - - - - - + RelativePath="..\..\test\allocator_v1.hpp"> + RelativePath="..\..\test\check_equal_containers.hpp"> @@ -541,23 +552,32 @@ + + + + + + + RelativePath="..\..\test\print_container.hpp"> @@ -598,27 +618,33 @@ + RelativePath="..\..\example\doc_anonymous_condition_shared_data.hpp"> + RelativePath="..\..\example\doc_anonymous_mutex_shared_data.hpp"> + RelativePath="..\..\example\doc_anonymous_semaphore_shared_data.hpp"> + RelativePath="..\..\example\doc_named_condition_shared_data.hpp"> + RelativePath="..\..\example\doc_upgradable_mutex_shared_data.hpp"> + + + + diff --git a/proj/vc7ide/intrusive_ptr_test.vcproj b/proj/vc7ide/intrusive_ptr_test.vcproj index 828ec96..ea6d86e 100644 --- a/proj/vc7ide/intrusive_ptr_test.vcproj +++ b/proj/vc7ide/intrusive_ptr_test.vcproj @@ -1,137 +1,137 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="intrusive_ptr_test" + ProjectGUID="{5821C383-6092-12FE-A877-BA0D33467633}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/iset_index_allocation_test.vcproj b/proj/vc7ide/iset_index_allocation_test.vcproj new file mode 100644 index 0000000..62faafb --- /dev/null +++ b/proj/vc7ide/iset_index_allocation_test.vcproj @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/iunordered_set_index_allocation_test.vcproj b/proj/vc7ide/iunordered_set_index_allocation_test.vcproj new file mode 100644 index 0000000..3ffd8b5 --- /dev/null +++ b/proj/vc7ide/iunordered_set_index_allocation_test.vcproj @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/list_ex.vcproj b/proj/vc7ide/list_ex.vcproj index f8b7e77..abae097 100644 --- a/proj/vc7ide/list_ex.vcproj +++ b/proj/vc7ide/list_ex.vcproj @@ -1,136 +1,136 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="list_test" + ProjectGUID="{58CCE183-6092-48FE-A4F7-BA0D3A792632}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/managed_mapped_file_test.vcproj b/proj/vc7ide/managed_mapped_file_test.vcproj index dad2b09..d146ec2 100644 --- a/proj/vc7ide/managed_mapped_file_test.vcproj +++ b/proj/vc7ide/managed_mapped_file_test.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="managed_mapped_file_test" + ProjectGUID="{5CCE1883-0926-F7A4-8FE4-BA0606D92331}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/managed_windows_shared_memory.vcproj b/proj/vc7ide/managed_windows_shared_memory.vcproj new file mode 100644 index 0000000..eb4fc58 --- /dev/null +++ b/proj/vc7ide/managed_windows_shared_memory.vcproj @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/map_index_allocation_test.vcproj b/proj/vc7ide/map_index_allocation_test.vcproj new file mode 100644 index 0000000..c9a77cb --- /dev/null +++ b/proj/vc7ide/map_index_allocation_test.vcproj @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/mapped_file_test.vcproj b/proj/vc7ide/mapped_file_test.vcproj index 56df378..ff3d717 100644 --- a/proj/vc7ide/mapped_file_test.vcproj +++ b/proj/vc7ide/mapped_file_test.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="mapped_file_test" + ProjectGUID="{5C6D9CE1-2609-F7A4-8FE4-BA0883602330}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/memory_algorithm_test.vcproj b/proj/vc7ide/memory_algorithm_test.vcproj index dd769f8..c804bce 100644 --- a/proj/vc7ide/memory_algorithm_test.vcproj +++ b/proj/vc7ide/memory_algorithm_test.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="memory_algorithm_test" + ProjectGUID="{58E18CC3-6092-8F4E-A3E7-A792230D3629}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/message_queue.vcproj b/proj/vc7ide/message_queue.vcproj index fa5cdd2..43eaf17 100644 --- a/proj/vc7ide/message_queue.vcproj +++ b/proj/vc7ide/message_queue.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="message_queue_test" + ProjectGUID="{58CCE183-6092-48FE-A4F7-BA0D3A792628}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/mutex_test.vcproj b/proj/vc7ide/mutex_test.vcproj index 612e769..00d6ad6 100644 --- a/proj/vc7ide/mutex_test.vcproj +++ b/proj/vc7ide/mutex_test.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="mutex_test" + ProjectGUID="{83581CCE-487E-3292-A4E7-BA07926D3A27}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/named_condition_test.vcproj b/proj/vc7ide/named_condition_test.vcproj index 355399a..073f6f3 100644 --- a/proj/vc7ide/named_condition_test.vcproj +++ b/proj/vc7ide/named_condition_test.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="named_condition_test" + ProjectGUID="{58CC2563-6092-48FE-FAF7-BA046A792658}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/named_mutex_test.vcproj b/proj/vc7ide/named_mutex_test.vcproj index d861e18..ff850fb 100644 --- a/proj/vc7ide/named_mutex_test.vcproj +++ b/proj/vc7ide/named_mutex_test.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="named_mutex_test" + ProjectGUID="{58CCE183-6092-48FE-A4F7-BA0D3A792625}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/named_recursive_mutex_test.vcproj b/proj/vc7ide/named_recursive_mutex_test.vcproj index 91b85ec..3094a32 100644 --- a/proj/vc7ide/named_recursive_mutex_test.vcproj +++ b/proj/vc7ide/named_recursive_mutex_test.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="named_recursive_mutex_test" + ProjectGUID="{5C83CE18-4F48-A7FE-6092-B7920AD3A624}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/named_semaphore_test.vcproj b/proj/vc7ide/named_semaphore_test.vcproj index bb7ebf0..6a85d6c 100644 --- a/proj/vc7ide/named_semaphore_test.vcproj +++ b/proj/vc7ide/named_semaphore_test.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="named_semaphore_test" + ProjectGUID="{58CCE283-1609-48FE-A4F7-BA0D3A793523}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/named_upgradable_mutex.vcproj b/proj/vc7ide/named_upgradable_mutex.vcproj index cac8d6d..ad94e13 100644 --- a/proj/vc7ide/named_upgradable_mutex.vcproj +++ b/proj/vc7ide/named_upgradable_mutex.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="named_upgradable_mutex_test" + ProjectGUID="{48C1FBE8-F7A4-0961-48FE-7D93A63B0A04}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/node_allocator_test.vcproj b/proj/vc7ide/node_allocator_test.vcproj index 67fd109..f90eb9e 100644 --- a/proj/vc7ide/node_allocator_test.vcproj +++ b/proj/vc7ide/node_allocator_test.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="node_allocator_test" + ProjectGUID="{58CCE183-6092-48FE-A4F7-BA0D3A792622}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/node_pool_test.vcproj b/proj/vc7ide/node_pool_test.vcproj new file mode 100644 index 0000000..62e2958 --- /dev/null +++ b/proj/vc7ide/node_pool_test.vcproj @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/null_index_test.vcproj b/proj/vc7ide/null_index_test.vcproj index 9e127a5..5c127a8 100644 --- a/proj/vc7ide/null_index_test.vcproj +++ b/proj/vc7ide/null_index_test.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="null_index_test" + ProjectGUID="{0000058C-0000-0000-0000-000000000021}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/private_adaptive_pool_test.vcproj b/proj/vc7ide/private_adaptive_pool_test.vcproj new file mode 100644 index 0000000..a0ca1e7 --- /dev/null +++ b/proj/vc7ide/private_adaptive_pool_test.vcproj @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/private_node_allocator_test.vcproj b/proj/vc7ide/private_node_allocator_test.vcproj index f576c5a..2bbb880 100644 --- a/proj/vc7ide/private_node_allocator_test.vcproj +++ b/proj/vc7ide/private_node_allocator_test.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="private_node_allocator_test" + ProjectGUID="{58CCE183-6092-48FE-A4F7-BA0D3A792620}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/recursive_mutex_test.vcproj b/proj/vc7ide/recursive_mutex_test.vcproj index f98c0b5..93c3cb7 100644 --- a/proj/vc7ide/recursive_mutex_test.vcproj +++ b/proj/vc7ide/recursive_mutex_test.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="recursive_mutex_test" + ProjectGUID="{83581CCE-487E-3292-A4E7-BA07926D3A14}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/semaphore_test.vcproj b/proj/vc7ide/semaphore_test.vcproj index 176e13f..3290a62 100644 --- a/proj/vc7ide/semaphore_test.vcproj +++ b/proj/vc7ide/semaphore_test.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="semaphore_test" + ProjectGUID="{5CE28C83-48FE-1676-4FA7-B50D3A76A013}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/shared_memory_mappable_test.vcproj b/proj/vc7ide/shared_memory_mappable_test.vcproj index b57825d..c807807 100644 --- a/proj/vc7ide/shared_memory_mappable_test.vcproj +++ b/proj/vc7ide/shared_memory_mappable_test.vcproj @@ -1,135 +1,135 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="shared_memory_mapping_test" + ProjectGUID="{5CE18C83-6025-36FE-A4F7-BA09176D3A11}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/shared_memory_test.vcproj b/proj/vc7ide/shared_memory_test.vcproj index 04b52b6..95a55ac 100644 --- a/proj/vc7ide/shared_memory_test.vcproj +++ b/proj/vc7ide/shared_memory_test.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="shared_memory_test" + ProjectGUID="{5E2838CC-0916-8F4E-A4F7-93506BA0D310}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/shared_ptr_test.vcproj b/proj/vc7ide/shared_ptr_test.vcproj index 008b213..a620af9 100644 --- a/proj/vc7ide/shared_ptr_test.vcproj +++ b/proj/vc7ide/shared_ptr_test.vcproj @@ -1,137 +1,137 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="shared_ptr_test" + ProjectGUID="{5371C383-6092-1238-A877-BAEB37867609}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/slist_test.vcproj b/proj/vc7ide/slist_test.vcproj index 72b01e9..5f5e62a 100644 --- a/proj/vc7ide/slist_test.vcproj +++ b/proj/vc7ide/slist_test.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="slist_test" + ProjectGUID="{58CCE183-6092-48FE-A4F7-BA0D3A792608}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/string_test.vcproj b/proj/vc7ide/string_test.vcproj index 7b305c9..b751dca 100644 --- a/proj/vc7ide/string_test.vcproj +++ b/proj/vc7ide/string_test.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="string_test" + ProjectGUID="{58CCE183-6092-48FE-A4F7-BA0D4A792607}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/tree_test.vcproj b/proj/vc7ide/tree_test.vcproj index 4dc558e..c3d8463 100644 --- a/proj/vc7ide/tree_test.vcproj +++ b/proj/vc7ide/tree_test.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="tree_test" + ProjectGUID="{58CCE183-6092-48FE-A4F7-BA0D3A792606}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/unique_ptr_test.vcproj b/proj/vc7ide/unique_ptr_test.vcproj index 3fb449c..7b28829 100644 --- a/proj/vc7ide/unique_ptr_test.vcproj +++ b/proj/vc7ide/unique_ptr_test.vcproj @@ -1,137 +1,137 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="unique_ptr_test" + ProjectGUID="{571C3383-6092-A877-1238-B3786BAE7605}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/upgradable_mutex.vcproj b/proj/vc7ide/upgradable_mutex.vcproj index b2bf16e..c3067a8 100644 --- a/proj/vc7ide/upgradable_mutex.vcproj +++ b/proj/vc7ide/upgradable_mutex.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="upgradable_mutex_test" + ProjectGUID="{4E88C1C2-0961-F7A4-F48E-A6A7D3B06004}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/user_buffer_test.vcproj b/proj/vc7ide/user_buffer_test.vcproj index 6bbc6fd..7e7424f 100644 --- a/proj/vc7ide/user_buffer_test.vcproj +++ b/proj/vc7ide/user_buffer_test.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="user_buffer_test" + ProjectGUID="{58CCE183-6092-48FE-A4F7-BA0D3A792603}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/vector_test.vcproj b/proj/vc7ide/vector_test.vcproj index 35037bc..3a7cecc 100644 --- a/proj/vc7ide/vector_test.vcproj +++ b/proj/vc7ide/vector_test.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="vector_test" + ProjectGUID="{5CE11C83-096A-84FE-4FA2-D3A6BA792002}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/vectorstream_test.vcproj b/proj/vc7ide/vectorstream_test.vcproj index 8d9a536..c1f4e6d 100644 --- a/proj/vc7ide/vectorstream_test.vcproj +++ b/proj/vc7ide/vectorstream_test.vcproj @@ -1,134 +1,134 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="7.10" + Name="vectorstream_test" + ProjectGUID="{58CCE183-6032-12FE-A4F7-BA893A767601}" + Keyword="Win32Proj"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/windows_shared_memory_mapping_test.vcproj b/proj/vc7ide/windows_shared_memory_mapping_test.vcproj new file mode 100644 index 0000000..e7389a2 --- /dev/null +++ b/proj/vc7ide/windows_shared_memory_mapping_test.vcproj @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/windows_shared_memory_test.vcproj b/proj/vc7ide/windows_shared_memory_test.vcproj new file mode 100644 index 0000000..e30af34 --- /dev/null +++ b/proj/vc7ide/windows_shared_memory_test.vcproj @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/Attic/file_lock_test.cpp b/test/Attic/file_lock_test.cpp deleted file mode 100644 index abf8724..0000000 --- a/test/Attic/file_lock_test.cpp +++ /dev/null @@ -1,51 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gazta�ga 2004-2006. Distributed under the Boost -// Software License, Version 1.0. (See accompanying file -// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/interprocess for documentation. -// -////////////////////////////////////////////////////////////////////////////// -#include -#include -#include -#include -#include -#include -#include "mutex_test_template.hpp" -#include "sharable_mutex_test_template.hpp" -#include -#include - - -//This wrapper is necessary to have a default constructor -//in generic mutex_test_template functions -class file_lock_lock_test_wrapper - : public boost::interprocess::file_lock -{ - public: - file_lock_lock_test_wrapper() - : boost::interprocess::file_lock("file_lock") - {} -}; - -int main () -{ - using namespace boost::interprocess; - //Destroy and create file - { - std::remove("file_lock"); - std::ofstream file("file_lock"); - if(!file){ - return 1; - } - } - - test::test_all_lock(); - test::test_all_mutex(); - test::test_all_sharable_mutex(); - return 0; -} - -#include diff --git a/test/Attic/printcontainer.hpp b/test/Attic/printcontainer.hpp deleted file mode 100644 index 6489a92..0000000 --- a/test/Attic/printcontainer.hpp +++ /dev/null @@ -1,45 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztañaga 2004-2006. Distributed under the Boost -// Software License, Version 1.0. (See accompanying file -// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// -// See http://www.boost.org/libs/interprocess for documentation. -// -////////////////////////////////////////////////////////////////////////////// - -#ifndef BOOST_PRINTCONTAINER_HPP -#define BOOST_PRINTCONTAINER_HPP - -#include -#include -#include -#include - -namespace boost{ -namespace interprocess{ -namespace test{ - -struct PrintValues : public std::unary_function -{ - void operator() (int value) const - { - std::cout << value << " "; - } -}; - -template -void PrintContents(const Container &cont, const char *contName) -{ - std::cout<< "Printing contents of " << contName << std::endl; - std::for_each(cont.begin(), cont.end(), PrintValues()); - std::cout<< std::endl << std::endl; -} - -} //namespace test{ -} //namespace interprocess{ -} //namespace boost{ - -#include - -#endif //#ifndef BOOST_PRINTCONTAINER_HPP diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 494e8a3..685e1a7 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -25,7 +25,7 @@ rule test_all : # additional args : # test-files : # requirements - ] ; + ] ; } return $(all_rules) ; diff --git a/test/adaptive_node_pool_test.cpp b/test/adaptive_node_pool_test.cpp new file mode 100644 index 0000000..7a1dba2 --- /dev/null +++ b/test/adaptive_node_pool_test.cpp @@ -0,0 +1,22 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2007. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include + +using namespace boost::interprocess; + +int main () +{ + return 0; +} + +#include diff --git a/test/adaptive_pool_test.cpp b/test/adaptive_pool_test.cpp new file mode 100644 index 0000000..7ed0075 --- /dev/null +++ b/test/adaptive_pool_test.cpp @@ -0,0 +1,38 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2004-2007. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include "print_container.hpp" +#include "dummy_test_allocator.hpp" +#include "movable_int.hpp" +#include "list_test.hpp" + +using namespace boost::interprocess; + +//We will work with wide characters for shared memory objects +//Alias an adaptive pool that allocates ints +typedef adaptive_pool + shmem_node_allocator_t; + +//Alias list types +typedef list MyShmList; + +int main () +{ + if(test::list_test()) + return 1; + + return 0; +} + +#include diff --git a/test/allocator_v1.hpp b/test/allocator_v1.hpp index bd3cfd9..f2a91bb 100644 --- a/test/allocator_v1.hpp +++ b/test/allocator_v1.hpp @@ -1,6 +1,6 @@ /////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztañaga 2005-2006. Distributed under the Boost +// (C) Copyright Ion Gaztañaga 2005-2007. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -65,8 +65,8 @@ class allocator_v1 ::type alloc_ptr_t; /*!Not assignable from related allocator_v1*/ - template - allocator_v1& operator=(const allocator_v1&); + template + allocator_v1& operator=(const allocator_v1&); /*!Not assignable from other allocator_v1*/ allocator_v1& operator=(const allocator_v1&); diff --git a/test/allocexcept_test.cpp b/test/allocexcept_test.cpp index b7b4881..b055c3b 100644 --- a/test/allocexcept_test.cpp +++ b/test/allocexcept_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztañaga 2004-2006. Distributed under the Boost +// (C) Copyright Ion Gaztañaga 2004-2007. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -9,8 +9,6 @@ ////////////////////////////////////////////////////////////////////////////// #include -#include - #include #include #include @@ -38,6 +36,7 @@ int main () const int memsize = 16384; const char *const shMemName = "MySharedMemory"; + try{ shared_memory_object::remove(shMemName); //Named allocate capable shared mem allocator @@ -78,8 +77,13 @@ int main () if(InstanceCounter::counter != 0) return 1; } + } + catch(...){ + shared_memory_object::remove(shMemName); + throw; + } + shared_memory_object::remove(shMemName); return 0; } #include - diff --git a/test/barrier_test.cpp b/test/barrier_test.cpp index dba131f..66d795a 100644 --- a/test/barrier_test.cpp +++ b/test/barrier_test.cpp @@ -10,16 +10,15 @@ // It is provided "as is" without express or implied warranty. ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztañaga 2005-2006. Distributed under the Boost +// (C) Copyright Ion Gaztañaga 2005-2007. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // // See http://www.boost.org/libs/interprocess for documentation. // ////////////////////////////////////////////////////////////////////////////// -#include -#include +#include #include #include #include @@ -52,16 +51,14 @@ void barrier_thread() int main () { - try{ - boost::thread_group g; global_parameter = 0; for (int i = 0; i < N_THREADS; ++i) g.create_thread(&barrier_thread); - g.join_all(); + g.join_all(); } catch(std::exception &e){ std::cout << "Exception cached: " << e.what() << std::endl; @@ -71,7 +68,6 @@ int main () std::cout << "unkwnown exception catched" << std::endl; return 1; } - return 0; } diff --git a/test/boost_interprocess_check.hpp b/test/boost_interprocess_check.hpp index 823ab46..2a906e7 100644 --- a/test/boost_interprocess_check.hpp +++ b/test/boost_interprocess_check.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztañaga 2004-2006. Distributed under the Boost +// (C) Copyright Ion Gaztañaga 2004-2007. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -11,6 +11,7 @@ #ifndef BOOST_INTERPROCESS_TEST_HEADER #define BOOST_INTERPROCESS_TEST_HEADER +#include #include #include @@ -21,4 +22,6 @@ namespace boost { namespace interprocess { namespace test { }}} //namespace boost { namespace interprocess { namespace test { +#include + #endif //BOOST_INTERPROCESS_TEST_HEADER diff --git a/test/bufferstream_test.cpp b/test/bufferstream_test.cpp index e2105ed..8d35597 100644 --- a/test/bufferstream_test.cpp +++ b/test/bufferstream_test.cpp @@ -1,6 +1,14 @@ -#include -#include +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2006. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#include #include #include #include diff --git a/test/cached_adaptive_pool_test.cpp b/test/cached_adaptive_pool_test.cpp new file mode 100644 index 0000000..024365e --- /dev/null +++ b/test/cached_adaptive_pool_test.cpp @@ -0,0 +1,39 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2004-2007. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include "print_container.hpp" +#include "dummy_test_allocator.hpp" +#include "movable_int.hpp" +#include "list_test.hpp" + +using namespace boost::interprocess; + +//We will work with wide characters for shared memory objects +//Alias an cached adaptive pool that allocates ints +typedef cached_adaptive_pool + + cached_node_allocator_t; + +//Alias list types +typedef list MyShmList; + +int main () +{ + if(test::list_test()) + return 1; + + return 0; +} + +#include diff --git a/test/cached_node_allocator_test.cpp b/test/cached_node_allocator_test.cpp index b3909d0..818ac4f 100644 --- a/test/cached_node_allocator_test.cpp +++ b/test/cached_node_allocator_test.cpp @@ -1,15 +1,14 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztañaga 2004-2006. Distributed under the Boost +// (C) Copyright Ion Gaztañaga 2004-2007. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // // See http://www.boost.org/libs/interprocess for documentation. // ////////////////////////////////////////////////////////////////////////////// -#include -#include +#include #include #include #include @@ -21,7 +20,7 @@ using namespace boost::interprocess; //We will work with wide characters for shared memory objects -//Alias node allocator type +//Alias a integer node allocator type typedef cached_node_allocator cached_node_allocator_t; diff --git a/test/check_equal_containers.hpp b/test/check_equal_containers.hpp index 2108a78..f930538 100644 --- a/test/check_equal_containers.hpp +++ b/test/check_equal_containers.hpp @@ -11,10 +11,10 @@ #ifndef BOOST_INTERPROCESS_TEST_CHECK_EQUAL_CONTAINERS_HPP #define BOOST_INTERPROCESS_TEST_CHECK_EQUAL_CONTAINERS_HPP +#include #include #include #include -#include namespace boost{ namespace interprocess{ diff --git a/test/condition_test.cpp b/test/condition_test.cpp index fc48dfd..c71292c 100644 --- a/test/condition_test.cpp +++ b/test/condition_test.cpp @@ -1,6 +1,14 @@ -#include -#include +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2006. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#include #include #include #include diff --git a/test/condition_test_template.hpp b/test/condition_test_template.hpp index b32f82c..f9a6a4e 100644 --- a/test/condition_test_template.hpp +++ b/test/condition_test_template.hpp @@ -10,13 +10,16 @@ // It is provided "as is" without express or implied warranty. ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztañaga 2005-2006. Distributed under the Boost +// (C) Copyright Ion Gaztañaga 2005-2007. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // // See http://www.boost.org/libs/interprocess for documentation. // ////////////////////////////////////////////////////////////////////////////// +#ifndef BOOST_INTERPROCESS_CONDITION_TEST_TEMPLATE_HPP +#define BOOST_INTERPROCESS_CONDITION_TEST_TEMPLATE_HPP + #include #include @@ -274,20 +277,22 @@ const int NumThreads = thread_factor*queue_size; //Function that removes items from queue template -static void condition_func(void) +struct condition_func { - boost::interprocess::scoped_lock - lock(mutex()); - while(count == 0){ - ++waiting_readers; - cond_empty().wait(lock); - --waiting_readers; + static void execute() + { + boost::interprocess::scoped_lock + lock(mutex()); + while(count == 0){ + ++waiting_readers; + cond_empty().wait(lock); + --waiting_readers; + } + --count; + if(waiting_writer) + cond_full().notify_one(); } - --count; - if(waiting_writer) - cond_full().notify_one(); - -} +}; //Queue functions template @@ -308,7 +313,9 @@ void do_test_condition_queue_notify_one(void) boost::thread_group thgroup; int i; for(i = 0; i< NumThreads; ++i){ - thgroup.create_thread(condition_func); +// thgroup.create_thread(&condition_func); +// thgroup.create_thread(&condition_func_bis); + thgroup.create_thread(&condition_func::execute); } //Add 20 elements one by one in the queue simulation @@ -352,7 +359,9 @@ void do_test_condition_queue_notify_all(void) boost::thread_group thgroup; int i; for(i = 0; i< NumThreads; ++i){ - thgroup.create_thread(condition_func); +// thgroup.create_thread(&condition_func); +// thgroup.create_thread(&condition_func_bis); + thgroup.create_thread(&condition_func::execute); } //Fill queue to the max size and notify all several times @@ -397,3 +406,5 @@ bool do_test_condition() } //namespace boost{ #include + +#endif //#ifndef BOOST_INTERPROCESS_CONDITION_TEST_TEMPLATE_HPP diff --git a/test/data_test.cpp b/test/data_test.cpp index 4cb6428..010d064 100644 --- a/test/data_test.cpp +++ b/test/data_test.cpp @@ -1,15 +1,14 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztañaga 2004-2006. Distributed under the Boost +// (C) Copyright Ion Gaztañaga 2004-2007. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // // See http://www.boost.org/libs/interprocess for documentation. // ////////////////////////////////////////////////////////////////////////////// -#include -#include +#include #include #include #include @@ -26,6 +25,7 @@ int main () const int memsize = 65536; const char *const shMemName = "MySharedMemory"; + try{ shared_memory_object::remove(shMemName); //Create shared memory @@ -45,7 +45,6 @@ int main () typedef boost::interprocess::vector MyVect; typedef boost::interprocess::list MyList; - //---- ALLOC, NAMED_ALLOC, NAMED_NEW TEST ----// { int i; @@ -92,7 +91,15 @@ int main () if(!res) return 1; */ + std::remove("shmem_file"); } + } + catch(...){ + std::remove("shmem_file"); + shared_memory_object::remove(shMemName); + throw; + } + shared_memory_object::remove(shMemName); return 0; } diff --git a/test/deque_test.cpp b/test/deque_test.cpp index 7443d09..30f3a8f 100644 --- a/test/deque_test.cpp +++ b/test/deque_test.cpp @@ -1,15 +1,14 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztañaga 2004-2006. Distributed under the Boost +// (C) Copyright Ion Gaztañaga 2004-2007. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // // See http://www.boost.org/libs/interprocess for documentation. // ////////////////////////////////////////////////////////////////////////////// -#include -#include +#include #include #include #include @@ -80,8 +79,10 @@ bool do_test() //Customize managed_shared_memory class typedef basic_managed_shared_memory , - flat_map_index + //simple_seq_fit, + rbtree_best_fit, + //flat_map_index + iset_index > my_managed_shared_memory; //Alias AllocatorType type @@ -95,112 +96,117 @@ bool do_test() const char *const shMemName = "MySharedMemory"; const int max = 100; - shared_memory_object::remove(shMemName); - - //Create shared memory - my_managed_shared_memory segment(create_only, shMemName, Memsize); - - segment.reserve_named_objects(100); - - //Shared memory allocator must be always be initialized - //since it has no default constructor - MyShmDeque *shmdeque = segment.template construct("MyShmDeque") - (segment.get_segment_manager()); - - MyStdDeque *stddeque = new MyStdDeque; - try{ - //Compare several shared memory deque operations with std::deque - int i; - for(i = 0; i < max; ++i){ - IntType move_me(i); - shmdeque->insert(shmdeque->end(), move(move_me)); - stddeque->insert(stddeque->end(), i); + shared_memory_object::remove(shMemName); + + //Create shared memory + my_managed_shared_memory segment(create_only, shMemName, Memsize); + + segment.reserve_named_objects(100); + + //Shared memory allocator must be always be initialized + //since it has no default constructor + MyShmDeque *shmdeque = segment.template construct("MyShmDeque") + (segment.get_segment_manager()); + + MyStdDeque *stddeque = new MyStdDeque; + + try{ + //Compare several shared memory deque operations with std::deque + int i; + for(i = 0; i < max; ++i){ + IntType move_me(i); + shmdeque->insert(shmdeque->end(), move(move_me)); + stddeque->insert(stddeque->end(), i); + } + if(!test::CheckEqualContainers(shmdeque, stddeque)) return 1; + + typename MyShmDeque::iterator it; + typename MyShmDeque::const_iterator cit = it; + + shmdeque->erase(shmdeque->begin()++); + stddeque->erase(stddeque->begin()++); + if(!test::CheckEqualContainers(shmdeque, stddeque)) return 1; + + shmdeque->erase(shmdeque->begin()); + stddeque->erase(stddeque->begin()); + if(!test::CheckEqualContainers(shmdeque, stddeque)) return 1; + + { + //Initialize values + IntType aux_vect[50]; + for(int i = 0; i < 50; ++i){ + IntType move_me (-1); + aux_vect[i] = move(move_me); + } + int aux_vect2[50]; + for(int i = 0; i < 50; ++i){ + aux_vect2[i] = -1; + } + + shmdeque->insert(shmdeque->end() + ,detail::make_move_iterator(&aux_vect[0]) + ,detail::make_move_iterator(aux_vect + 50)); + stddeque->insert(stddeque->end(), aux_vect2, aux_vect2 + 50); + if(!test::CheckEqualContainers(shmdeque, stddeque)) return false; + + for(int i = 0, j = static_cast(shmdeque->size()); i < j; ++i){ + shmdeque->erase(shmdeque->begin()); + stddeque->erase(stddeque->begin()); + } + if(!test::CheckEqualContainers(shmdeque, stddeque)) return false; + } + { + IntType aux_vect[50]; + for(int i = 0; i < 50; ++i){ + IntType move_me(-1); + aux_vect[i] = move(move_me); + } + int aux_vect2[50]; + for(int i = 0; i < 50; ++i){ + aux_vect2[i] = -1; + } + shmdeque->insert(shmdeque->begin() + ,detail::make_move_iterator(&aux_vect[0]) + ,detail::make_move_iterator(aux_vect + 50)); + stddeque->insert(stddeque->begin(), aux_vect2, aux_vect2 + 50); + if(!test::CheckEqualContainers(shmdeque, stddeque)) return false; + } + + if(!copyable_only(shmdeque, stddeque + ,boost::integral_constant + ::value>())){ + return false; + } + + shmdeque->erase(shmdeque->begin()); + stddeque->erase(stddeque->begin()); + + if(!test::CheckEqualContainers(shmdeque, stddeque)) return 1; + + for(i = 0; i < max; ++i){ + IntType move_me(i); + shmdeque->insert(shmdeque->begin(), move(move_me)); + stddeque->insert(stddeque->begin(), i); + } + if(!test::CheckEqualContainers(shmdeque, stddeque)) return 1; + + segment.template destroy("MyShmDeque"); + delete stddeque; } - if(!test::CheckEqualContainers(shmdeque, stddeque)) return 1; - - typename MyShmDeque::iterator it; - typename MyShmDeque::const_iterator cit = it; - - shmdeque->erase(shmdeque->begin()++); - stddeque->erase(stddeque->begin()++); - if(!test::CheckEqualContainers(shmdeque, stddeque)) return 1; - - shmdeque->erase(shmdeque->begin()); - stddeque->erase(stddeque->begin()); - if(!test::CheckEqualContainers(shmdeque, stddeque)) return 1; - - { - //Initialize values - IntType aux_vect[50]; - for(int i = 0; i < 50; ++i){ - IntType move_me (-1); - aux_vect[i] = move(move_me); - } - int aux_vect2[50]; - for(int i = 0; i < 50; ++i){ - aux_vect2[i] = -1; - } - - shmdeque->insert(shmdeque->end() - ,detail::make_move_iterator(&aux_vect[0]) - ,detail::make_move_iterator(aux_vect + 50)); - stddeque->insert(stddeque->end(), aux_vect2, aux_vect2 + 50); - if(!test::CheckEqualContainers(shmdeque, stddeque)) return false; - - for(int i = 0, j = static_cast(shmdeque->size()); i < j; ++i){ - shmdeque->erase(shmdeque->begin()); - stddeque->erase(stddeque->begin()); - } - if(!test::CheckEqualContainers(shmdeque, stddeque)) return false; - } - { - IntType aux_vect[50]; - for(int i = 0; i < 50; ++i){ - IntType move_me(-1); - aux_vect[i] = move(move_me); - } - int aux_vect2[50]; - for(int i = 0; i < 50; ++i){ - aux_vect2[i] = -1; - } - shmdeque->insert(shmdeque->begin() - ,detail::make_move_iterator(&aux_vect[0]) - ,detail::make_move_iterator(aux_vect + 50)); - stddeque->insert(stddeque->begin(), aux_vect2, aux_vect2 + 50); - if(!test::CheckEqualContainers(shmdeque, stddeque)) return false; - } - - if(!copyable_only(shmdeque, stddeque - ,boost::integral_constant - ::value>())){ + catch(std::exception &ex){ + std::cout << ex.what() << std::endl; return false; } - - shmdeque->erase(shmdeque->begin()); - stddeque->erase(stddeque->begin()); - - if(!test::CheckEqualContainers(shmdeque, stddeque)) return 1; - - for(i = 0; i < max; ++i){ - IntType move_me(i); - shmdeque->insert(shmdeque->begin(), move(move_me)); - stddeque->insert(stddeque->begin(), i); - } - if(!test::CheckEqualContainers(shmdeque, stddeque)) return 1; - - segment.template destroy("MyShmDeque"); - delete stddeque; + + std::cout << std::endl << "Test OK!" << std::endl; } - catch(std::exception &ex){ - std::cout << ex.what() << std::endl; - return false; + catch(...){ + shared_memory_object::remove(shMemName); + throw; } - - std::cout << std::endl << "Test OK!" << std::endl; + shared_memory_object::remove(shMemName); return true; - - return 0; } int main () @@ -217,5 +223,4 @@ int main () return 0; } - #include diff --git a/test/dummy_test_allocator.hpp b/test/dummy_test_allocator.hpp index 48d8da9..3942870 100644 --- a/test/dummy_test_allocator.hpp +++ b/test/dummy_test_allocator.hpp @@ -1,6 +1,6 @@ /////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztañaga 2005-2006. Distributed under the Boost +// (C) Copyright Ion Gaztañaga 2005-2007. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // diff --git a/test/expand_bwd_test_allocator.hpp b/test/expand_bwd_test_allocator.hpp index 637982c..ad6998d 100644 --- a/test/expand_bwd_test_allocator.hpp +++ b/test/expand_bwd_test_allocator.hpp @@ -1,6 +1,6 @@ /////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztañaga 2005-2006. Distributed under the Boost +// (C) Copyright Ion Gaztañaga 2005-2007. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // diff --git a/test/expand_bwd_test_template.hpp b/test/expand_bwd_test_template.hpp index 8cb036b..ed8fb82 100644 --- a/test/expand_bwd_test_template.hpp +++ b/test/expand_bwd_test_template.hpp @@ -11,6 +11,7 @@ #ifndef BOOST_INTERPROCESS_TEST_ALLOCATION_TEST_TEMPLATE_HEADER #define BOOST_INTERPROCESS_TEST_ALLOCATION_TEST_TEMPLATE_HEADER +#include #include #include "expand_bwd_test_allocator.hpp" #include @@ -20,7 +21,7 @@ namespace boost { namespace interprocess { namespace test { template struct value_holder { - value_holder(T val): m_value(val){} + value_holder(T val) : m_value(val){} value_holder(): m_value(0){} ~value_holder(){ m_value = 0; } bool operator == (const value_holder &other) const @@ -31,7 +32,47 @@ struct value_holder T m_value; }; +template +struct triple_value_holder +{ + triple_value_holder(T val) + : m_value1(val) + , m_value2(val) + , m_value3(val) + {} + + triple_value_holder() + : m_value1(0) + , m_value2(0) + , m_value3(0) + {} + + ~triple_value_holder() + { m_value1 = m_value2 = m_value3 = 0; } + + bool operator == (const triple_value_holder &other) const + { + return m_value1 == other.m_value1 + && m_value2 == other.m_value2 + && m_value3 == other.m_value3; + } + + bool operator != (const triple_value_holder &other) const + { + return m_value1 != other.m_value1 + || m_value2 != other.m_value2 + || m_value3 != other.m_value3; + } + + T m_value1; + T m_value2; + T m_value3; +}; + typedef value_holder int_holder; +typedef triple_value_holder triple_int_holder; + + //Function to check if both sets are equal template @@ -209,5 +250,7 @@ bool test_all_expand_bwd() }}} //namespace boost { namespace interprocess { namespace test { +#include + #endif //BOOST_INTERPROCESS_TEST_ALLOCATION_TEST_TEMPLATE_HEADER diff --git a/test/file_mapping_test.cpp b/test/file_mapping_test.cpp index 03ffb05..67e3e80 100644 --- a/test/file_mapping_test.cpp +++ b/test/file_mapping_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztañaga 2004-2005. Distributed under the Boost +// (C) Copyright Ion Gaztañaga 2004-2007. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -9,12 +9,11 @@ ////////////////////////////////////////////////////////////////////////////// #include -#include - #include #include #include #include +#include using namespace boost::interprocess; @@ -120,156 +119,12 @@ int main () } } catch(std::exception &exc){ + std::remove("my_file"); std::cout << "Unhandled exception: " << exc.what() << std::endl; + throw; } - + std::remove("my_file"); return 0; } #include - -/* -#include -#include -#include -#include -#include -#include - -char allchars [] = "abcdefghijklmnopqrstuvwxyz"; - -struct DictionaryValue -{ - std::string str; - std::size_t count; - bool operator == (const DictionaryValue &other) const - { return str == other.str; } -}; - -struct DictionaryHasher -: std::unary_function -{ - std::size_t operator()(const DictionaryValue &val) const - { - const char *str = val.str.data(); - std::size_t len = val.str.size(); - std::size_t hash = 0; - - for (;;) - { - switch (len) - { - case 0: - return hash; - - case 1: - hash *= 37; - hash += *(unsigned char *)str; - return hash; - - case 2: - hash *= 37; - hash += *(unsigned short *)str; - return hash; - - case 3: - hash *= 37; - hash += (*(unsigned short *)str << 8) + - ((unsigned char *)str)[2]; - return hash; - - default: - hash *= 37; - hash += *(long *)str; - str += 4; - len -= 4; - break; - } - } - } - -}; - -int main( int argc, char* argv[] ) -{ - std::size_t w_total = 0; - std::size_t l_total = 0; - std::size_t c_total = 0; - - typedef boost::unordered_set - ,boost::fast_pool_allocator - > Dictionary; - - Dictionary dictionary; - typedef Dictionary::iterator iterator; - DictionaryValue dict_value; - - std::ifstream input_file(argv[1], std::ios_base::in | std::ios_base::binary ); - input_file.seekg(0, std::ios::end); - - std::vector data(static_cast(input_file.tellg())); - input_file.seekg(0, std::ios::beg); - input_file.read(&data[0], static_cast(data.size())); - input_file.close(); - - std::size_t w_count = 0; - std::size_t w_diff = 'z'-'a'; - - for ( int a = 0; a < 100; ++a ) - { - std::string &word = dict_value.str; - word.reserve(64); - dict_value.count = 0; - - std::size_t w_cnt = 0; - std::size_t l_cnt = 0; - std::size_t c_cnt = 0; - bool inword = false; - std::size_t wstart = 0; - for ( std::size_t j = 0, size = data.size(); j < size; j++ ) - { - char c = data[j]; - if (c == '\n') - ++l_cnt; - if (c >= '0' && c <= '9') - { - } - else if (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z') - { - if (!inword) - { - wstart = j; - inword = true; - ++w_cnt; - } - } - else if (inword) - { - word.assign(&data[wstart], &data[j]); - ++w_count; - std::size_t num = w_count%25; - word.insert(1, 1, allchars[num]); -// dictionary.insert(dict_value).first->count++; - inword = false; - } - ++c_cnt; - } - - if (inword) - { - word.assign(&data[wstart], &data[data.size()]); - ++w_count; - std::size_t num = w_count%25; - word.insert(1, 1, allchars[num]); -// dictionary.insert(dict_value).first->count++; - } - l_total += l_cnt; - w_total += w_cnt; - c_total += c_cnt; - } - - return 0; -} -*/ diff --git a/test/flat_map_index_allocation_test.cpp b/test/flat_map_index_allocation_test.cpp new file mode 100644 index 0000000..bf3060a --- /dev/null +++ b/test/flat_map_index_allocation_test.cpp @@ -0,0 +1,25 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2006. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include "named_allocation_test_template.hpp" + +int main () +{ + using namespace boost::interprocess; + if(!test::test_named_allocation()){ + return 1; + } + + return 0; +} + +#include diff --git a/test/flat_tree_test.cpp b/test/flat_tree_test.cpp index 7551d8b..baa3adf 100644 --- a/test/flat_tree_test.cpp +++ b/test/flat_tree_test.cpp @@ -1,15 +1,14 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztañaga 2004-2006. Distributed under the Boost +// (C) Copyright Ion Gaztañaga 2004-2007. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // // See http://www.boost.org/libs/interprocess for documentation. // ////////////////////////////////////////////////////////////////////////////// -#include -#include +#include #include #include #include @@ -60,23 +59,24 @@ template class boost::interprocess::flat_multimap //Customize managed_shared_memory class typedef basic_managed_shared_memory , + //simple_seq_fit, + rbtree_best_fit, flat_map_index > my_managed_shared_memory; //Alias allocator type -typedef allocator +typedef allocator shmem_allocator_t; -typedef allocator +typedef allocator shmem_movable_allocator_t; -typedef allocator, managed_shared_memory::segment_manager> +typedef allocator, my_managed_shared_memory::segment_manager> shmem_pair_allocator_t; -typedef allocator, managed_shared_memory::segment_manager> +typedef allocator, my_managed_shared_memory::segment_manager> shmem_movable_pair_allocator_t; -typedef allocator +typedef allocator shmem_move_copy_allocator_t; -typedef allocator, managed_shared_memory::segment_manager> +typedef allocator, my_managed_shared_memory::segment_manager> shmem_move_copy_pair_allocator_t; //Alias set types diff --git a/test/intrusive_ptr_test.cpp b/test/intrusive_ptr_test.cpp index ea61105..2120941 100644 --- a/test/intrusive_ptr_test.cpp +++ b/test/intrusive_ptr_test.cpp @@ -8,9 +8,8 @@ // See http://www.boost.org/libs/interprocess for documentation. // ////////////////////////////////////////////////////////////////////////////// -#include -#include +#include #include #include #include diff --git a/test/iset_index_allocation_test.cpp b/test/iset_index_allocation_test.cpp new file mode 100644 index 0000000..efb8069 --- /dev/null +++ b/test/iset_index_allocation_test.cpp @@ -0,0 +1,25 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2006. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include "named_allocation_test_template.hpp" + +int main () +{ + using namespace boost::interprocess; + if(!test::test_named_allocation()){ + return 1; + } + + return 0; +} + +#include diff --git a/test/iunordered_set_index_allocation_test.cpp b/test/iunordered_set_index_allocation_test.cpp new file mode 100644 index 0000000..d7dab1a --- /dev/null +++ b/test/iunordered_set_index_allocation_test.cpp @@ -0,0 +1,25 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2006. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include "named_allocation_test_template.hpp" + +int main () +{ + using namespace boost::interprocess; + if(!test::test_named_allocation()){ + return 1; + } + + return 0; +} + +#include diff --git a/test/list_test.cpp b/test/list_test.cpp index b9e6b72..1e5fdb4 100644 --- a/test/list_test.cpp +++ b/test/list_test.cpp @@ -1,15 +1,14 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztañaga 2004-2006. Distributed under the Boost +// (C) Copyright Ion Gaztañaga 2004-2007. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // // See http://www.boost.org/libs/interprocess for documentation. // ////////////////////////////////////////////////////////////////////////////// -#include -#include +#include #include #include #include diff --git a/test/list_test.hpp b/test/list_test.hpp index a70c046..acfe54b 100644 --- a/test/list_test.hpp +++ b/test/list_test.hpp @@ -11,6 +11,7 @@ #ifndef BOOST_INTERPROCESS_TEST_LIST_TEST_HEADER #define BOOST_INTERPROCESS_TEST_LIST_TEST_HEADER +#include #include "check_equal_containers.hpp" #include #include @@ -96,6 +97,7 @@ int list_test (bool copied_allocators_equal = true) const int max = 100; typedef push_data_function push_data_t; + try{ //Named new capable shared mem allocator //Create shared memory shared_memory_object::remove(shMemName); @@ -148,6 +150,14 @@ int list_test (bool copied_allocators_equal = true) if(!CheckEqualContainers(shmlist, stdlist)) return 1; } + shmlist->reverse(); + stdlist->reverse(); + if(!CheckEqualContainers(shmlist, stdlist)) return 1; + + shmlist->reverse(); + stdlist->reverse(); + if(!CheckEqualContainers(shmlist, stdlist)) return 1; + { IntType aux_vect[50]; for(int i = 0; i < 50; ++i){ @@ -178,12 +188,6 @@ int list_test (bool copied_allocators_equal = true) stdlist->resize(stdlist->size()/2); if(!CheckEqualContainers(shmlist, stdlist)) return 1; - const IntType &value1 = *shmlist->begin(); - shmlist->remove(value1); - const int &value2 = *stdlist->begin(); - stdlist->remove(value2); - if(!CheckEqualContainers(shmlist, stdlist)) return 1; - if(push_data_t()(max, shmlist, stdlist)){ return 1; } @@ -209,7 +213,19 @@ int list_test (bool copied_allocators_equal = true) return 1; } + if(push_data_t()(listsize, &othershmlist, &otherstdlist)){ + return 1; + } + if(copied_allocators_equal){ + shmlist->sort(std::greater()); + stdlist->sort(std::greater()); + if(!CheckEqualContainers(shmlist, stdlist)) return 1; + + othershmlist.sort(std::greater()); + otherstdlist.sort(std::greater()); + if(!CheckEqualContainers(&othershmlist, &otherstdlist)) return 1; + shmlist->merge(othershmlist, std::greater()); stdlist->merge(otherstdlist, std::greater()); if(!CheckEqualContainers(shmlist, stdlist)) return 1; @@ -217,6 +233,12 @@ int list_test (bool copied_allocators_equal = true) segment.template destroy("MyList"); delete stdlist; + } + catch(...){ + shared_memory_object::remove(shMemName); + throw; + } + shared_memory_object::remove(shMemName); return 0; } @@ -224,4 +246,6 @@ int list_test (bool copied_allocators_equal = true) } //namespace interprocess{ } //namespace boost{ +#include + #endif diff --git a/test/managed_mapped_file_test.cpp b/test/managed_mapped_file_test.cpp index 7bfa740..118505e 100644 --- a/test/managed_mapped_file_test.cpp +++ b/test/managed_mapped_file_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztañaga 2004-2006. Distributed under the Boost +// (C) Copyright Ion Gaztañaga 2004-2007. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -8,6 +8,7 @@ // ////////////////////////////////////////////////////////////////////////////// +#include #include #include #include @@ -90,36 +91,8 @@ int main () if(0 != mfile.find("MyVector").first) return -1; } - + std::remove(FileName); return 0; } -/* -#include -#include -#include - -using boost::interprocess::managed_mapped_file; -using boost::interprocess::allocator; -using boost::interprocess::vector; -using boost::interprocess::create_only; - -typedef allocator int_alloc; -typedef vector shvi; -typedef allocator vec_alloc; -typedef vector shvvi; - -int main() -{ - std::remove("./file_mapping"); - managed_mapped_file file_mapping(create_only, "./file_mapping", 1000); - - shvvi * svvi = file_mapping.construct("Vector") (file_mapping.get_segment_manager()); - shvi * svi = file_mapping.construct("SubVector") (file_mapping.get_segment_manager()); - - svvi->push_back(*svi); - - return 0; -} -*/ - +#include diff --git a/test/managed_windows_shared_memory_test.cpp b/test/managed_windows_shared_memory_test.cpp new file mode 100644 index 0000000..1ae8caa --- /dev/null +++ b/test/managed_windows_shared_memory_test.cpp @@ -0,0 +1,101 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2004-2007. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include + +#ifdef BOOST_WINDOWS + +#include +#include +#include +#include + +using namespace boost::interprocess; + +int main () +{ + const int MemSize = 65536; + const char *const MemName = "MySharedMemory"; + + //STL compatible allocator object for shared memory + typedef allocator + allocator_int_t; + //A vector that uses that allocator + typedef boost::interprocess::vector MyVect; + + { + const int max = 100; + void *array[max]; + //Named allocate capable shared memory allocator + managed_windows_shared_memory w_shm(create_only, MemName, MemSize); + + int i; + //Let's allocate some memory + for(i = 0; i < max; ++i){ + array[i] = w_shm.allocate(i+1); + } + + //Deallocate allocated memory + for(i = 0; i < max; ++i){ + w_shm.deallocate(array[i]); + } + } + + { + //Named allocate capable shared memory managed memory class + managed_windows_shared_memory w_shm(create_only, MemName, MemSize); + + //Construct the STL-like allocator with the segment manager + const allocator_int_t myallocator (w_shm.get_segment_manager()); + + //Construct vector + MyVect *w_shm_vect = w_shm.construct ("MyVector") (myallocator); + + //Test that vector can be found via name + if(w_shm_vect != w_shm.find("MyVector").first) + return -1; + + //Destroy and check it is not present + w_shm.destroy ("MyVector"); + if(0 != w_shm.find("MyVector").first) + return -1; + + //Construct a vector in the shared memory + w_shm_vect = w_shm.construct ("MyVector") (myallocator); + + //Map preexisting segment again in memory + managed_windows_shared_memory w_shm_new(open_only, MemName); + + //Check vector is still there + w_shm_vect = w_shm_new.find("MyVector").first; + if(!w_shm_vect) + return -1; + + if(w_shm_new.get_size() != w_shm.get_size()) + return 1; + //Destroy and check it is not present + w_shm_new.destroy_ptr(w_shm_vect); + if(0 != w_shm_new.find("MyVector").first) + return 1; + } + + return 0; +} + +#else + +int main() +{ + return 0; +} + +#endif + +#include diff --git a/test/map_index_allocation_test.cpp b/test/map_index_allocation_test.cpp new file mode 100644 index 0000000..2711235 --- /dev/null +++ b/test/map_index_allocation_test.cpp @@ -0,0 +1,25 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2006. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include "named_allocation_test_template.hpp" + +int main () +{ + using namespace boost::interprocess; + if(!test::test_named_allocation()){ + return 1; + } + + return 0; +} + +#include diff --git a/test/map_test.hpp b/test/map_test.hpp index 654760b..7825767 100644 --- a/test/map_test.hpp +++ b/test/map_test.hpp @@ -11,6 +11,7 @@ #ifndef BOOST_INTERPROCESS_TEST_MAP_TEST_HEADER #define BOOST_INTERPROCESS_TEST_MAP_TEST_HEADER +#include #include "check_equal_containers.hpp" #include #include @@ -43,6 +44,7 @@ int map_test () const char *const shMemName = "/MySharedMemory"; const int max = 100; + try{ //Create shared memory shared_memory_object::remove(shMemName); ManagedSharedMemory segment(create_only, shMemName, memsize); @@ -63,6 +65,50 @@ int map_test () MyStdMultiMap *stdmultimap = new MyStdMultiMap; + //Test construction from a range + { + //This is really nasty, but we have no other simple choice + IntPairType aux_vect[50]; + for(int i = 0; i < 50; ++i){ + new(&aux_vect[i])IntPairType(IntType(i/2), IntType(i/2)); + } + + typedef typename MyStdMap::value_type StdValueType; + typedef typename MyStdMap::key_type StdKeyType; + typedef typename MyStdMap::mapped_type StdMappedType; + StdValueType aux_vect2[50]; + for(int i = 0; i < 50; ++i){ + new(&aux_vect2[i])StdValueType(StdKeyType(i/2), StdMappedType(i/2)); + } + + IntPairType aux_vect3[50]; + for(int i = 0; i < 50; ++i){ + new(&aux_vect3[i])IntPairType(IntType(i/2), IntType(i/2)); + } + + MyShmMap *shmset2 = + segment.template construct("MyShmMap2") + (detail::make_move_iterator(&aux_vect[0]) + , detail::make_move_iterator(aux_vect + 50) + , std::less(), segment.get_segment_manager()); + + MyStdMap *stdset2 = new MyStdMap(aux_vect2, aux_vect2 + 50); + + MyShmMultiMap *shmmultiset2 = + segment.template construct("MyShmMultiMap2") + (detail::make_move_iterator(&aux_vect3[0]) + , detail::make_move_iterator(aux_vect3 + 50) + , std::less(), segment.get_segment_manager()); + + MyStdMultiMap *stdmultiset2 = new MyStdMultiMap(aux_vect2, aux_vect2 + 50); + if(!CheckEqualContainers(shmset2, stdset2)) return 1; + if(!CheckEqualContainers(shmmultiset2, stdmultiset2)) return 1; + segment.destroy_ptr(shmset2); + segment.destroy_ptr(shmmultiset2); + delete stdset2; + delete stdmultiset2; + } + int i, j; for(i = 0; i < max; ++i){ shmmap->insert(move(IntPairType (move(IntType(i)), move(IntType(i))))); @@ -263,7 +309,90 @@ int map_test () delete stdmap; segment.destroy_ptr(shmmultimap); delete stdmultimap; + } + catch(...){ + shared_memory_object::remove(shMemName); + throw; + } + shared_memory_object::remove(shMemName); + return 0; +} +template +int map_test_copyable () +{ + typedef typename MyShmMap::key_type IntType; + typedef std::pair IntPairType; + typedef typename MyStdMap::value_type StdPairType; + + const int memsize = 65536; + const char *const shMemName = "/MySharedMemory"; + const int max = 100; + + try{ + //Create shared memory + shared_memory_object::remove(shMemName); + ManagedSharedMemory segment(create_only, shMemName, memsize); + + segment.reserve_named_objects(100); + + //Shared memory allocator must be always be initialized + //since it has no default constructor + MyShmMap *shmmap = + segment.template construct("MyShmMap") + (std::less(), segment.get_segment_manager()); + + MyStdMap *stdmap = new MyStdMap; + + MyShmMultiMap *shmmultimap = + segment.template construct("MyShmMultiMap") + (std::less(), segment.get_segment_manager()); + + MyStdMultiMap *stdmultimap = new MyStdMultiMap; + + int i; + for(i = 0; i < max; ++i){ + shmmap->insert(move(IntPairType(move(IntType(i)), move(IntType(i))))); + stdmap->insert(StdPairType(i, i)); + shmmultimap->insert(move(IntPairType(move(IntType(i)), move(IntType(i))))); + stdmultimap->insert(StdPairType(i, i)); + } + if(!CheckEqualContainers(shmmap, stdmap)) return 1; + if(!CheckEqualContainers(shmmultimap, stdmultimap)) return 1; + + { + //Now, test copy constructor + MyShmMap shmmapcopy(*shmmap); + MyStdMap stdmapcopy(*stdmap); + MyShmMultiMap shmmmapcopy(*shmmultimap); + MyStdMultiMap stdmmapcopy(*stdmultimap); + + if(!CheckEqualContainers(&shmmapcopy, &stdmapcopy)) + return 1; + if(!CheckEqualContainers(&shmmmapcopy, &stdmmapcopy)) + return 1; + + //And now assignment + shmmapcopy = *shmmap; + stdmapcopy = *stdmap; + shmmmapcopy = *shmmultimap; + stdmmapcopy = *stdmultimap; + + if(!CheckEqualContainers(&shmmapcopy, &stdmapcopy)) + return 1; + if(!CheckEqualContainers(&shmmmapcopy, &stdmmapcopy)) + return 1; + } + } + catch(...){ + shared_memory_object::remove(shMemName); + throw; + } + shared_memory_object::remove(shMemName); return 0; } @@ -271,4 +400,6 @@ int map_test () } //namespace interprocess{ } //namespace boost{ +#include + #endif //#ifndef BOOST_INTERPROCESS_TEST_MAP_TEST_HEADER diff --git a/test/mapped_file_test.cpp b/test/mapped_file_test.cpp index 59a72e6..3873689 100644 --- a/test/mapped_file_test.cpp +++ b/test/mapped_file_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztañaga 2004-2006. Distributed under the Boost +// (C) Copyright Ion Gaztañaga 2004-2007. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -8,6 +8,7 @@ // ////////////////////////////////////////////////////////////////////////////// +#include #include #include #include @@ -74,3 +75,5 @@ int main () std::remove(FileName); return 0; } + +#include diff --git a/test/memory_algorithm_test.cpp b/test/memory_algorithm_test.cpp index 9237c0c..6a90ace 100644 --- a/test/memory_algorithm_test.cpp +++ b/test/memory_algorithm_test.cpp @@ -9,12 +9,12 @@ ////////////////////////////////////////////////////////////////////////////// #include -#include #include #include +#include #include #include -#include "allocation_test_template.hpp" +#include "memory_algorithm_test_template.hpp" #include @@ -23,11 +23,12 @@ int main () using namespace boost::interprocess; const int memsize = 16384; const char *const shMemName = "MySharedMemory"; + { //A shared memory with simple sequential fit algorithm typedef basic_managed_shared_memory > + ,simple_seq_fit ,null_index > my_managed_shared_memory; @@ -41,8 +42,25 @@ int main () } } + { + //A shared memory with red-black tree best fit algorithm + typedef basic_managed_shared_memory + + ,null_index + > my_managed_shared_memory; + + //Create shared memory + shared_memory_object::remove(shMemName); + my_managed_shared_memory segment(create_only, shMemName, memsize); + + //Now take the segment manager and launch memory test + if(!test::test_all_allocation(*segment.get_segment_manager())){ + return 1; + } + } + shared_memory_object::remove(shMemName); return 0; } #include - diff --git a/test/Attic/allocation_test_template.hpp b/test/memory_algorithm_test_template.hpp similarity index 55% rename from test/Attic/allocation_test_template.hpp rename to test/memory_algorithm_test_template.hpp index 1087d5a..e43636f 100644 --- a/test/Attic/allocation_test_template.hpp +++ b/test/memory_algorithm_test_template.hpp @@ -8,13 +8,15 @@ // ////////////////////////////////////////////////////////////////////////////// -#ifndef BOOST_INTERPROCESS_TEST_ALLOCATION_TEST_TEMPLATE_HEADER -#define BOOST_INTERPROCESS_TEST_ALLOCATION_TEST_TEMPLATE_HEADER +#ifndef BOOST_INTERPROCESS_TEST_MEMORY_ALGORITHM_TEST_TEMPLATE_HEADER +#define BOOST_INTERPROCESS_TEST_MEMORY_ALGORITHM_TEST_TEMPLATE_HEADER +#include #include #include #include #include +#include namespace boost { namespace interprocess { namespace test { @@ -182,6 +184,79 @@ bool test_allocation_expand(Allocator &a) return a.all_memory_deallocated() && a.check_sanity(); } +//This test allocates until there is no more memory +//and after that tries to expand all the buffers to +//avoid the wasted internal fragmentation +template +bool test_allocation_shrink_and_expand(Allocator &a) +{ + std::vector buffers; + std::vector received_sizes; + std::vector size_reduced; + + //Allocate buffers wand store received sizes + for(int i = 0; true; ++i){ + std::size_t received_size; + void *ptr = a.allocation_command + ( allocate_new | nothrow_allocation, i + , i*2, received_size).first; + if(!ptr){ + ptr = a.allocation_command + ( allocate_new | nothrow_allocation, 1 + , i*2, received_size).first; + if(!ptr) + break; + } + buffers.push_back(ptr); + received_sizes.push_back(received_size); + } + + //Now shrink to half + for(int i = 0, max = (int)buffers.size() + ;i < max + ; ++i){ + std::size_t received_size; + if(a.allocation_command( shrink_in_place | nothrow_allocation, received_sizes[i] + , i, received_size, buffers[i]).first){ + if(received_size > std::size_t(received_sizes[i])){ + return false; + } + if(received_size < std::size_t(i)){ + return false; + } + size_reduced.push_back(received_size != received_sizes[i]); + } + } + + //Now try to expand to the original size + for(int i = 0, max = (int)buffers.size() + ;i < max + ;++i){ + std::size_t received_size; + + if(a.allocation_command( expand_fwd | nothrow_allocation, received_sizes[i] + , received_sizes[i], received_size, buffers[i]).first){ + if(received_size != received_sizes[i]){ + return false; + } + } + else{ + return false; + } + } + + //Deallocate it in non sequential order + for(int j = 0, max = (int)buffers.size() + ;j < max + ;++j){ + int pos = (j%4)*((int)buffers.size())/4; + a.deallocate(buffers[pos]); + buffers.erase(buffers.begin()+pos); + } + + return a.all_memory_deallocated() && a.check_sanity(); +} + //This test allocates until there is no more memory //and after that deallocates the odd buffers to //make room for expansions. The expansion will probably @@ -258,53 +333,195 @@ bool test_allocation_deallocation_expand(Allocator &a) //the buffer fills all the memory template bool test_allocation_with_reuse(Allocator &a) +{ + //We will repeat this test for different sized elements + for(int size = 1; size < 20; ++size){ + std::vector buffers; + + //Allocate buffers with extra memory + for(int i = 0; true; ++i){ + void *ptr = a.allocate(i*size, std::nothrow); + if(!ptr) + break; + buffers.push_back(ptr); + } + + //Now deallocate all except the latest + //Now try to expand to the double of the size + for(int i = 0, max = (int)buffers.size() - 1 + ;i < max + ;++i){ + a.deallocate(buffers[i]); + } + + //Save the unique buffer and clear vector + void *ptr = buffers.back(); + buffers.clear(); + + //Now allocate with reuse + std::size_t received_size = 0; + for(int i = 0; true; ++i){ + std::pair ret = + a.allocation_command( expand_bwd | nothrow_allocation, received_size/size*size + size + , received_size/size*size+(i+1)*size*2, received_size, ptr, size); + if(!ret.first) + break; + //If we have memory, this must be a buffer reuse + if(!ret.second) + return 1; + ptr = ret.first; + } + //There is only a single block so deallocate it + a.deallocate(ptr); + + if(!a.all_memory_deallocated() || !a.check_sanity()) + return false; + } + return true; +} + + +//This test allocates memory with different alignments +//and checks returned memory is aligned. +template +bool test_aligned_allocation(Allocator &a) +{ + //Allocate aligned buffers in a loop + //and then deallocate it + bool continue_loop = true; + for(unsigned int i = 1; continue_loop; i <<= 1){ + for(unsigned int j = 1; true; j <<= 1){ + void *ptr = a.allocate_aligned(i-1, j, std::nothrow); + if(!ptr){ + if(j == 1) + continue_loop = false; + break; + } + + if(((std::size_t)ptr & (j - 1)) != 0) + return false; + a.deallocate(ptr); + if(!a.all_memory_deallocated() || !a.check_sanity()){ + return false; + } + } + } + + return a.all_memory_deallocated() && a.check_sanity(); +} + +//This test allocates memory with different alignments +//and checks returned memory is aligned. +template +bool test_continuous_aligned_allocation(Allocator &a) +{ + std::vector buffers; + //Allocate aligned buffers in a loop + //and then deallocate it + bool continue_loop = true; + for(unsigned i = 1; continue_loop && i; i <<= 1){ + for(unsigned int j = 1; j; j <<= 1){ + for(bool any_allocated = false; 1;){ + void *ptr = a.allocate_aligned(i-1, j, std::nothrow); + buffers.push_back(ptr); + if(!ptr){ + if(j == 1 && !any_allocated){ + continue_loop = false; + } + break; + } + else{ + any_allocated = true; + } + + if(((std::size_t)ptr & (j - 1)) != 0) + return false; + } + //Deallocate all + for(unsigned int k = (int)buffers.size(); k--;){ + a.deallocate(buffers[k]); + } + buffers.clear(); + if(!a.all_memory_deallocated() && a.check_sanity()) + return false; + if(!continue_loop) + break; + } + } + + return a.all_memory_deallocated() && a.check_sanity(); +} + +//This test allocates memory, writes it with a non-zero value and +//tests clear_free_memory initializes to zero for the next allocation +template +bool test_clear_free_memory(Allocator &a) { std::vector buffers; - //Allocate buffers with extra memory + //Allocate memory for(int i = 0; true; ++i){ void *ptr = a.allocate(i, std::nothrow); if(!ptr) break; buffers.push_back(ptr); } - - //Now deallocate all except the latest - //Now try to expand to the double of the size - for(int i = 0, max = (int)buffers.size() - 1 - ;i < max - ;++i){ - a.deallocate(buffers[i]); + + //Mark it + for(int i = 0, max = buffers.size(); i < max; ++i){ + std::memset(buffers[i], 1, i); } - //Save the unique buffer and clear vector - void *ptr = buffers.back(); + //Deallocate all + for(int j = (int)buffers.size() + ;j-- + ;){ + a.deallocate(buffers[j]); + } buffers.clear(); - //Now allocate with reuse - std::size_t received_size = 0; + if(!a.all_memory_deallocated() && a.check_sanity()) + return false; + + //Now clear all free memory + a.clear_free_memory(); + + if(!a.all_memory_deallocated() && a.check_sanity()) + return false; + + //Now test all allocated memory is zero + //Allocate memory for(int i = 0; true; ++i){ - std::pair ret = - a.allocation_command( expand_bwd | nothrow_allocation, received_size+1 - , received_size+(i+1)*2, received_size, ptr); - if(!ret.first) + void *ptr = a.allocate(i, std::nothrow); + if(!ptr) break; - //If we have memory, this must be a buffer reuse - if(!ret.second) - return 1; - ptr = ret.first; + buffers.push_back(ptr); } - //There is only a single block so deallocate it - a.deallocate(ptr); - - return a.all_memory_deallocated() && a.check_sanity(); + + //Test allocated memory is zero + for(int i = 0, max = buffers.size(); i < max; ++i){ + for(int j = 0; j < i; ++j){ + if(((char*)buffers[i])[j]) return false; + } + } + + //Deallocate all + for(int j = (int)buffers.size() + ;j-- + ;){ + a.deallocate(buffers[j]); + } + if(!a.all_memory_deallocated() && a.check_sanity()) + return false; + + return true; } + //This function calls all tests template bool test_all_allocation(Allocator &a) { - std::cout << "Starting test_allocation_direct_deallocation. Class: " << typeid(a).name() << std::endl; @@ -341,6 +558,12 @@ bool test_all_allocation(Allocator &a) return false; } + if(!test_allocation_shrink_and_expand(a)){ + std::cout << "test_allocation_shrink_and_expand failed. Class: " + << typeid(a).name() << std::endl; + return false; + } + std::cout << "Starting test_allocation_expand. Class: " << typeid(a).name() << std::endl; @@ -362,10 +585,30 @@ bool test_all_allocation(Allocator &a) return false; } + if(!test_aligned_allocation(a)){ + std::cout << "test_aligned_allocation failed. Class: " + << typeid(a).name() << std::endl; + return false; + } + + if(!test_continuous_aligned_allocation(a)){ + std::cout << "test_continuous_aligned_allocation failed. Class: " + << typeid(a).name() << std::endl; + return false; + } + + if(!test_clear_free_memory(a)){ + std::cout << "test_clear_free_memory failed. Class: " + << typeid(a).name() << std::endl; + return false; + } + return true; } }}} //namespace boost { namespace interprocess { namespace test { -#endif //BOOST_INTERPROCESS_TEST_ALLOCATION_TEST_TEMPLATE_HEADER +#include + +#endif //BOOST_INTERPROCESS_TEST_MEMORY_ALGORITHM_TEST_TEMPLATE_HEADER diff --git a/test/message_queue_test.cpp b/test/message_queue_test.cpp index d23f062..9305358 100644 --- a/test/message_queue_test.cpp +++ b/test/message_queue_test.cpp @@ -1,15 +1,14 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztañaga 2004-2006. Distributed under the Boost +// (C) Copyright Ion Gaztañaga 2004-2007. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // // See http://www.boost.org/libs/interprocess for documentation. // ////////////////////////////////////////////////////////////////////////////// -#include -#include +#include #include #include #include @@ -40,43 +39,47 @@ using namespace boost::interprocess; bool test_priority_order() { message_queue::remove("test_priority_order"); - message_queue mq1 - (open_or_create, "test_priority_order", 100, sizeof(std::size_t)), - mq2 - (open_or_create, "test_priority_order", 100, sizeof(std::size_t)); + { + message_queue mq1 + (open_or_create, "test_priority_order", 100, sizeof(std::size_t)), + mq2 + (open_or_create, "test_priority_order", 100, sizeof(std::size_t)); - //We test that the queue is ordered by priority and in the - //same priority, is a FIFO - std::size_t recvd = 0; - unsigned int priority = 0; - std::size_t tstamp; + //We test that the queue is ordered by priority and in the + //same priority, is a FIFO + std::size_t recvd = 0; + unsigned int priority = 0; + std::size_t tstamp; - //We will send 100 message with priority 0-9 - //The message will contain the timestamp of the message - for(std::size_t i = 0; i < 100; ++i){ - tstamp = i; - mq1.send(&tstamp, sizeof(tstamp), (unsigned int)(i%10)); - } - - unsigned int priority_prev = std::numeric_limits::max(); - std::size_t tstamp_prev = 0; - - //Receive all messages and test those are ordered - //by priority and by FIFO in the same priority - for(std::size_t i = 0; i < 100; ++i){ - mq1.receive(&tstamp, sizeof(tstamp), recvd, priority); - if(priority > priority_prev) - return false; - if(priority == priority_prev && - tstamp <= tstamp_prev){ - return false; + //We will send 100 message with priority 0-9 + //The message will contain the timestamp of the message + for(std::size_t i = 0; i < 100; ++i){ + tstamp = i; + mq1.send(&tstamp, sizeof(tstamp), (unsigned int)(i%10)); + } + + unsigned int priority_prev = std::numeric_limits::max(); + std::size_t tstamp_prev = 0; + + //Receive all messages and test those are ordered + //by priority and by FIFO in the same priority + for(std::size_t i = 0; i < 100; ++i){ + mq1.receive(&tstamp, sizeof(tstamp), recvd, priority); + if(priority > priority_prev) + return false; + if(priority == priority_prev && + tstamp <= tstamp_prev){ + return false; + } + priority_prev = priority; + tstamp_prev = tstamp; } - priority_prev = priority; - tstamp_prev = tstamp; } + message_queue::remove("test_priority_order"); return true; } +//[message_queue_test_test_serialize_db //This test creates a in memory data-base using Interprocess machinery and //serializes it through a message queue. Then rebuilds the data-base in //another buffer and checks it against the original data-base @@ -85,7 +88,7 @@ bool test_serialize_db() //Typedef data to create a Interprocess map typedef std::pair MyPair; typedef std::less MyLess; - typedef node_allocator + typedef node_allocator node_allocator_t; typedef map buffer_destiny(BufferSize, 0); message_queue::remove("message_queue"); - //Create the message-queues - message_queue mq1(create_only, "message_queue", 1, MaxMsgSize); + { + //Create the message-queues + message_queue mq1(create_only, "message_queue", 1, MaxMsgSize); - //Open previously created message-queue simulating other process - message_queue mq2(open_only, "message_queue"); + //Open previously created message-queue simulating other process + message_queue mq2(open_only, "message_queue"); - //A managed heap memory to create the origin database - managed_heap_memory db_origin(buffer_destiny.size()); + //A managed heap memory to create the origin database + managed_heap_memory db_origin(buffer_destiny.size()); - //Construct the map in the first buffer - MyMap *map1 = db_origin.construct("MyMap") - (MyLess(), - db_origin.get_segment_manager()); - if(!map1) - return false; + //Construct the map in the first buffer + MyMap *map1 = db_origin.construct("MyMap") + (MyLess(), + db_origin.get_segment_manager()); + if(!map1) + return false; - //Fill map1 until is full - try{ - std::size_t i = 0; + //Fill map1 until is full + try{ + std::size_t i = 0; + while(1){ + (*map1)[i] = i; + ++i; + } + } + catch(boost::interprocess::bad_alloc &){} + + //Data control data sending through the message queue + std::size_t sent = 0; + std::size_t recvd = 0; + std::size_t total_recvd = 0; + unsigned int priority; + + //Send whole first buffer through the mq1, read it + //through mq2 to the second buffer while(1){ - (*map1)[i] = i; - ++i; + //Send a fragment of buffer1 through mq1 + std::size_t bytes_to_send = MaxMsgSize < (db_origin.get_size() - sent) ? + MaxMsgSize : (db_origin.get_size() - sent); + mq1.send( &static_cast(db_origin.get_address())[sent] + , bytes_to_send + , 0); + sent += bytes_to_send; + //Receive the fragment through mq2 to buffer_destiny + mq2.receive( &buffer_destiny[total_recvd] + , BufferSize - recvd + , recvd + , priority); + total_recvd += recvd; + + //Check if we have received all the buffer + if(total_recvd == BufferSize){ + break; + } } - } - catch(boost::interprocess::bad_alloc &){} + + //The buffer will contain a copy of the original database + //so let's interpret the buffer with managed_external_buffer + managed_external_buffer db_destiny(open_only, &buffer_destiny[0], BufferSize); - //Data control data sending through the message queue - std::size_t sent = 0; - std::size_t recvd = 0; - std::size_t total_recvd = 0; - unsigned int priority; + //Let's find the map + std::pair ret = db_destiny.find("MyMap"); + MyMap *map2 = ret.first; - //Send whole first buffer through the mq1, read it - //through mq2 to the second buffer - while(1){ - //Send a fragment of buffer1 through mq1 - std::size_t bytes_to_send = MaxMsgSize < (db_origin.get_size() - sent) ? - MaxMsgSize : (db_origin.get_size() - sent); - mq1.send( &static_cast(db_origin.get_address())[sent] - , bytes_to_send - , 0); - sent += bytes_to_send; - //Receive the fragment through mq2 to buffer_destiny - mq2.receive( &buffer_destiny[total_recvd] - , BufferSize - recvd - , recvd - , priority); - total_recvd += recvd; - - //Check if we have received all the buffer - if(total_recvd == BufferSize){ - break; - } - } - - //The buffer will contain a copy of the original database - //so let's interpret the buffer with managed_external_buffer - managed_external_buffer db_destiny(open_only, &buffer_destiny[0], BufferSize); - - //Let's find the map - std::pair ret = db_destiny.find("MyMap"); - MyMap *map2 = ret.first; - - //Check if we have found it - if(!map2){ - return false; - } - - //Check if it is a single variable (not an array) - if(ret.second != 1){ - return false; - } - - //Now let's compare size - if(map1->size() != map2->size()){ - return false; - } - - //Now let's compare all db values - for(std::size_t i = 0, num_elements = map1->size(); i < num_elements; ++i){ - if((*map1)[i] != (*map2)[i]){ + //Check if we have found it + if(!map2){ return false; } - } - - //Destroy maps from db-s - db_origin.destroy_ptr(map1); - db_destiny.destroy_ptr(map2); + //Check if it is a single variable (not an array) + if(ret.second != 1){ + return false; + } + + //Now let's compare size + if(map1->size() != map2->size()){ + return false; + } + + //Now let's compare all db values + for(std::size_t i = 0, num_elements = map1->size(); i < num_elements; ++i){ + if((*map1)[i] != (*map2)[i]){ + return false; + } + } + + //Destroy maps from db-s + db_origin.destroy_ptr(map1); + db_destiny.destroy_ptr(map2); + } + message_queue::remove("message_queue"); return true; } - +//] static const int MsgSize = 10; static const int NumMsg = 1000; static char msgsend [10]; @@ -215,22 +220,25 @@ void receiver() bool test_buffer_overflow() { boost::interprocess::message_queue::remove("mymsg"); - std::auto_ptr - ptr(new boost::interprocess::message_queue - (create_only, "mymsg", 10, 10)); - pmessage_queue = ptr.get(); + { + std::auto_ptr + ptr(new boost::interprocess::message_queue + (create_only, "mymsg", 10, 10)); + pmessage_queue = ptr.get(); - //Launch the receiver thread - boost::thread thread(&receiver); - boost::thread::yield(); + //Launch the receiver thread + boost::thread thread(&receiver); + boost::thread::yield(); - int nummsg = NumMsg; + int nummsg = NumMsg; - while(nummsg--){ - pmessage_queue->send(msgsend, MsgSize, 0); + while(nummsg--){ + pmessage_queue->send(msgsend, MsgSize, 0); + } + + thread.join(); } - - thread.join(); + boost::interprocess::message_queue::remove("mymsg"); return true; } diff --git a/test/movable_int.hpp b/test/movable_int.hpp index 98cdc27..5c8b12a 100644 --- a/test/movable_int.hpp +++ b/test/movable_int.hpp @@ -59,10 +59,22 @@ class movable_int bool operator >(const movable_int &mi) const { return this->m_int > mi.m_int; } + int get_int() const + { return m_int; } + private: int m_int; }; +template +std::basic_ostream & operator<< + (std::basic_ostream & os, movable_int const & p) + +{ + os << p.get_int(); + return os; +} + class movable_and_copyable_int { public: @@ -107,10 +119,21 @@ class movable_and_copyable_int bool operator >(const movable_and_copyable_int &mi) const { return this->m_int > mi.m_int; } + int get_int() const + { return m_int; } + private: int m_int; }; +template +std::basic_ostream & operator<< + (std::basic_ostream & os, movable_and_copyable_int const & p) + +{ + os << p.get_int(); + return os; +} } //namespace test { } //namespace interprocess { diff --git a/test/mutex_test.cpp b/test/mutex_test.cpp index 51db1e4..2cf655a 100644 --- a/test/mutex_test.cpp +++ b/test/mutex_test.cpp @@ -1,14 +1,14 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztañaga 2004-2006. Distributed under the Boost +// (C) Copyright Ion Gaztañaga 2004-2007. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // // See http://www.boost.org/libs/interprocess for documentation. // ////////////////////////////////////////////////////////////////////////////// + #include -#include #include #include #include diff --git a/test/mutex_test_template.hpp b/test/mutex_test_template.hpp index 1c88d2c..a322ae6 100644 --- a/test/mutex_test_template.hpp +++ b/test/mutex_test_template.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztañaga 2004-2006. Distributed under the Boost +// (C) Copyright Ion Gaztañaga 2004-2007. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // @@ -21,6 +21,7 @@ #ifndef BOOST_INTERPROCESS_TEST_MUTEX_TEST_TEMPLATE_HEADER #define BOOST_INTERPROCESS_TEST_MUTEX_TEST_TEMPLATE_HEADER +#include #include #include "boost_interprocess_check.hpp" #include "util.hpp" @@ -346,4 +347,6 @@ void test_all_mutex() }}} //namespace boost { namespace interprocess { namespace test { +#include + #endif //BOOST_INTERPROCESS_TEST_MUTEX_TEST_TEMPLATE_HEADER diff --git a/test/named_allocation_test_template.hpp b/test/named_allocation_test_template.hpp new file mode 100644 index 0000000..d6e2bb5 --- /dev/null +++ b/test/named_allocation_test_template.hpp @@ -0,0 +1,312 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztañaga 2006. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_NAMED_ALLOCATION_TEST_TEMPLATE_HEADER +#define BOOST_INTERPROCESS_NAMED_ALLOCATION_TEST_TEMPLATE_HEADER + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace interprocess { namespace test { + +//This test allocates until there is no more memory +//and after that deallocates all in the same order +template +bool test_names_and_types(ManagedMemory &m) +{ + std::vector buffers; + const int BufferLen = 100; + char name[BufferLen]; + + for(int i = 0; true; ++i){ + std::sprintf(name, "%s%010d", "prefix_name_", i); + char *ptr = m.template construct(name, std::nothrow)(i); + + if(!ptr) + break; + if(std::strcmp(m.get_name(ptr), name) != 0) + return false; + + if(m.template find(name).first == 0) + return false; + + if(m.get_type(ptr) != named_type) + return false; + + buffers.push_back(ptr); + } + + if(m.get_num_named_objects() != buffers.size() || !m.check_sanity()) + return false; + + for(int j = 0, max = (int)buffers.size() + ;j < max + ;++j){ + m.destroy_ptr(buffers[j]); + } + + if(m.get_num_named_objects() != 0 || !m.check_sanity()) + return false; + return true; +} + +//This test allocates until there is no more memory +//and after that deallocates all in the same order +template +bool test_direct_named_allocation_destruction(ManagedMemory &m) +{ + std::vector buffers; + const int BufferLen = 100; + char name[BufferLen]; + + for(int i = 0; true; ++i){ + std::sprintf(name, "%s%010d", "prefix_name_", i); + char *ptr = m.template construct(name, std::nothrow)(i); + if(!ptr) + break; + if(m.template find(name).first == 0) + return false; + buffers.push_back(ptr); + } + + if(m.get_num_named_objects() != buffers.size() || !m.check_sanity()) + return false; + + for(int j = 0, max = (int)buffers.size() + ;j < max + ;++j){ + m.destroy_ptr(buffers[j]); + } + + if(m.get_num_named_objects() != 0 || !m.check_sanity()) + return false; + return true; +} + +//This test allocates until there is no more memory +//and after that deallocates all in the inverse order +template +bool test_named_allocation_inverse_destruction(ManagedMemory &m) +{ + std::vector buffers; + const int BufferLen = 100; + char name[BufferLen]; + + for(int i = 0; true; ++i){ + std::sprintf(name, "%s%010d", "prefix_name_", i); + char *ptr = m.template construct(name, std::nothrow)(i); + if(!ptr) + break; + buffers.push_back(ptr); + } + + if(m.get_num_named_objects() != buffers.size() || !m.check_sanity()) + return false; + + for(int j = (int)buffers.size() + ;j-- + ;){ + m.destroy_ptr(buffers[j]); + } + + if(m.get_num_named_objects() != 0 || !m.check_sanity()) + return false; + return true; +} + +//This test allocates until there is no more memory +//and after that deallocates all following a pattern +template +bool test_named_allocation_mixed_destruction(ManagedMemory &m) +{ + std::vector buffers; + const int BufferLen = 100; + char name[BufferLen]; + + for(int i = 0; true; ++i){ + std::sprintf(name, "%s%010d", "prefix_name_", i); + char *ptr = m.template construct(name, std::nothrow)(i); + if(!ptr) + break; + buffers.push_back(ptr); + } + + if(m.get_num_named_objects() != buffers.size() || !m.check_sanity()) + return false; + + for(int j = 0, max = (int)buffers.size() + ;j < max + ;++j){ + int pos = (j%4)*((int)buffers.size())/4; + m.destroy_ptr(buffers[pos]); + buffers.erase(buffers.begin()+pos); + } + + if(m.get_num_named_objects() != 0 || !m.check_sanity()) + return false; + return true; +} + +//This test allocates until there is no more memory +//and after that deallocates all in the same order +template +bool test_inverse_named_allocation_destruction(ManagedMemory &m) +{ + std::vector buffers; + const int BufferLen = 100; + char name[BufferLen]; + const unsigned int FirstNumber = (unsigned int)-1; + + for(unsigned int i = 0; true; ++i){ + std::sprintf(name, "%s%010u", "prefix_name_", FirstNumber - i); + char *ptr = m.template construct(name, std::nothrow)(i); + if(!ptr) + break; + buffers.push_back(ptr); + } + + if(m.get_num_named_objects() != buffers.size() || !m.check_sanity()) + return false; + + for(unsigned int j = 0, max = (unsigned int)buffers.size() + ;j < max + ;++j){ + m.destroy_ptr(buffers[j]); + } + + if(m.get_num_named_objects() != 0 || !m.check_sanity()) + return false; + return true; +} + +///This function calls all tests +template +bool test_all_named_allocation(ManagedMemory &m) +{ + std::cout << "Starting test_names_and_types. Class: " + << typeid(m).name() << std::endl; + + if(!test_names_and_types(m)){ + std::cout << "test_names_and_types failed. Class: " + << typeid(m).name() << std::endl; + return false; + } + + std::cout << "Starting test_direct_named_allocation_destruction. Class: " + << typeid(m).name() << std::endl; + + if(!test_direct_named_allocation_destruction(m)){ + std::cout << "test_direct_named_allocation_destruction failed. Class: " + << typeid(m).name() << std::endl; + return false; + } + + std::cout << "Starting test_named_allocation_inverse_destruction. Class: " + << typeid(m).name() << std::endl; + + if(!test_named_allocation_inverse_destruction(m)){ + std::cout << "test_named_allocation_inverse_destruction failed. Class: " + << typeid(m).name() << std::endl; + return false; + } + + std::cout << "Starting test_named_allocation_mixed_destruction. Class: " + << typeid(m).name() << std::endl; + + if(!test_named_allocation_mixed_destruction(m)){ + std::cout << "test_named_allocation_mixed_destruction failed. Class: " + << typeid(m).name() << std::endl; + return false; + } + + std::cout << "Starting test_inverse_named_allocation_destruction. Class: " + << typeid(m).name() << std::endl; + + if(!test_inverse_named_allocation_destruction(m)){ + std::cout << "test_inverse_named_allocation_destruction failed. Class: " + << typeid(m).name() << std::endl; + return false; + } + + return true; +} + +//This function calls all tests +template