diff --git a/doc/interprocess.qbk b/doc/interprocess.qbk index 047cc29..3c1eb6f 100644 --- a/doc/interprocess.qbk +++ b/doc/interprocess.qbk @@ -1,5 +1,5 @@ [/ - / Copyright (c) 2005-2011 Ion Gaztanaga + / Copyright (c) 2005-2012 Ion Gaztanaga / / 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) @@ -622,14 +622,9 @@ to shared memory created with other process that don't use 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 transmit the size of the segment to processes opening the -segment. +shared memory. Sharing memory between services and user applications is also different. To share memory between services and user applications the name of the shared memory must start with the @@ -865,7 +860,7 @@ to create `mapped_region` objects. A mapped region created from a shared memory object or a file mapping are the same class and this has many advantages. One can, for example, mix in STL containers mapped regions from shared memory -and memory mapped files. The libraries that only depend on mapped regions can +and memory mapped files. Libraries that only depend on mapped regions can be used to work with shared memory or memory mapped files without recompiling them. [endsect] @@ -881,7 +876,7 @@ surely different in each process. Since each process might have used its address in a different way (allocation of more or less dynamic memory, for example), there is no guarantee that the file/shared memory is going to be mapped in the same address. -If two processes map the same object in different addresses, this invalids the use +If two processes map the same object in different addresses, this invalidates the use of pointers in that memory, since the pointer (which is an absolute address) would only make sense for the process that wrote it. The solution for this is to use offsets (distance) between objects instead of pointers: If two objects are placed in the same @@ -1590,6 +1585,14 @@ Boost.Interprocess offers the following condition types: An anonymous condition variable that can be placed in shared memory or memory mapped files to be used with [classref boost::interprocess::interprocess_mutex]. +[c++] + + #include + +* [classref boost::interprocess::interprocess_condition_any interprocess_condition_any]: + An anonymous condition variable that can be placed in shared memory or memory + mapped files to be used with any lock type. + [c++] #include @@ -1597,6 +1600,13 @@ Boost.Interprocess offers the following condition types: * [classref boost::interprocess::named_condition named_condition]: A named condition variable to be used with [classref boost::interprocess::named_mutex named_mutex]. +[c++] + + #include + +* [classref boost::interprocess::named_condition named_condition]: A named + condition variable to be used with any lock type. + Named conditions are similar to anonymous conditions, but they are used in combination with named mutexes. Several times, we don't want to store synchronization objects with the synchronized data: @@ -1725,12 +1735,12 @@ efficient than a mutex/condition combination. [endsect] -[section:upgradable_mutexes Upgradable Mutexes] +[section:sharable_upgradable_mutexes Sharable and Upgradable Mutexes] -[section:upgradable_whats_a_mutex What's An Upgradable Mutex?] +[section:upgradable_whats_a_mutex What's a Sharable and an Upgradable Mutex?] -An upgradable mutex is a special mutex that offers more locking possibilities than -a normal mutex. Sometimes, we can distinguish between [*reading] the data and +Sharable and upgradable mutex are special mutex types that offers more locking possibilities +than a normal mutex. Sometimes, we can distinguish between [*reading] the data and [*modifying] the data. If just some threads need to modify the data, and a plain mutex is used to protect the data from concurrent access, concurrency is pretty limited: two threads that only read the data will be serialized instead of being executed @@ -1740,20 +1750,21 @@ If we allow concurrent access to threads that just read the data but we avoid concurrent access between threads that read and modify or between threads that modify, we can increase performance. This is specially true in applications where data reading is more common than data modification and the synchronized data reading code needs -some time to execute. With an upgradable mutex we can acquire 3 -lock types: +some time to execute. With a sharable mutex we can acquire 2 lock types: * [*Exclusive lock]: Similar to a plain mutex. If a thread acquires an exclusive lock, no other thread can acquire any lock (exclusive or other) until the exclusive - lock is released. If any thread has a sharable or upgradable lock a thread trying + lock is released. If any thread other has any lock other than exclusive, a thread trying to acquire an exclusive lock will block. This lock will be acquired by threads that will modify the data. * [*Sharable lock]: If a thread acquires a sharable lock, other threads - can acquire a sharable lock or an upgradable lock. If any thread has acquired + can't acquire the exclusive lock. If any thread has acquired the exclusive lock a thread trying to acquire a sharable lock will block. This locking is executed by threads that just need to read the data. +With an upgradable mutex we can acquire previous locks plus a new upgradable lock: + * [*Upgradable lock]: Acquiring an upgradable lock is similar to acquiring a [*privileged sharable lock]. If a thread acquires an upgradable lock, other threads can acquire a sharable lock. If any thread has acquired the exclusive or upgradable lock @@ -1772,20 +1783,34 @@ lock types: To sum up: -[table Locking Possibilities +[table Locking Possibilities for a Sharable Mutex + [[If a thread has acquired the...] [Other threads can acquire...]] + [[Sharable lock] [many sharable locks]] + [[Exclusive lock] [no locks]] +] + +[table Locking Possibilities for an Upgradable Mutex [[If a thread has acquired the...] [Other threads can acquire...]] [[Sharable lock] [many sharable locks and 1 upgradable lock]] [[Upgradable lock] [many sharable locks]] [[Exclusive lock] [no locks]] ] -A thread that has acquired a lock can try to acquire another lock type atomically. +[endsect] + +[section:upgradable_transitions Lock transitions for Upgradable Mutex] + +A sharable mutex has no option to change the acquired lock for another lock +atomically. + +On the other hand, for an upgradable mutex, a thread that has +acquired a lock can try to acquire another lock type atomically. All lock transitions are not guaranteed to succeed. Even if a transition is guaranteed to succeed, some transitions will block the thread waiting until other threads release the sharable locks. [*Atomically] means that no other thread will acquire an Upgradable or Exclusive lock in the transition, [*so data is guaranteed to remain unchanged]: -[table Transition Possibilities +[table Transition Possibilities for an Upgradable Mutex [[If a thread has acquired the...] [It can atomically release the previous lock and...]] [[Sharable lock] [try to obtain (not guaranteed) immediately the Exclusive lock if no other thread has exclusive or upgrable lock]] [[Sharable lock] [try to obtain (not guaranteed) immediately the Upgradable lock if no other thread has exclusive or upgrable lock]] @@ -1803,18 +1828,18 @@ and there are more readers than modifiers. [endsect] -[section:upgradable_mutexes_operations Upgradable Mutex Operations] +[section:sharable_upgradable_mutexes_operations Upgradable Mutex Operations] All the upgradable mutex types from [*Boost.Interprocess] implement the following operations: -[section:upgradable_mutexes_operations_exclusive Exclusive Locking] +[section:sharable_upgradable_mutexes_operations_exclusive Exclusive Locking (Sharable & Upgradable Mutexes)] [blurb ['[*void lock()]]] [*Effects:] The calling thread tries to obtain exclusive ownership of the mutex, and if -another thread has exclusive, sharable or upgradable ownership of the mutex, +another thread has any ownership of the mutex (exclusive or other), it waits until it can obtain the ownership. [*Throws:] *interprocess_exception* on error. @@ -1823,8 +1848,8 @@ it waits until it can obtain the ownership. [*Effects:] The calling thread tries to acquire exclusive ownership of the mutex without -waiting. If no other thread has exclusive, sharable or upgradable ownership of -the mutex this succeeds. +waiting. If no other thread has any ownership of the mutex (exclusive or other) +this succeeds. [*Returns:] If it can acquire exclusive ownership immediately returns true. If it has to wait, returns false. @@ -1835,8 +1860,8 @@ If it has to wait, returns false. [*Effects:] The calling thread tries to acquire exclusive ownership of the mutex -waiting if necessary until no other thread has exclusive, -sharable or upgradable ownership of the mutex or abs_time is reached. +waiting if necessary until no other thread has any ownership of the mutex +(exclusive or other) or abs_time is reached. [*Returns:] If acquires exclusive ownership, returns true. Otherwise returns false. @@ -1853,7 +1878,7 @@ returns false. [endsect] -[section:upgradable_mutexes_operations_sharable Sharable Locking] +[section:sharable_upgradable_mutexes_operations_sharable Sharable Locking (Sharable & Upgradable Mutexes)] [blurb ['[*void lock_sharable()]]] @@ -1898,7 +1923,7 @@ returns false. [endsect] -[section:upgradable_mutexes_operations_upgradable Upgradable Locking] +[section:upgradable_mutexes_operations_upgradable Upgradable Locking (Upgradable Mutex only)] [blurb ['[*void lock_upgradable()]]] @@ -1943,7 +1968,7 @@ returns false. [endsect] -[section:upgradable_mutexes_operations_demotions Demotions] +[section:upgradable_mutexes_operations_demotions Demotions (Upgradable Mutex only)] [blurb ['[*void unlock_and_lock_upgradable()]]] @@ -1974,7 +1999,7 @@ ownership. This operation is non-blocking. [endsect] -[section:upgradable_mutexes_operations_promotions Promotions] +[section:upgradable_mutexes_operations_promotions Promotions (Upgradable Mutex only)] [blurb ['[*void unlock_upgradable_and_lock()]]] [*Precondition:] The thread must have upgradable ownership of the mutex. @@ -2036,7 +2061,23 @@ are UTC time points, not local time points] [endsect] -[section:upgradable_mutexes_mutex_interprocess_mutexes Boost.Interprocess Upgradable Mutex Types And Headers] +[section:sharable_upgradable_mutexes_mutex_interprocess_mutexes Boost.Interprocess Sharable & Upgradable Mutex Types And Headers] + +Boost.Interprocess offers the following sharable mutex types: + +[c++] + + #include + +* [classref boost::interprocess::interprocess_sharable_mutex interprocess_sharable_mutex]: A non-recursive, + anonymous sharable mutex that can be placed in shared memory or memory mapped files. + +[c++] + + #include + +* [classref boost::interprocess::named_sharable_mutex named_sharable_mutex]: A non-recursive, + named sharable mutex. Boost.Interprocess offers the following upgradable mutex types: @@ -2056,7 +2097,7 @@ Boost.Interprocess offers the following upgradable mutex types: [endsect] -[section:upgradable_mutexes_locks Sharable Lock And Upgradable Lock] +[section:sharable_upgradable_locks Sharable Lock And Upgradable Lock] As with plain mutexes, it's important to release the acquired lock even in the presence of exceptions. [*Boost.Interprocess] mutexes are best used with the @@ -2089,20 +2130,16 @@ can use `sharable_lock` if the synchronization object offers [*lock_sharable()] `sharable_lock` calls [*unlock_sharable()] in its destructor, and `upgradable_lock` calls [*unlock_upgradable()] in its destructor, so the upgradable mutex is always unlocked when an exception occurs. -Scoped lock has many constructors to lock, -try_lock, timed_lock a mutex or not to lock it at all. - [c++] using namespace boost::interprocess; - //Let's create any mutex type: - MutexType mutex; + SharableOrUpgradableMutex sh_or_up_mutex; { //This will call lock_sharable() - sharable_lock lock(mutex); + sharable_lock lock(sh_or_up_mutex); //Some code @@ -2111,7 +2148,7 @@ try_lock, timed_lock a mutex or not to lock it at all. { //This won't lock the mutex() - sharable_lock lock(mutex, defer_lock); + sharable_lock lock(sh_or_up_mutex, defer_lock); //Lock it on demand. This will call lock_sharable() lock.lock(); @@ -2123,7 +2160,7 @@ try_lock, timed_lock a mutex or not to lock it at all. { //This will call try_lock_sharable() - sharable_lock lock(mutex, try_to_lock); + sharable_lock lock(sh_or_up_mutex, try_to_lock); //Check if the mutex has been successfully locked if(lock){ @@ -2136,7 +2173,7 @@ try_lock, timed_lock a mutex or not to lock it at all. boost::posix_time::ptime abs_time = ... //This will call timed_lock_sharable() - scoped_lock lock(mutex, abs_time); + scoped_lock lock(sh_or_up_mutex, abs_time); //Check if the mutex has been successfully locked if(lock){ @@ -2145,9 +2182,11 @@ try_lock, timed_lock a mutex or not to lock it at all. //If the mutex was locked it will be unlocked } + UpgradableMutex up_mutex; + { //This will call lock_upgradable() - upgradable_lock lock(mutex); + upgradable_lock lock(up_mutex); //Some code @@ -2156,7 +2195,7 @@ try_lock, timed_lock a mutex or not to lock it at all. { //This won't lock the mutex() - upgradable_lock lock(mutex, defer_lock); + upgradable_lock lock(up_mutex, defer_lock); //Lock it on demand. This will call lock_upgradable() lock.lock(); @@ -2168,7 +2207,7 @@ try_lock, timed_lock a mutex or not to lock it at all. { //This will call try_lock_upgradable() - upgradable_lock lock(mutex, try_to_lock); + upgradable_lock lock(up_mutex, try_to_lock); //Check if the mutex has been successfully locked if(lock){ @@ -2181,7 +2220,7 @@ try_lock, timed_lock a mutex or not to lock it at all. boost::posix_time::ptime abs_time = ... //This will call timed_lock_upgradable() - scoped_lock lock(mutex, abs_time); + scoped_lock lock(up_mutex, abs_time); //Check if the mutex has been successfully locked if(lock){ @@ -6574,11 +6613,13 @@ example, a new managed shared memory that uses the new index: [section:notes_windows Notes for Windows users] -[*Boost.Interprocess] uses the COM library to implement some features and initializes -the COM library with concurrency model `COINIT_APARTMENTTHREADED`. -If the COM library was already initialized by the calling thread for other model, [*Boost.Interprocess] +[section:notes_windows_com_init COM Initialization] + +[*Boost.Interprocess] uses the Windows COM library to implement some features and initializes +it with concurrency model `COINIT_APARTMENTTHREADED`. +If the COM library was already initialized by the calling thread for another concurrency model, [*Boost.Interprocess] handles this gracefully and uses COM calls for the already initialized model. If for some reason, you -might want [*Boost.Interprocess] to initialize the COM library with another model, define the macro +want [*Boost.Interprocess] to initialize the COM library with another model, define the macro `BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL` before including [*Boost.Interprocess] to one of these values: * `COINIT_APARTMENTTHREADED_BIPC` @@ -6588,6 +6629,46 @@ might want [*Boost.Interprocess] to initialize the COM library with another mode [endsect] +[section:notes_windows_shm_folder Shared memory emulation folder] + +Shared memory (`shared_memory_object`) is implemented in windows using memory mapped files, placed in a +directory in the shared documents folder (`SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders\Common AppData`). +This directory name is the last bootup time (obtained via COM calls), so that each bootup shared memory is created in a new +folder obtaining kernel persistence shared memory. + +Unfortunately, due to COM implementation related errors, in Boost 1.48 & Boost 1.49 the bootup-time folder was dumped and files +were directly created in shared documents folder, reverting to filesystem persistence shared memory. Boost 1.50 fixed those issues +and recovered bootup time directory and kernel persistence. If you need to reproduce Boost 1.48 & Boost 1.49 behaviour to communicate +with applications compiled with that version, comment `#define BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME` directive +in the Windows configuration part of `boost/interprocess/detail/workaround.hpp`. + +[endsect] + +[endsect] + +[section:notes_linux Notes for Linux users] + +[section:notes_linux_overcommit Overcommit] + +The committed address space is the total amount of virtual memory (swap or physical memory/RAM) that the kernel might have to supply +if all applications decide to access all of the memory they've requested from the kernel. +By default, Linux allows processes to commit more virtual memory than available in the system. If that memory is not +accessed, no physical memory + swap is actually used. + +The reason for this behaviour is that Linux tries to optimize memory usage on forked processes; fork() creates a full copy of +the process space, but with overcommitted memory, in this new forked instance only pages which have been written to actually need +to be allocated by the kernel. If applications access more memory than available, then the kernel must free memory in the hard way: +the OOM (Out Of Memory)-killer picks some processes to kill in order to recover memory. + +[*Boost.Interprocess] has no way to change this behaviour and users might suffer the OOM-killer when accessing shared memory. +According to the [@http://www.kernel.org/doc/Documentation/vm/overcommit-accounting Kernel documentation], the +Linux kernel supports several overcommit modes. If you need non-kill guarantees in your application, you should +change this overcommit behaviour. + +[endsect] + +[endsect] + [endsect] [section:thanks_to Thanks to...] @@ -6635,11 +6716,30 @@ thank them: [section:release_notes Release Notes] +[section:release_notes_boost_1_52_00 Boost 1.52 Release] + +* Added `shrink_by` and `advise` functions in `mapped_region`. +* [*ABI breaking]Reimplemented `message_queue` with a circular buffer index (the + old behavior used an ordered array, leading to excessive copies). This + should greatly increase performance but breaks ABI. Old behaviour/ABI can be used + undefining macro `BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX` in `boost/interprocess/detail/workaround.hpp` +* Improved `message_queue` insertion time avoiding priority search for common cases + (both array and circular buffer configurations). +* Implemented `sharable_mutex` and `interproces_condition_any`. +* Improved `offset_ptr` performance. +* Added integer overflow checks. + +[endsect] + [section:release_notes_boost_1_51_00 Boost 1.51 Release] * Synchronous and asynchronous flushing for `mapped_region::flush`. -* Source & ABI breaking: Removed `get_offset` method from `mapped_region` as +* [*Source & ABI breaking]: Removed `get_offset` method from `mapped_region` as it has no practical utility and `m_offset` member was not for anything else. +* [*Source & ABI breaking]: Removed `flush` from `managed_shared_memory`. + as it is unspecified according to POSIX: + [@http://pubs.opengroup.org/onlinepubs/009695399/functions/msync.html + ['"The effect of msync() on a shared memory object or a typed memory object is unspecified"] ]. * Fixed bug [@https://svn.boost.org/trac/boost/ticket/7152 #7152], diff --git a/example/Jamfile.v2 b/example/Jamfile.v2 index b2d7194..5362e33 100644 --- a/example/Jamfile.v2 +++ b/example/Jamfile.v2 @@ -1,6 +1,6 @@ # Boost Interprocess Library Example Jamfile -# (C) Copyright Ion Gaztanaga 2006. +# (C) Copyright Ion Gaztanaga 2006-2012. # 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) diff --git a/example/comp_doc_anonymous_conditionA.cpp b/example/comp_doc_anonymous_conditionA.cpp index f015a9e..79aef83 100644 --- a/example/comp_doc_anonymous_conditionA.cpp +++ b/example/comp_doc_anonymous_conditionA.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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/example/comp_doc_anonymous_conditionB.cpp b/example/comp_doc_anonymous_conditionB.cpp index ba8c2d8..a1694dc 100644 --- a/example/comp_doc_anonymous_conditionB.cpp +++ b/example/comp_doc_anonymous_conditionB.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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/example/comp_doc_anonymous_mutexA.cpp b/example/comp_doc_anonymous_mutexA.cpp index d27933f..16793af 100644 --- a/example/comp_doc_anonymous_mutexA.cpp +++ b/example/comp_doc_anonymous_mutexA.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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/example/comp_doc_anonymous_mutexB.cpp b/example/comp_doc_anonymous_mutexB.cpp index 4cc73a6..1365ad5 100644 --- a/example/comp_doc_anonymous_mutexB.cpp +++ b/example/comp_doc_anonymous_mutexB.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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/example/comp_doc_anonymous_semaphoreA.cpp b/example/comp_doc_anonymous_semaphoreA.cpp index 800e91a..34e9960 100644 --- a/example/comp_doc_anonymous_semaphoreA.cpp +++ b/example/comp_doc_anonymous_semaphoreA.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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/example/comp_doc_anonymous_semaphoreB.cpp b/example/comp_doc_anonymous_semaphoreB.cpp index cc5b592..0ee5362 100644 --- a/example/comp_doc_anonymous_semaphoreB.cpp +++ b/example/comp_doc_anonymous_semaphoreB.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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/example/comp_doc_anonymous_upgradable_mutexA.cpp b/example/comp_doc_anonymous_upgradable_mutexA.cpp index a4e2bef..7296990 100644 --- a/example/comp_doc_anonymous_upgradable_mutexA.cpp +++ b/example/comp_doc_anonymous_upgradable_mutexA.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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/example/comp_doc_anonymous_upgradable_mutexB.cpp b/example/comp_doc_anonymous_upgradable_mutexB.cpp index edf4c63..61c1b5a 100644 --- a/example/comp_doc_anonymous_upgradable_mutexB.cpp +++ b/example/comp_doc_anonymous_upgradable_mutexB.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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/example/comp_doc_message_queueA.cpp b/example/comp_doc_message_queueA.cpp index 8efd488..66b0236 100644 --- a/example/comp_doc_message_queueA.cpp +++ b/example/comp_doc_message_queueA.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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/example/comp_doc_message_queueB.cpp b/example/comp_doc_message_queueB.cpp index 3e96643..a3efe29 100644 --- a/example/comp_doc_message_queueB.cpp +++ b/example/comp_doc_message_queueB.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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/example/doc_adaptive_pool.cpp b/example/doc_adaptive_pool.cpp index 2a1feb3..9236ae2 100644 --- a/example/doc_adaptive_pool.cpp +++ b/example/doc_adaptive_pool.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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/example/doc_allocator.cpp b/example/doc_allocator.cpp index febff5e..529715f 100644 --- a/example/doc_allocator.cpp +++ b/example/doc_allocator.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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/example/doc_anonymous_condition_shared_data.hpp b/example/doc_anonymous_condition_shared_data.hpp index 17054db..7cb3104 100644 --- a/example/doc_anonymous_condition_shared_data.hpp +++ b/example/doc_anonymous_condition_shared_data.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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/example/doc_anonymous_mutex_shared_data.hpp b/example/doc_anonymous_mutex_shared_data.hpp index 7458eb5..3884f60 100644 --- a/example/doc_anonymous_mutex_shared_data.hpp +++ b/example/doc_anonymous_mutex_shared_data.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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/example/doc_anonymous_semaphore_shared_data.hpp b/example/doc_anonymous_semaphore_shared_data.hpp index 819f73e..65334f5 100644 --- a/example/doc_anonymous_semaphore_shared_data.hpp +++ b/example/doc_anonymous_semaphore_shared_data.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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/example/doc_anonymous_shared_memory.cpp b/example/doc_anonymous_shared_memory.cpp index 2285f5e..3fb49e1 100644 --- a/example/doc_anonymous_shared_memory.cpp +++ b/example/doc_anonymous_shared_memory.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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) // @@ -23,7 +23,7 @@ int main () //Write all the memory to 1 std::memset(region.get_address(), 1, region.get_size()); - + //The segment is unmapped when "region" goes out of scope } catch(interprocess_exception &ex){ diff --git a/example/doc_bufferstream.cpp b/example/doc_bufferstream.cpp index 310a842..0b51326 100644 --- a/example/doc_bufferstream.cpp +++ b/example/doc_bufferstream.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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) // @@ -93,7 +93,7 @@ int main () //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, m = data.size()*5; i < m; ++i){ mybufstream << data[i%5] << std::endl; diff --git a/example/doc_cached_adaptive_pool.cpp b/example/doc_cached_adaptive_pool.cpp index 421b161..9e92cf5 100644 --- a/example/doc_cached_adaptive_pool.cpp +++ b/example/doc_cached_adaptive_pool.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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/example/doc_cached_node_allocator.cpp b/example/doc_cached_node_allocator.cpp index b89df48..a65559b 100644 --- a/example/doc_cached_node_allocator.cpp +++ b/example/doc_cached_node_allocator.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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/example/doc_complex_map.cpp b/example/doc_complex_map.cpp index 344d6b7..2d40086 100644 --- a/example/doc_complex_map.cpp +++ b/example/doc_complex_map.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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/example/doc_cont.cpp b/example/doc_cont.cpp index f609922..889fc74 100644 --- a/example/doc_cont.cpp +++ b/example/doc_cont.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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/example/doc_file_mapping.cpp b/example/doc_file_mapping.cpp index a3fa06f..4ae3b8f 100644 --- a/example/doc_file_mapping.cpp +++ b/example/doc_file_mapping.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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/example/doc_intrusive.cpp b/example/doc_intrusive.cpp index 7f50e15..d342855 100644 --- a/example/doc_intrusive.cpp +++ b/example/doc_intrusive.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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/example/doc_ipc_message.cpp b/example/doc_ipc_message.cpp index ecc6d14..9e52e9f 100644 --- a/example/doc_ipc_message.cpp +++ b/example/doc_ipc_message.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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/example/doc_managed_aligned_allocation.cpp b/example/doc_managed_aligned_allocation.cpp index e15c569..167f20e 100644 --- a/example/doc_managed_aligned_allocation.cpp +++ b/example/doc_managed_aligned_allocation.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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) // @@ -111,7 +111,7 @@ int main() m_segment.deallocate(ptrs.back()); ptrs.pop_back(); ptrs.push_back(m_segment.allocate_aligned(128, 128)); - } + } return 0; } */ diff --git a/example/doc_managed_allocation_command.cpp b/example/doc_managed_allocation_command.cpp index 18d3012..06da748 100644 --- a/example/doc_managed_allocation_command.cpp +++ b/example/doc_managed_allocation_command.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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/example/doc_managed_construction_info.cpp b/example/doc_managed_construction_info.cpp index 582a001..628608a 100644 --- a/example/doc_managed_construction_info.cpp +++ b/example/doc_managed_construction_info.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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/example/doc_managed_copy_on_write.cpp b/example/doc_managed_copy_on_write.cpp index 1d7d8ba..0b72181 100644 --- a/example/doc_managed_copy_on_write.cpp +++ b/example/doc_managed_copy_on_write.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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) // @@ -81,7 +81,7 @@ int main() { //Now create a read-only version managed_mapped_file managed_file_ro(open_read_only, ManagedFile); - + //Check the original is intact if(!managed_file_ro.find("MyInt").first && managed_file_ro.find("MyInt2").first) throw int(0); diff --git a/example/doc_managed_external_buffer.cpp b/example/doc_managed_external_buffer.cpp index 2847df8..f9d4b58 100644 --- a/example/doc_managed_external_buffer.cpp +++ b/example/doc_managed_external_buffer.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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) // @@ -54,7 +54,7 @@ int main() //from the first one and duplicate all the data. static boost::aligned_storage::type static_buffer2; 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); diff --git a/example/doc_managed_grow.cpp b/example/doc_managed_grow.cpp index e49cbf9..6e1e71d 100644 --- a/example/doc_managed_grow.cpp +++ b/example/doc_managed_grow.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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/example/doc_managed_heap_memory.cpp b/example/doc_managed_heap_memory.cpp index 1d72ce5..976188a 100644 --- a/example/doc_managed_heap_memory.cpp +++ b/example/doc_managed_heap_memory.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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) // @@ -50,7 +50,7 @@ int main () //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) { @@ -61,7 +61,7 @@ int main () //memory is full } - //Let's obtain the new size of the list + //Let's obtain the new size of the list MyList::size_type new_size = mylist->size(); assert(new_size > old_size); diff --git a/example/doc_managed_mapped_file.cpp b/example/doc_managed_mapped_file.cpp index 7b4fac3..723fb3a 100644 --- a/example/doc_managed_mapped_file.cpp +++ b/example/doc_managed_mapped_file.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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) // @@ -25,7 +25,7 @@ typedef list > MyList; int main () -{ +{ //Define file names //<- #if 1 @@ -77,7 +77,7 @@ int main () //so use previously obtained handle to find the new pointer. MyList *mylist = static_cast (mfile_memory.get_address_from_handle(list_handle)); - + //Fill list until there is no more room in the file try{ while(1) { @@ -88,7 +88,7 @@ int main () //mapped file is full } - //Let's obtain the new size of the list + //Let's obtain the new size of the list MyList::size_type new_size = mylist->size(); assert(new_size > old_size); diff --git a/example/doc_managed_multiple_allocation.cpp b/example/doc_managed_multiple_allocation.cpp index a651716..2192d15 100644 --- a/example/doc_managed_multiple_allocation.cpp +++ b/example/doc_managed_multiple_allocation.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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) // @@ -64,8 +64,7 @@ int main() //Initialize our data while(!chain.empty()){ - void *buf = chain.front(); - chain.pop_front(); + void *buf = chain.pop_front(); allocated_buffers.push_back(buf); //The iterator must be incremented before overwriting memory //because otherwise, the iterator is invalidated. diff --git a/example/doc_managed_raw_allocation.cpp b/example/doc_managed_raw_allocation.cpp index 2eb31b5..2ddc997 100644 --- a/example/doc_managed_raw_allocation.cpp +++ b/example/doc_managed_raw_allocation.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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/example/doc_map.cpp b/example/doc_map.cpp index 897047a..929e7bb 100644 --- a/example/doc_map.cpp +++ b/example/doc_map.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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/example/doc_move_containers.cpp b/example/doc_move_containers.cpp index 8158fb6..46438f5 100644 --- a/example/doc_move_containers.cpp +++ b/example/doc_move_containers.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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) // @@ -28,7 +28,7 @@ int main () typedef allocator CharAllocator; typedef basic_string ,CharAllocator> MyShmString; - typedef allocator StringAllocator; + typedef allocator StringAllocator; typedef vector MyShmStringVector; //Remove shared memory on construction and destruction @@ -73,7 +73,7 @@ int main () //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); diff --git a/example/doc_multi_index.cpp b/example/doc_multi_index.cpp index 698f7b9..6845807 100644 --- a/example/doc_multi_index.cpp +++ b/example/doc_multi_index.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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/example/doc_named_alloc.cpp b/example/doc_named_alloc.cpp index 780b50a..99ffbcc 100644 --- a/example/doc_named_alloc.cpp +++ b/example/doc_named_alloc.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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) // @@ -112,12 +112,12 @@ int main(int argc, char *argv[]) std::pair res; //Find the array - res = segment.find ("MyType array"); + res = segment.find ("MyType array"); //Length should be 10 if(res.second != 10) return 1; //Find the object - res = segment.find ("MyType instance"); + res = segment.find ("MyType instance"); //Length should be 1 if(res.second != 1) return 1; diff --git a/example/doc_named_condition_shared_data.hpp b/example/doc_named_condition_shared_data.hpp index 892a4eb..ae94db6 100644 --- a/example/doc_named_condition_shared_data.hpp +++ b/example/doc_named_condition_shared_data.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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/example/doc_named_mutex.cpp b/example/doc_named_mutex.cpp index 5093b2d..98f5b37 100644 --- a/example/doc_named_mutex.cpp +++ b/example/doc_named_mutex.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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) // @@ -77,7 +77,7 @@ int main () //-> for(int i = 0; i < 10; ++i){ - + //Do some operations... //Write to file atomically diff --git a/example/doc_node_allocator.cpp b/example/doc_node_allocator.cpp index a5578d7..dcedab4 100644 --- a/example/doc_node_allocator.cpp +++ b/example/doc_node_allocator.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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/example/doc_offset_ptr.cpp b/example/doc_offset_ptr.cpp index 955b41b..118feab 100644 --- a/example/doc_offset_ptr.cpp +++ b/example/doc_offset_ptr.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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/example/doc_private_adaptive_pool.cpp b/example/doc_private_adaptive_pool.cpp index 7447bf2..3dd854a 100644 --- a/example/doc_private_adaptive_pool.cpp +++ b/example/doc_private_adaptive_pool.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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) // @@ -68,7 +68,7 @@ int main () //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); + assert(allocator_instance != allocator_instance2); //Create another adaptive_pool using copy-constructor. private_adaptive_pool_t allocator_instance3(allocator_instance2); diff --git a/example/doc_private_node_allocator.cpp b/example/doc_private_node_allocator.cpp index 4ef0a45..8a75691 100644 --- a/example/doc_private_node_allocator.cpp +++ b/example/doc_private_node_allocator.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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) // @@ -68,7 +68,7 @@ int main () //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); + assert(allocator_instance != allocator_instance2); //Create another node_allocator using copy-constructor. private_node_allocator_t allocator_instance3(allocator_instance2); diff --git a/example/doc_scoped_ptr.cpp b/example/doc_scoped_ptr.cpp index 1f20af7..b3e3e2e 100644 --- a/example/doc_scoped_ptr.cpp +++ b/example/doc_scoped_ptr.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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) // @@ -86,7 +86,7 @@ int main () my_class * my_object = shmem.construct("my_object")(); my_class * my_object2 = shmem.construct(anonymous_instance)(); shmem.destroy_ptr(my_object2); - + //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 diff --git a/example/doc_shared_memory.cpp b/example/doc_shared_memory.cpp index 24261e5..cb553de 100644 --- a/example/doc_shared_memory.cpp +++ b/example/doc_shared_memory.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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/example/doc_shared_ptr.cpp b/example/doc_shared_ptr.cpp index e44eb05..4e452da 100644 --- a/example/doc_shared_ptr.cpp +++ b/example/doc_shared_ptr.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2011. +// (C) Copyright Ion Gaztanaga 2006-2012. // 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) @@ -128,11 +128,11 @@ int main () //Now destroy the remaining owner. "object to share" will be destroyed file.destroy_ptr(owner2); assert(file.find("object to share").first == 0); - + //Test observer assert(local_observer1.expired()); assert(local_observer1.use_count() == 0); - + //The reference count will be deallocated when all weak pointers //disappear. After that, the file is unmapped. } diff --git a/example/doc_shared_ptr_explicit.cpp b/example/doc_shared_ptr_explicit.cpp index 06a253d..d084d3f 100644 --- a/example/doc_shared_ptr_explicit.cpp +++ b/example/doc_shared_ptr_explicit.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2011. +// (C) Copyright Ion Gaztanaga 2006-2012. // 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) @@ -62,7 +62,7 @@ int main () //<- #endif //-> - + //Create a shared pointer in shared memory //pointing to a newly created object in the segment my_shared_ptr &shared_ptr_instance = diff --git a/example/doc_spawn_vector.cpp b/example/doc_spawn_vector.cpp index 86e60d0..8970527 100644 --- a/example/doc_spawn_vector.cpp +++ b/example/doc_spawn_vector.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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/example/doc_unique_ptr.cpp b/example/doc_unique_ptr.cpp index d9f99f3..c87f798 100644 --- a/example/doc_unique_ptr.cpp +++ b/example/doc_unique_ptr.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2011. +// (C) Copyright Ion Gaztanaga 2006-2012. // 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) @@ -97,11 +97,11 @@ int main () unique_vector->push_back(boost::move(p)); assert(unique_vector->back()->number_ == i); } - + //Now create a list of unique pointers unique_ptr_list_t *unique_list = file.construct("unique list")(file.get_segment_manager()); - + //Pass ownership of all values to the list for(int i = 99; !unique_vector->empty(); --i){ unique_list->push_front(boost::move(unique_vector->back())); @@ -131,7 +131,7 @@ int main () for(int i = 0; i < 100; ++i, ++list_it){ assert((*list_it)->number_ == i); } - + //Now destroy the list. All elements will be automatically deallocated. file.destroy_ptr(unique_list); } diff --git a/example/doc_unordered_map.cpp b/example/doc_unordered_map.cpp index 0d141ef..a834ac1 100644 --- a/example/doc_unordered_map.cpp +++ b/example/doc_unordered_map.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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/example/doc_upgradable_mutex_shared_data.hpp b/example/doc_upgradable_mutex_shared_data.hpp index cc85750..09c5a39 100644 --- a/example/doc_upgradable_mutex_shared_data.hpp +++ b/example/doc_upgradable_mutex_shared_data.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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/example/doc_vectorstream.cpp b/example/doc_vectorstream.cpp index 2d61219..fbfa6c5 100644 --- a/example/doc_vectorstream.cpp +++ b/example/doc_vectorstream.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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/example/doc_where_allocate.cpp b/example/doc_where_allocate.cpp index 0c57a3e..c8f14f1 100644 --- a/example/doc_where_allocate.cpp +++ b/example/doc_where_allocate.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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) // @@ -27,7 +27,7 @@ int main () typedef basic_string, CharAllocator> MyShmString; typedef allocator - StringAllocator; + StringAllocator; typedef vector MyShmStringVector; diff --git a/example/doc_windows_shared_memory.cpp b/example/doc_windows_shared_memory.cpp index 6bffbad..17f1f82 100644 --- a/example/doc_windows_shared_memory.cpp +++ b/example/doc_windows_shared_memory.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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/example/doc_xsi_shared_memory.cpp b/example/doc_xsi_shared_memory.cpp index 3d645c5..bdd878a 100644 --- a/example/doc_xsi_shared_memory.cpp +++ b/example/doc_xsi_shared_memory.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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/include/boost/interprocess/allocators/adaptive_pool.hpp b/include/boost/interprocess/allocators/adaptive_pool.hpp index a85202b..d506af2 100644 --- a/include/boost/interprocess/allocators/adaptive_pool.hpp +++ b/include/boost/interprocess/allocators/adaptive_pool.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -105,7 +105,7 @@ class adaptive_pool_base //!adaptive_pool_base template struct rebind - { + { typedef adaptive_pool_base other; }; @@ -129,8 +129,8 @@ class adaptive_pool_base //!count of the associated node pool. Never throws adaptive_pool_base(const adaptive_pool_base &other) : mp_node_pool(other.get_node_pool()) - { - node_pool<0>::get(ipcdetail::to_raw_pointer(mp_node_pool))->inc_ref_count(); + { + node_pool<0>::get(ipcdetail::to_raw_pointer(mp_node_pool))->inc_ref_count(); } //!Assignment from other adaptive_pool_base @@ -211,7 +211,7 @@ class adaptive_pool_v1 template struct rebind - { + { typedef adaptive_pool_v1 other; }; @@ -271,7 +271,7 @@ class adaptive_pool template struct rebind - { + { typedef adaptive_pool other; }; @@ -303,7 +303,7 @@ class adaptive_pool //!adaptive_pool template struct rebind - { + { typedef adaptive_pool other; }; diff --git a/include/boost/interprocess/allocators/allocator.hpp b/include/boost/interprocess/allocators/allocator.hpp index 38e8c69..a695eac 100644 --- a/include/boost/interprocess/allocators/allocator.hpp +++ b/include/boost/interprocess/allocators/allocator.hpp @@ -1,6 +1,6 @@ /////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -115,7 +115,7 @@ class allocator //!objects of type T2 template struct rebind - { + { typedef allocator other; }; @@ -145,8 +145,9 @@ class allocator pointer allocate(size_type count, cvoid_ptr hint = 0) { (void)hint; - if(count > this->max_size()) + if(size_overflows(count)){ throw bad_alloc(); + } return pointer(static_cast(mp_mngr->allocate(count*sizeof(T)))); } @@ -169,7 +170,7 @@ class allocator //!pointed by p can hold. This size only works for memory allocated with //!allocate, allocation_command and allocate_many. size_type size(const pointer &p) const - { + { return (size_type)mp_mngr->size(ipcdetail::to_raw_pointer(p))/sizeof(T); } @@ -192,7 +193,10 @@ class allocator multiallocation_chain allocate_many (size_type elem_size, size_type num_elements) { - return multiallocation_chain(mp_mngr->allocate_many(sizeof(T)*elem_size, num_elements)); + if(size_overflows(elem_size)){ + throw bad_alloc(); + } + return multiallocation_chain(mp_mngr->allocate_many(elem_size*sizeof(T), num_elements)); } //!Allocates n_elements elements, each one of size elem_sizes[i]in a diff --git a/include/boost/interprocess/allocators/cached_adaptive_pool.hpp b/include/boost/interprocess/allocators/cached_adaptive_pool.hpp index 98af033..6de24c4 100644 --- a/include/boost/interprocess/allocators/cached_adaptive_pool.hpp +++ b/include/boost/interprocess/allocators/cached_adaptive_pool.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -69,7 +69,7 @@ class cached_adaptive_pool_v1 template struct rebind - { + { typedef cached_adaptive_pool_v1 other; }; @@ -149,7 +149,7 @@ class cached_adaptive_pool template struct rebind - { + { typedef cached_adaptive_pool other; }; @@ -183,7 +183,7 @@ class cached_adaptive_pool //!cached_adaptive_pool template struct rebind - { + { typedef cached_adaptive_pool other; }; diff --git a/include/boost/interprocess/allocators/cached_node_allocator.hpp b/include/boost/interprocess/allocators/cached_node_allocator.hpp index b0ad0e4..3cef997 100644 --- a/include/boost/interprocess/allocators/cached_node_allocator.hpp +++ b/include/boost/interprocess/allocators/cached_node_allocator.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -64,7 +64,7 @@ class cached_node_allocator_v1 template struct rebind - { + { typedef cached_node_allocator_v1 other; }; @@ -122,7 +122,7 @@ class cached_node_allocator template struct rebind - { + { typedef cached_node_allocator other; }; @@ -155,7 +155,7 @@ class cached_node_allocator //!cached_node_allocator template struct rebind - { + { typedef cached_node_allocator other; }; diff --git a/include/boost/interprocess/allocators/detail/adaptive_node_pool.hpp b/include/boost/interprocess/allocators/detail/adaptive_node_pool.hpp index abe1831..0dfba0a 100644 --- a/include/boost/interprocess/allocators/detail/adaptive_node_pool.hpp +++ b/include/boost/interprocess/allocators/detail/adaptive_node_pool.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -74,7 +74,7 @@ class private_adaptive_node_pool }; //!Pooled shared memory allocator using adaptive pool. Includes -//!a reference count but the class does not delete itself, this is +//!a reference count but the class does not delete itself, this is //!responsibility of user classes. Node size (NodeSize) and the number of //!nodes allocated per block (NodesPerBlock) are known at compile time template< class SegmentManager diff --git a/include/boost/interprocess/allocators/detail/allocator_common.hpp b/include/boost/interprocess/allocators/detail/allocator_common.hpp index ba14d3f..597da9d 100644 --- a/include/boost/interprocess/allocators/detail/allocator_common.hpp +++ b/include/boost/interprocess/allocators/detail/allocator_common.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2008. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2008-2012. 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) // @@ -73,7 +73,7 @@ namespace ipcdetail { template struct get_or_create_node_pool_func { - + //!This connects or constructs the unique instance of node_pool_t //!Can throw boost::interprocess::bad_alloc void operator()() @@ -90,7 +90,7 @@ struct get_or_create_node_pool_func //!object parameters get_or_create_node_pool_func(typename NodePool::segment_manager *mngr) : mp_segment_manager(mngr){} - + NodePool *mp_node_pool; typename NodePool::segment_manager *mp_segment_manager; }; @@ -118,7 +118,7 @@ struct destroy_if_last_link_func //Last link, let's destroy the segment_manager mp_node_pool->get_segment_manager()->template destroy(boost::interprocess::unique_instance); - } + } //!Constructor. Initializes function //!object parameters @@ -173,7 +173,7 @@ class cache_impl ~cache_impl() { this->deallocate_all_cached_nodes(); - ipcdetail::destroy_node_pool_if_last_link(ipcdetail::to_raw_pointer(mp_node_pool)); + ipcdetail::destroy_node_pool_if_last_link(ipcdetail::to_raw_pointer(mp_node_pool)); } NodePool *get_node_pool() const @@ -191,8 +191,7 @@ class cache_impl if(m_cached_nodes.empty()){ m_cached_nodes = mp_node_pool->allocate_nodes(m_max_cached_nodes/2); } - void *ret = ipcdetail::to_raw_pointer(m_cached_nodes.front()); - m_cached_nodes.pop_front(); + void *ret = ipcdetail::to_raw_pointer(m_cached_nodes.pop_front()); return ret; } @@ -203,8 +202,7 @@ class cache_impl BOOST_TRY{ //If don't have any cached node, we have to get a new list of free nodes from the pool while(!m_cached_nodes.empty() && count--){ - void *ret = ipcdetail::to_raw_pointer(m_cached_nodes.front()); - m_cached_nodes.pop_front(); + void *ret = ipcdetail::to_raw_pointer(m_cached_nodes.pop_front()); chain.push_back(ret); ++allocated; } @@ -335,7 +333,7 @@ class array_allocation_impl //!pointed by p can hold. This size only works for memory allocated with //!allocate, allocation_command and allocate_many. size_type size(const pointer &p) const - { + { return (size_type)this->derived()->get_segment_manager()->size(ipcdetail::to_raw_pointer(p))/sizeof(T); } @@ -357,7 +355,10 @@ class array_allocation_impl //!with deallocate(...) multiallocation_chain allocate_many(size_type elem_size, size_type num_elements) { - return this->derived()->get_segment_manager()->allocate_many(sizeof(T)*elem_size, num_elements); + if(size_overflows(elem_size)){ + throw bad_alloc(); + } + return this->derived()->get_segment_manager()->allocate_many(elem_size*sizeof(T), num_elements); } //!Allocates n_elements elements, each one of size elem_sizes[i]in a @@ -457,14 +458,17 @@ class node_pool_allocation_impl (void)hint; typedef typename node_pool<0>::type node_pool_t; node_pool_t *pool = node_pool<0>::get(this->derived()->get_node_pool()); - if(count > this->max_size()) + if(size_overflows(count)){ throw bad_alloc(); - else if(Version == 1 && count == 1) + } + else if(Version == 1 && count == 1){ return pointer(static_cast (pool->allocate_node())); - else + } + else{ return pointer(static_cast - (pool->get_segment_manager()->allocate(sizeof(T)*count))); + (pool->get_segment_manager()->allocate(count*sizeof(T)))); + } } //!Deallocate allocated memory. Never throws @@ -605,14 +609,15 @@ class cached_allocator_impl { (void)hint; void * ret; - if(count > this->max_size()) + if(size_overflows(count)){ throw bad_alloc(); + } else if(Version == 1 && count == 1){ ret = m_cache.cached_allocation(); } else{ - ret = this->get_segment_manager()->allocate(sizeof(T)*count); - } + ret = this->get_segment_manager()->allocate(count*sizeof(T)); + } return pointer(static_cast(ret)); } @@ -699,7 +704,7 @@ bool operator!=(const cached_allocator_impl &alloc1, //!Pooled shared memory allocator using adaptive pool. Includes -//!a reference count but the class does not delete itself, this is +//!a reference count but the class does not delete itself, this is //!responsibility of user classes. Node size (NodeSize) and the number of //!nodes allocated per block (NodesPerBlock) are known at compile time template @@ -736,7 +741,7 @@ class shared_pool_impl //----------------------- return private_node_allocator_t::allocate_node(); } - + //!Deallocates an array pointed by ptr. Never throws void deallocate_node(void *ptr) { diff --git a/include/boost/interprocess/allocators/detail/node_pool.hpp b/include/boost/interprocess/allocators/detail/node_pool.hpp index 562b648..e67d321 100644 --- a/include/boost/interprocess/allocators/detail/node_pool.hpp +++ b/include/boost/interprocess/allocators/detail/node_pool.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -37,7 +37,7 @@ namespace ipcdetail { //!Pooled shared memory allocator using single segregated storage. Includes -//!a reference count but the class does not delete itself, this is +//!a reference count but the class does not delete itself, this is //!responsibility of user classes. Node size (NodeSize) and the number of //!nodes allocated per block (NodesPerBlock) are known at compile time template< class SegmentManager, std::size_t NodeSize, std::size_t NodesPerBlock > @@ -73,11 +73,11 @@ class private_node_pool //!Pooled shared memory allocator using single segregated storage. Includes -//!a reference count but the class does not delete itself, this is +//!a reference count but the class does not delete itself, this is //!responsibility of user classes. Node size (NodeSize) and the number of //!nodes allocated per block (NodesPerBlock) are known at compile time //!Pooled shared memory allocator using adaptive pool. Includes -//!a reference count but the class does not delete itself, this is +//!a reference count but the class does not delete itself, this is //!responsibility of user classes. Node size (NodeSize) and the number of //!nodes allocated per block (NodesPerBlock) are known at compile time template< class SegmentManager diff --git a/include/boost/interprocess/allocators/detail/node_tools.hpp b/include/boost/interprocess/allocators/detail/node_tools.hpp index da7e466..e9fec38 100644 --- a/include/boost/interprocess/allocators/detail/node_tools.hpp +++ b/include/boost/interprocess/allocators/detail/node_tools.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2007-2012. 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/include/boost/interprocess/allocators/node_allocator.hpp b/include/boost/interprocess/allocators/node_allocator.hpp index 2c1fe56..1f9203d 100644 --- a/include/boost/interprocess/allocators/node_allocator.hpp +++ b/include/boost/interprocess/allocators/node_allocator.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -102,7 +102,7 @@ class node_allocator_base //!node_allocator_base template struct rebind - { + { typedef node_allocator_base other; }; @@ -128,8 +128,8 @@ class node_allocator_base //!count of the associated node pool. Never throws node_allocator_base(const node_allocator_base &other) : mp_node_pool(other.get_node_pool()) - { - node_pool<0>::get(ipcdetail::to_raw_pointer(mp_node_pool))->inc_ref_count(); + { + node_pool<0>::get(ipcdetail::to_raw_pointer(mp_node_pool))->inc_ref_count(); } //!Copy constructor from related node_allocator_base. If not present, constructs @@ -206,7 +206,7 @@ class node_allocator_v1 template struct rebind - { + { typedef node_allocator_v1 other; }; @@ -256,7 +256,7 @@ class node_allocator template struct rebind - { + { typedef node_allocator other; }; @@ -288,7 +288,7 @@ class node_allocator //!node_allocator template struct rebind - { + { typedef node_allocator other; }; diff --git a/include/boost/interprocess/allocators/private_adaptive_pool.hpp b/include/boost/interprocess/allocators/private_adaptive_pool.hpp index febe85c..9a466e4 100644 --- a/include/boost/interprocess/allocators/private_adaptive_pool.hpp +++ b/include/boost/interprocess/allocators/private_adaptive_pool.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -102,7 +102,7 @@ class private_adaptive_pool_base //!Obtains node_allocator from other node_allocator template struct rebind - { + { typedef private_adaptive_pool_base other; }; @@ -210,7 +210,7 @@ class private_adaptive_pool_v1 template struct rebind - { + { typedef private_adaptive_pool_v1 other; }; @@ -269,7 +269,7 @@ class private_adaptive_pool template struct rebind - { + { typedef private_adaptive_pool other; }; @@ -302,7 +302,7 @@ class private_adaptive_pool //!private_adaptive_pool template struct rebind - { + { typedef private_adaptive_pool other; }; diff --git a/include/boost/interprocess/allocators/private_node_allocator.hpp b/include/boost/interprocess/allocators/private_node_allocator.hpp index 46b7dd6..798258d 100644 --- a/include/boost/interprocess/allocators/private_node_allocator.hpp +++ b/include/boost/interprocess/allocators/private_node_allocator.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -97,7 +97,7 @@ class private_node_allocator_base //!Obtains node_allocator from other node_allocator template struct rebind - { + { typedef private_node_allocator_base other; }; @@ -198,7 +198,7 @@ class private_node_allocator_v1 template struct rebind - { + { typedef private_node_allocator_v1 other; }; @@ -246,7 +246,7 @@ class private_node_allocator template struct rebind - { + { typedef private_node_allocator other; }; @@ -279,7 +279,7 @@ class private_node_allocator //!private_node_allocator template struct rebind - { + { typedef private_node_allocator other; }; diff --git a/include/boost/interprocess/anonymous_shared_memory.hpp b/include/boost/interprocess/anonymous_shared_memory.hpp index 624f57f..2eb219a 100644 --- a/include/boost/interprocess/anonymous_shared_memory.hpp +++ b/include/boost/interprocess/anonymous_shared_memory.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -90,13 +90,13 @@ anonymous_shared_memory(std::size_t size, void *address = 0) , 0); if(address == MAP_FAILED){ - if(fd != -1) + if(fd != -1) close(fd); error_info err = system_error_code(); throw interprocess_exception(err); } - if(fd != -1) + if(fd != -1) close(fd); return ipcdetail::raw_mapped_region_creator::create_posix_mapped_region(address, size); diff --git a/include/boost/interprocess/containers/allocation_type.hpp b/include/boost/interprocess/containers/allocation_type.hpp index 660b6cb..eea431b 100644 --- a/include/boost/interprocess/containers/allocation_type.hpp +++ b/include/boost/interprocess/containers/allocation_type.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2008-2012. 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/include/boost/interprocess/containers/containers_fwd.hpp b/include/boost/interprocess/containers/containers_fwd.hpp index 7852bbc..28cd0f1 100644 --- a/include/boost/interprocess/containers/containers_fwd.hpp +++ b/include/boost/interprocess/containers/containers_fwd.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2009. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2009-2012. 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/include/boost/interprocess/containers/deque.hpp b/include/boost/interprocess/containers/deque.hpp index 30ca432..66122e2 100644 --- a/include/boost/interprocess/containers/deque.hpp +++ b/include/boost/interprocess/containers/deque.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2008-2012. 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/include/boost/interprocess/containers/flat_map.hpp b/include/boost/interprocess/containers/flat_map.hpp index f18a006..38b04ac 100644 --- a/include/boost/interprocess/containers/flat_map.hpp +++ b/include/boost/interprocess/containers/flat_map.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2008-2012. 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/include/boost/interprocess/containers/flat_set.hpp b/include/boost/interprocess/containers/flat_set.hpp index 1b2bf9b..45b42fd 100644 --- a/include/boost/interprocess/containers/flat_set.hpp +++ b/include/boost/interprocess/containers/flat_set.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2008-2012. 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/include/boost/interprocess/containers/list.hpp b/include/boost/interprocess/containers/list.hpp index a75b975..50f0ff0 100644 --- a/include/boost/interprocess/containers/list.hpp +++ b/include/boost/interprocess/containers/list.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2008-2012. 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/include/boost/interprocess/containers/map.hpp b/include/boost/interprocess/containers/map.hpp index 2e45ec0..ca00b20 100644 --- a/include/boost/interprocess/containers/map.hpp +++ b/include/boost/interprocess/containers/map.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2008-2012. 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/include/boost/interprocess/containers/pair.hpp b/include/boost/interprocess/containers/pair.hpp index 8ba6d04..65526ab 100644 --- a/include/boost/interprocess/containers/pair.hpp +++ b/include/boost/interprocess/containers/pair.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2008-2012. 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/include/boost/interprocess/containers/set.hpp b/include/boost/interprocess/containers/set.hpp index db06afe..6979204 100644 --- a/include/boost/interprocess/containers/set.hpp +++ b/include/boost/interprocess/containers/set.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2008-2012. 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/include/boost/interprocess/containers/slist.hpp b/include/boost/interprocess/containers/slist.hpp index f93379c..b511d06 100644 --- a/include/boost/interprocess/containers/slist.hpp +++ b/include/boost/interprocess/containers/slist.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2008-2012. 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/include/boost/interprocess/containers/stable_vector.hpp b/include/boost/interprocess/containers/stable_vector.hpp index ae09e6b..4a59b81 100644 --- a/include/boost/interprocess/containers/stable_vector.hpp +++ b/include/boost/interprocess/containers/stable_vector.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2008-2012. 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/include/boost/interprocess/containers/string.hpp b/include/boost/interprocess/containers/string.hpp index a11bb90..e7af2fa 100644 --- a/include/boost/interprocess/containers/string.hpp +++ b/include/boost/interprocess/containers/string.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2008-2012. 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/include/boost/interprocess/containers/vector.hpp b/include/boost/interprocess/containers/vector.hpp index 3a6b411..3f10e01 100644 --- a/include/boost/interprocess/containers/vector.hpp +++ b/include/boost/interprocess/containers/vector.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2008-2012. 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/include/boost/interprocess/containers/version_type.hpp b/include/boost/interprocess/containers/version_type.hpp index 247f800..4516e8c 100644 --- a/include/boost/interprocess/containers/version_type.hpp +++ b/include/boost/interprocess/containers/version_type.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2008-2012. 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/include/boost/interprocess/creation_tags.hpp b/include/boost/interprocess/creation_tags.hpp index 374829a..459eb4d 100644 --- a/include/boost/interprocess/creation_tags.hpp +++ b/include/boost/interprocess/creation_tags.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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/include/boost/interprocess/detail/atomic.hpp b/include/boost/interprocess/detail/atomic.hpp index aab1533..08481a4 100644 --- a/include/boost/interprocess/detail/atomic.hpp +++ b/include/boost/interprocess/detail/atomic.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2011 +// (C) Copyright Ion Gaztanaga 2006-2012 // (C) Copyright Markus Schoepflin 2007 // (C) Copyright Bryce Lelbach 2010 // @@ -390,96 +390,96 @@ inline boost::uint32_t atomic_cas32( } //namespace interprocess{ } //namespace boost{ -#elif defined(__IBMCPP__) && (__IBMCPP__ >= 800) && defined(_AIX) +#elif defined(__IBMCPP__) && (__IBMCPP__ >= 800) && defined(_AIX) -#include +#include -namespace boost { -namespace interprocess { -namespace ipcdetail{ +namespace boost { +namespace interprocess { +namespace ipcdetail{ -//first define boost::uint32_t versions of __lwarx and __stwcx to avoid poluting -//all the functions with casts +//first define boost::uint32_t versions of __lwarx and __stwcx to avoid poluting +//all the functions with casts -//! From XLC documenation : -//! This function can be used with a subsequent stwcxu call to implement a -//! read-modify-write on a specified memory location. The two functions work -//! together to ensure that if the store is successfully performed, no other -//! processor or mechanism can modify the target doubleword between the time -//! lwarxu function is executed and the time the stwcxu functio ncompletes. -//! "mem" : pointer to the object -//! Returns the value at pointed to by mem -inline boost::uint32_t lwarxu(volatile boost::uint32_t *mem) -{ - return static_cast(__lwarx(reinterpret_cast(mem))); -} +//! From XLC documenation : +//! This function can be used with a subsequent stwcxu call to implement a +//! read-modify-write on a specified memory location. The two functions work +//! together to ensure that if the store is successfully performed, no other +//! processor or mechanism can modify the target doubleword between the time +//! lwarxu function is executed and the time the stwcxu functio ncompletes. +//! "mem" : pointer to the object +//! Returns the value at pointed to by mem +inline boost::uint32_t lwarxu(volatile boost::uint32_t *mem) +{ + return static_cast(__lwarx(reinterpret_cast(mem))); +} -//! "mem" : pointer to the object -//! "val" : the value to store -//! Returns true if the update of mem is successful and false if it is -//!unsuccessful -inline bool stwcxu(volatile boost::uint32_t* mem, boost::uint32_t val) -{ - return (__stwcx(reinterpret_cast(mem), static_cast(val)) != 0); -} +//! "mem" : pointer to the object +//! "val" : the value to store +//! Returns true if the update of mem is successful and false if it is +//!unsuccessful +inline bool stwcxu(volatile boost::uint32_t* mem, boost::uint32_t val) +{ + return (__stwcx(reinterpret_cast(mem), static_cast(val)) != 0); +} -//! "mem": pointer to the object -//! "val": amount to add -//! Returns the old value pointed to by mem -inline boost::uint32_t atomic_add32 - (volatile boost::uint32_t *mem, boost::uint32_t val) -{ - boost::uint32_t oldValue; - do - { - oldValue = lwarxu(mem); - }while (!stwcxu(mem, oldValue+val)); - return oldValue; -} +//! "mem": pointer to the object +//! "val": amount to add +//! Returns the old value pointed to by mem +inline boost::uint32_t atomic_add32 + (volatile boost::uint32_t *mem, boost::uint32_t val) +{ + boost::uint32_t oldValue; + do + { + oldValue = lwarxu(mem); + }while (!stwcxu(mem, oldValue+val)); + return oldValue; +} -//! Atomically increment an apr_uint32_t by 1 -//! "mem": pointer to the object -//! Returns the old value pointed to by mem -inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem) -{ return atomic_add32(mem, 1); } +//! Atomically increment an apr_uint32_t by 1 +//! "mem": pointer to the object +//! Returns the old value pointed to by mem +inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem) +{ return atomic_add32(mem, 1); } -//! Atomically decrement an boost::uint32_t by 1 -//! "mem": pointer to the atomic value -//! Returns the old value pointed to by mem -inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem) -{ return atomic_add32(mem, (boost::uint32_t)-1); } +//! Atomically decrement an boost::uint32_t by 1 +//! "mem": pointer to the atomic value +//! Returns the old value pointed to by mem +inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem) +{ return atomic_add32(mem, (boost::uint32_t)-1); } -//! Atomically read an boost::uint32_t from memory -inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem) -{ return *mem; } +//! Atomically read an boost::uint32_t from memory +inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem) +{ return *mem; } -//! Compare an boost::uint32_t's value with "cmp". -//! If they are the same swap the value with "with" -//! "mem": pointer to the value -//! "with" what to swap it with -//! "cmp": the value to compare it to -//! Returns the old value of *mem -inline boost::uint32_t atomic_cas32 - (volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp) -{ - boost::uint32_t oldValue; - boost::uint32_t valueToStore; - do - { - oldValue = lwarxu(mem); - } while (!stwcxu(mem, (oldValue == with) ? cmp : oldValue)); +//! Compare an boost::uint32_t's value with "cmp". +//! If they are the same swap the value with "with" +//! "mem": pointer to the value +//! "with" what to swap it with +//! "cmp": the value to compare it to +//! Returns the old value of *mem +inline boost::uint32_t atomic_cas32 + (volatile boost::uint32_t *mem, boost::uint32_t with, boost::uint32_t cmp) +{ + boost::uint32_t oldValue; + boost::uint32_t valueToStore; + do + { + oldValue = lwarxu(mem); + } while (!stwcxu(mem, (oldValue == with) ? cmp : oldValue)); - return oldValue; -} + return oldValue; +} -//! Atomically set an boost::uint32_t in memory -//! "mem": pointer to the object -//! "param": val value that the object will assume -inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val) -{ *mem = val; } +//! Atomically set an boost::uint32_t in memory +//! "mem": pointer to the object +//! "param": val value that the object will assume +inline void atomic_write32(volatile boost::uint32_t *mem, boost::uint32_t val) +{ *mem = val; } -} //namespace ipcdetail -} //namespace interprocess +} //namespace ipcdetail +} //namespace interprocess } //namespace boost #elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) @@ -552,9 +552,9 @@ inline bool atomic_add_unless32 return c != unless_this; } -} //namespace ipcdetail -} //namespace interprocess -} //namespace boost +} //namespace ipcdetail +} //namespace interprocess +} //namespace boost #include diff --git a/include/boost/interprocess/detail/cast_tags.hpp b/include/boost/interprocess/detail/cast_tags.hpp index bd91d1b..37dabd1 100644 --- a/include/boost/interprocess/detail/cast_tags.hpp +++ b/include/boost/interprocess/detail/cast_tags.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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/include/boost/interprocess/detail/config_begin.hpp b/include/boost/interprocess/detail/config_begin.hpp index a72f6df..9224f7d 100644 --- a/include/boost/interprocess/detail/config_begin.hpp +++ b/include/boost/interprocess/detail/config_begin.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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/include/boost/interprocess/detail/config_end.hpp b/include/boost/interprocess/detail/config_end.hpp index 422458e..f871ce7 100644 --- a/include/boost/interprocess/detail/config_end.hpp +++ b/include/boost/interprocess/detail/config_end.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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/include/boost/interprocess/detail/file_wrapper.hpp b/include/boost/interprocess/detail/file_wrapper.hpp index 586e20d..e139df2 100644 --- a/include/boost/interprocess/detail/file_wrapper.hpp +++ b/include/boost/interprocess/detail/file_wrapper.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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) // @@ -60,10 +60,10 @@ class file_wrapper //!After the call, "moved" does not represent any file. //!Does not throw file_wrapper &operator=(BOOST_RV_REF(file_wrapper) moved) - { + { file_wrapper tmp(boost::move(moved)); this->swap(tmp); - return *this; + return *this; } //!Swaps to file_wrappers. @@ -73,7 +73,7 @@ class file_wrapper //!Erases a file from the system. //!Returns false on error. Never throws static bool remove(const char *name); - + //!Sets the size of the file void truncate(offset_t length); @@ -122,10 +122,10 @@ inline bool file_wrapper::get_size(offset_t &size) const { return get_file_size((file_handle_t)m_handle, size); } inline void file_wrapper::swap(file_wrapper &other) -{ +{ std::swap(m_handle, other.m_handle); std::swap(m_mode, other.m_mode); - m_filename.swap(other.m_filename); + m_filename.swap(other.m_filename); } inline mapping_handle_t file_wrapper::get_mapping_handle() const diff --git a/include/boost/interprocess/detail/in_place_interface.hpp b/include/boost/interprocess/detail/in_place_interface.hpp index b43b2ce..7c0966c 100644 --- a/include/boost/interprocess/detail/in_place_interface.hpp +++ b/include/boost/interprocess/detail/in_place_interface.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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/include/boost/interprocess/detail/intermodule_singleton.hpp b/include/boost/interprocess/detail/intermodule_singleton.hpp index 0543226..9f41ba6 100644 --- a/include/boost/interprocess/detail/intermodule_singleton.hpp +++ b/include/boost/interprocess/detail/intermodule_singleton.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2009-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2009-2012. 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/include/boost/interprocess/detail/intermodule_singleton_common.hpp b/include/boost/interprocess/detail/intermodule_singleton_common.hpp index 0710c0b..ff4069f 100644 --- a/include/boost/interprocess/detail/intermodule_singleton_common.hpp +++ b/include/boost/interprocess/detail/intermodule_singleton_common.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2009-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2009-2012. 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) // @@ -199,7 +199,7 @@ class intermodule_singleton_common private: static ThreadSafeGlobalMap &get_map() { - return *static_cast(static_cast(&mem_holder.map_mem)); + return *static_cast(static_cast(&mem_holder.map_mem[0])); } static void initialize_global_map_handle() @@ -274,7 +274,7 @@ class intermodule_singleton_common //Values: Uninitialized, Initializing, Initialized, Broken static volatile boost::uint32_t this_module_map_initialized; - //Raw memory to construct the global map manager + //Raw memory to construct the global map manager static struct mem_holder_t { ::boost::detail::max_align aligner; @@ -411,7 +411,7 @@ class intermodule_singleton_impl atomic_inc32(&rcount->singleton_ref_count); ret_ptr = rcount->ptr; } - void *data() const + void *data() const { return ret_ptr; } private: @@ -448,7 +448,7 @@ class intermodule_singleton_impl } void *data() const { return ret_ptr; } - + private: ThreadSafeGlobalMap &m_map; void *ret_ptr; diff --git a/include/boost/interprocess/detail/interprocess_tester.hpp b/include/boost/interprocess/detail/interprocess_tester.hpp index 2581776..2fcc07b 100644 --- a/include/boost/interprocess/detail/interprocess_tester.hpp +++ b/include/boost/interprocess/detail/interprocess_tester.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2007-2012. 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/include/boost/interprocess/detail/intersegment_ptr.hpp b/include/boost/interprocess/detail/intersegment_ptr.hpp index 16d3505..ca2ff4a 100644 --- a/include/boost/interprocess/detail/intersegment_ptr.hpp +++ b/include/boost/interprocess/detail/intersegment_ptr.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -177,7 +177,7 @@ struct intersegment_base void set_mode(std::size_t mode) { - BOOST_ASSERT(mode < is_max_mode); + BOOST_ASSERT(mode < is_max_mode); members.direct.ctrl = mode; } @@ -309,13 +309,13 @@ struct flat_map_intersegment void *ptr_base; void *this_base; get_segment_info_and_offset(this, this_info, this_offset, this_base); - + if(!this_info.group){ this->set_mode(is_in_stack); this->members.direct.addr = const_cast(ptr); } else{ - get_segment_info_and_offset(ptr, ptr_info, ptr_offset, ptr_base); + get_segment_info_and_offset(ptr, ptr_info, ptr_offset, ptr_base); if(ptr_info.group != this_info.group){ this->set_mode(is_pointee_outside); @@ -383,7 +383,7 @@ struct flat_map_intersegment }; vector m_segments; multi_segment_services &m_ms_services; - + public: segment_group_t(multi_segment_services &ms_services) : m_ms_services(ms_services) @@ -445,7 +445,7 @@ struct flat_map_intersegment typedef Mutex mutex_type; //!Maps base addresses and segment information //!(size and segment group and id)* - + ptr_to_segment_info_t m_ptr_to_segment_info; ~mappings_t() @@ -486,7 +486,7 @@ struct flat_map_intersegment --it; char * segment_base = const_cast(reinterpret_cast(it->first)); std::size_t segment_size = it->second.size; - + if(segment_base <= reinterpret_cast(ptr) && (segment_base + segment_size) >= reinterpret_cast(ptr)){ segment = it->second; @@ -552,7 +552,7 @@ struct flat_map_intersegment s_groups.insert(segment_group_t(*services)); BOOST_ASSERT(ret.second); return &*ret.first; - } + } } static bool delete_group(segment_group_id id) @@ -574,7 +574,7 @@ struct flat_map_intersegment } } return success; - } + } } }; @@ -663,17 +663,17 @@ class intersegment_ptr : public flat_map_intersegment //!Pointer-like -> operator. It can return 0 pointer. //!Never throws. - pointer operator->() const + pointer operator->() const { return self_t::get(); } //!Dereferencing operator, if it is a null intersegment_ptr behavior //!is undefined. Never throws. - reference operator* () const + reference operator* () const { return *(self_t::get()); } //!Indexing operator. //!Never throws. - reference operator[](std::ptrdiff_t idx) const + reference operator[](std::ptrdiff_t idx) const { return self_t::get()[idx]; } //!Assignment from pointer (saves extra conversion). @@ -690,15 +690,15 @@ class intersegment_ptr : public flat_map_intersegment //!are assignable, intersegment_ptrs will be assignable. Never throws. template intersegment_ptr& operator= (const intersegment_ptr & ptr) - { + { pointer p(ptr.get()); (void)p; - base_t::set_from_other(ptr); return *this; + base_t::set_from_other(ptr); return *this; } //!intersegment_ptr + std::ptrdiff_t. //!Never throws. - intersegment_ptr operator+ (std::ptrdiff_t idx) const - { + intersegment_ptr operator+ (std::ptrdiff_t idx) const + { intersegment_ptr result (*this); result.inc_offset(idx*sizeof(T)); return result; @@ -706,8 +706,8 @@ class intersegment_ptr : public flat_map_intersegment //!intersegment_ptr - std::ptrdiff_t. //!Never throws. - intersegment_ptr operator- (std::ptrdiff_t idx) const - { + intersegment_ptr operator- (std::ptrdiff_t idx) const + { intersegment_ptr result (*this); result.dec_offset(idx*sizeof(T)); return result; @@ -745,7 +745,7 @@ class intersegment_ptr : public flat_map_intersegment //!Safe bool conversion operator. //!Never throws. - operator unspecified_bool_type() const + operator unspecified_bool_type() const { return base_t::is_null()? 0 : &self_t::unspecified_bool_type_func; } //!Not operator. Not needed in theory, but improves portability. @@ -784,12 +784,12 @@ class intersegment_ptr : public flat_map_intersegment template inline bool operator ==(const intersegment_ptr &left, const intersegment_ptr &right) -{ +{ //Make sure both pointers can be compared bool e = typename intersegment_ptr::pointer(0) == typename intersegment_ptr::pointer(0); (void)e; - return left._equal(right); + return left._equal(right); } //!Returns true if *this is less than other. @@ -798,12 +798,12 @@ bool operator ==(const intersegment_ptr &left, template inline bool operator <(const intersegment_ptr &left, const intersegment_ptr &right) -{ +{ //Make sure both pointers can be compared bool e = typename intersegment_ptr::pointer(0) < typename intersegment_ptr::pointer(0); (void)e; - return left._less(right); + return left._less(right); } template inline diff --git a/include/boost/interprocess/detail/managed_memory_impl.hpp b/include/boost/interprocess/detail/managed_memory_impl.hpp index f9ecb8a..4161d30 100644 --- a/include/boost/interprocess/detail/managed_memory_impl.hpp +++ b/include/boost/interprocess/detail/managed_memory_impl.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -172,14 +172,14 @@ class basic_managed_memory_impl //This function should not throw. The index construction can //throw if constructor allocates memory. So we must catch it. BOOST_TRY{ - //Let's construct the allocator in memory + //Let's construct the allocator in memory mp_header = new(addr) segment_manager(size); } BOOST_CATCH(...){ return false; } BOOST_CATCH_END - return true; + return true; } //!Connects to a segment manager in the reserved buffer. Never throws. @@ -192,7 +192,7 @@ class basic_managed_memory_impl //!Frees resources. Never throws. bool close_impl() - { + { bool ret = mp_header != 0; mp_header = 0; return ret; @@ -254,12 +254,12 @@ class basic_managed_memory_impl handle_t get_handle_from_address (const void *ptr) const { return (handle_t)(reinterpret_cast(ptr) - - reinterpret_cast(this->get_address())); + reinterpret_cast(this->get_address())); } //!Returns true if the address belongs to the managed memory segment bool belongs_to_segment (const void *ptr) const - { + { return ptr >= this->get_address() && ptr < (reinterpret_cast(this->get_address()) + this->get_size()); } @@ -292,7 +292,7 @@ class basic_managed_memory_impl allocation_command (boost::interprocess::allocation_type command, size_type limit_size, size_type preferred_size,size_type &received_size, T *reuse_ptr = 0) - { + { return mp_header->allocation_command (command, limit_size, preferred_size, received_size, reuse_ptr); } @@ -724,7 +724,7 @@ class create_open_func : m_frontend(frontend), m_type(type){} bool operator()(void *addr, typename BasicManagedMemoryImpl::size_type size, bool created) const - { + { if(((m_type == DoOpen) && created) || ((m_type == DoCreate) && !created)) return false; diff --git a/include/boost/interprocess/detail/managed_multi_shared_memory.hpp b/include/boost/interprocess/detail/managed_multi_shared_memory.hpp index 654c8bb..cd7ed9c 100644 --- a/include/boost/interprocess/detail/managed_multi_shared_memory.hpp +++ b/include/boost/interprocess/detail/managed_multi_shared_memory.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -36,7 +36,7 @@ #include //These includes needed to fulfill default template parameters of //predeclarations in interprocess_fwd.hpp -#include +#include #include //!\file @@ -69,7 +69,7 @@ class basic_managed_multi_shared_memory self_t; typedef ipcdetail::basic_managed_memory_impl base_t; - + typedef typename MemoryAlgorithm::void_pointer void_pointer; typedef typename ipcdetail:: managed_open_or_create_impl managed_impl; @@ -100,7 +100,7 @@ class basic_managed_multi_shared_memory // if(!m_shmem.create(m_mem_name, size, m_addr)) // return 0; // return m_shmem.get_address(); -// } +// } // private: // shared_memory &m_shmem; // const char *m_mem_name; @@ -134,7 +134,7 @@ class basic_managed_multi_shared_memory typename shmem_list_t::value_type &m_impl = *mp_frontend->m_shmem_list.rbegin(); return result_type(m_impl.get_real_address(), m_impl.get_real_size()-1); }*/ - return result_type(static_cast(0), 0); + return result_type(static_cast(0), 0); } virtual bool update_segments () @@ -174,7 +174,7 @@ class basic_managed_multi_shared_memory : mp_frontend(frontend), m_type(type), m_segment_number(segment_number){} bool operator()(void *addr, size_type size, bool created) const - { + { if(((m_type == DoOpen) && created) || ((m_type == DoCreate) && !created)) return false; @@ -226,7 +226,7 @@ class basic_managed_multi_shared_memory : mp_frontend(frontend){} void operator()(const mapped_region ®ion, bool last) const - { + { if(last) mp_frontend->destroy_impl(); else mp_frontend->close_impl(); } @@ -251,7 +251,7 @@ class basic_managed_multi_shared_memory const permissions &perm = permissions()) : m_group_services(get_this_pointer()) { - priv_open_or_create(create_open_func::DoCreate,name, size, perm); + priv_open_or_create(create_open_func::DoCreate,name, size, perm); } basic_managed_multi_shared_memory(open_or_create_t, @@ -301,7 +301,7 @@ class basic_managed_multi_shared_memory if(group){ void_pointer::delete_group(group); } - return false; + return false; } bool priv_new_segment(typename create_open_func::type_t type, @@ -368,7 +368,7 @@ class basic_managed_multi_shared_memory //!Frees resources. Never throws. void priv_close() - { + { if(!m_shmem_list.empty()){ bool ret; //Obtain group identifier @@ -385,7 +385,7 @@ class basic_managed_multi_shared_memory m_shmem_list.clear(); } } - + private: shmem_list_t m_shmem_list; group_services m_group_services; diff --git a/include/boost/interprocess/detail/managed_open_or_create_impl.hpp b/include/boost/interprocess/detail/managed_open_or_create_impl.hpp index a4f1f15..06d986b 100644 --- a/include/boost/interprocess/detail/managed_open_or_create_impl.hpp +++ b/include/boost/interprocess/detail/managed_open_or_create_impl.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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) // @@ -48,12 +48,12 @@ class xsi_key; template<> struct managed_open_or_create_impl_device_id_t -{ +{ typedef xsi_key type; }; #endif //BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS - + /// @endcond namespace ipcdetail { @@ -79,7 +79,7 @@ class managed_open_or_create_impl_device_holder const DeviceAbstraction &get_device() const { return dev; } - + private: DeviceAbstraction dev; }; @@ -94,9 +94,9 @@ class managed_open_or_create_impl typedef typename managed_open_or_create_impl_device_id_t::type device_id_t; typedef managed_open_or_create_impl_device_holder DevHolder; enum - { - UninitializedSegment, - InitializingSegment, + { + UninitializedSegment, + InitializingSegment, InitializedSegment, CorruptedSegment }; @@ -222,10 +222,10 @@ class managed_open_or_create_impl { this->swap(moved); } managed_open_or_create_impl &operator=(BOOST_RV_REF(managed_open_or_create_impl) moved) - { + { managed_open_or_create_impl tmp(boost::move(moved)); this->swap(tmp); - return *this; + return *this; } ~managed_open_or_create_impl() diff --git a/include/boost/interprocess/detail/math_functions.hpp b/include/boost/interprocess/detail/math_functions.hpp index 2fc457c..20922b3 100644 --- a/include/boost/interprocess/detail/math_functions.hpp +++ b/include/boost/interprocess/detail/math_functions.hpp @@ -1,7 +1,7 @@ ////////////////////////////////////////////////////////////////////////////// // // (C) Copyright Stephen Cleary 2000. -// (C) Copyright Ion Gaztanaga 2007-2011. +// (C) Copyright Ion Gaztanaga 2007-2012. // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -93,7 +93,7 @@ inline std::size_t floor_log2 (std::size_t x) std::size_t n = x; std::size_t log2 = 0; - + for(std::size_t shift = Bits >> 1; shift; shift >>= 1){ std::size_t tmp = n >> shift; if (tmp) diff --git a/include/boost/interprocess/detail/min_max.hpp b/include/boost/interprocess/detail/min_max.hpp index 1f4ebdf..63ce7ef 100644 --- a/include/boost/interprocess/detail/min_max.hpp +++ b/include/boost/interprocess/detail/min_max.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. +// (C) Copyright Ion Gaztanaga 2005-2012. // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/include/boost/interprocess/detail/move.hpp b/include/boost/interprocess/detail/move.hpp index 1ec43b2..87684f6 100644 --- a/include/boost/interprocess/detail/move.hpp +++ b/include/boost/interprocess/detail/move.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2010-2011. +// (C) Copyright Ion Gaztanaga 2010-2012. // 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/include/boost/interprocess/detail/mpl.hpp b/include/boost/interprocess/detail/mpl.hpp index e2c7f52..4c5e1f1 100644 --- a/include/boost/interprocess/detail/mpl.hpp +++ b/include/boost/interprocess/detail/mpl.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. +// (C) Copyright Ion Gaztanaga 2005-2012. // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/include/boost/interprocess/detail/multi_segment_services.hpp b/include/boost/interprocess/detail/multi_segment_services.hpp index d1451d3..f625a9b 100644 --- a/include/boost/interprocess/detail/multi_segment_services.hpp +++ b/include/boost/interprocess/detail/multi_segment_services.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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/include/boost/interprocess/detail/named_proxy.hpp b/include/boost/interprocess/detail/named_proxy.hpp index c2aafed..14a9aa0 100644 --- a/include/boost/interprocess/detail/named_proxy.hpp +++ b/include/boost/interprocess/detail/named_proxy.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -93,7 +93,7 @@ struct CtorNArg : public placement_destroy {} tuple args_; -}; +}; //!Describes a proxy class that implements named //!allocation syntax. @@ -119,7 +119,7 @@ class named_proxy template T *operator()(Args &&...args) const - { + { CtorNArg &&ctor_obj = CtorNArg (boost::forward(args)...); return mp_mngr->template @@ -199,7 +199,7 @@ struct Ctor0Arg : public placement_destroy // private: // void construct(void *mem, true_) // { new((void*)mem)T(*m_p1, *m_p2); } -// +// // void construct(void *mem, false_) // { new((void*)mem)T(m_p1, m_p2); } // @@ -293,7 +293,7 @@ class named_proxy //!makes a named allocation and calls the //!default constructor T *operator()() const - { + { Ctor0Arg ctor_obj; return mp_mngr->template generic_construct(mp_name, m_num, m_find, m_dothrow, ctor_obj); diff --git a/include/boost/interprocess/detail/os_file_functions.hpp b/include/boost/interprocess/detail/os_file_functions.hpp index 08decd9..840079d 100644 --- a/include/boost/interprocess/detail/os_file_functions.hpp +++ b/include/boost/interprocess/detail/os_file_functions.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -96,28 +96,28 @@ inline const char *get_temporary_path() inline file_handle_t create_new_file (const char *name, mode_t mode, const permissions & perm = permissions(), bool temporary = false) -{ +{ unsigned long attr = temporary ? winapi::file_attribute_temporary : 0; return winapi::create_file ( name, (unsigned int)mode, winapi::create_new, attr - , (winapi::interprocess_security_attributes*)perm.get_permissions()); + , (winapi::interprocess_security_attributes*)perm.get_permissions()); } inline file_handle_t create_or_open_file (const char *name, mode_t mode, const permissions & perm = permissions(), bool temporary = false) -{ +{ unsigned long attr = temporary ? winapi::file_attribute_temporary : 0; return winapi::create_file ( name, (unsigned int)mode, winapi::open_always, attr - , (winapi::interprocess_security_attributes*)perm.get_permissions()); + , (winapi::interprocess_security_attributes*)perm.get_permissions()); } inline file_handle_t open_existing_file (const char *name, mode_t mode, bool temporary = false) -{ +{ unsigned long attr = temporary ? winapi::file_attribute_temporary : 0; return winapi::create_file - (name, (unsigned int)mode, winapi::open_existing, attr, 0); + (name, (unsigned int)mode, winapi::open_existing, attr, 0); } inline bool delete_file(const char *name) @@ -177,7 +177,7 @@ inline bool get_file_pointer(file_handle_t hnd, offset_t &off) { return winapi::set_file_pointer_ex(hnd, 0, &off, winapi::file_current); } inline bool write_file(file_handle_t hnd, const void *data, std::size_t numdata) -{ +{ unsigned long written; return 0 != winapi::write_file(hnd, data, (unsigned long)numdata, &written, 0); } @@ -189,9 +189,9 @@ inline bool close_file(file_handle_t hnd) { return 0 != winapi::close_handle(hnd); } inline bool acquire_file_lock(file_handle_t hnd) -{ +{ static winapi::interprocess_overlapped overlapped; - const unsigned long len = ~((unsigned long)(0u)); + const unsigned long len = ((unsigned long)-1); // winapi::interprocess_overlapped overlapped; // std::memset(&overlapped, 0, sizeof(overlapped)); return winapi::lock_file_ex @@ -199,8 +199,8 @@ inline bool acquire_file_lock(file_handle_t hnd) } inline bool try_acquire_file_lock(file_handle_t hnd, bool &acquired) -{ - const unsigned long len = ~((unsigned long)(0u)); +{ + const unsigned long len = ((unsigned long)-1); winapi::interprocess_overlapped overlapped; std::memset(&overlapped, 0, sizeof(overlapped)); if(!winapi::lock_file_ex @@ -208,30 +208,30 @@ inline bool try_acquire_file_lock(file_handle_t hnd, bool &acquired) 0, len, len, &overlapped)){ return winapi::get_last_error() == winapi::error_lock_violation ? acquired = false, true : false; - + } return (acquired = true); } inline bool release_file_lock(file_handle_t hnd) -{ - const unsigned long len = ~((unsigned long)(0u)); +{ + const unsigned long len = ((unsigned long)-1); winapi::interprocess_overlapped overlapped; std::memset(&overlapped, 0, sizeof(overlapped)); return winapi::unlock_file_ex(hnd, 0, len, len, &overlapped); } inline bool acquire_file_lock_sharable(file_handle_t hnd) -{ - const unsigned long len = ~((unsigned long)(0u)); +{ + const unsigned long len = ((unsigned long)-1); winapi::interprocess_overlapped overlapped; std::memset(&overlapped, 0, sizeof(overlapped)); return winapi::lock_file_ex(hnd, 0, 0, len, len, &overlapped); } inline bool try_acquire_file_lock_sharable(file_handle_t hnd, bool &acquired) -{ - const unsigned long len = ~((unsigned long)(0u)); +{ + const unsigned long len = ((unsigned long)-1); winapi::interprocess_overlapped overlapped; std::memset(&overlapped, 0, sizeof(overlapped)); if(!winapi::lock_file_ex @@ -406,7 +406,7 @@ inline const char *get_temporary_path() inline file_handle_t create_new_file (const char *name, mode_t mode, const permissions & perm = permissions(), bool temporary = false) -{ +{ (void)temporary; int ret = ::open(name, ((int)mode) | O_EXCL | O_CREAT, perm.get_permissions()); if(ret >= 0){ @@ -439,7 +439,7 @@ inline file_handle_t create_or_open_file inline file_handle_t open_existing_file (const char *name, mode_t mode, bool temporary = false) -{ +{ (void)temporary; return ::open(name, (int)mode); } @@ -459,7 +459,7 @@ inline bool truncate_file (file_handle_t hnd, std::size_t size) } inline bool get_file_size(file_handle_t hnd, offset_t &size) -{ +{ struct stat data; bool ret = 0 == ::fstat(hnd, &data); if(ret){ @@ -472,7 +472,7 @@ inline bool set_file_pointer(file_handle_t hnd, offset_t off, file_pos_t pos) { return ((off_t)(-1)) != ::lseek(hnd, off, (int)pos); } inline bool get_file_pointer(file_handle_t hnd, offset_t &off) -{ +{ off = ::lseek(hnd, 0, SEEK_CUR); return off != ((off_t)-1); } @@ -522,7 +522,7 @@ inline bool release_file_lock(file_handle_t hnd) } inline bool acquire_file_lock_sharable(file_handle_t hnd) -{ +{ struct ::flock lock; lock.l_type = F_RDLCK; lock.l_whence = SEEK_SET; @@ -532,7 +532,7 @@ inline bool acquire_file_lock_sharable(file_handle_t hnd) } inline bool try_acquire_file_lock_sharable(file_handle_t hnd, bool &acquired) -{ +{ struct flock lock; lock.l_type = F_RDLCK; lock.l_whence = SEEK_SET; @@ -601,7 +601,7 @@ inline bool delete_subdirectories_recursive || (de->d_name[1] == '.' && de->d_name[2] == '\0' )) ){ continue; } - if(dont_delete_this && std::strcmp(dont_delete_this, de->d_name) == 0){ + if(dont_delete_this && std::strcmp(dont_delete_this, de->d_name) == 0){ continue; } fn = refcstrRootDirectory; diff --git a/include/boost/interprocess/detail/os_thread_functions.hpp b/include/boost/interprocess/detail/os_thread_functions.hpp index 8d769fc..f881a1f 100644 --- a/include/boost/interprocess/detail/os_thread_functions.hpp +++ b/include/boost/interprocess/detail/os_thread_functions.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -104,7 +104,7 @@ typedef pthread_t OS_thread_id_t; typedef pid_t OS_process_id_t; struct OS_systemwide_thread_id_t -{ +{ OS_systemwide_thread_id_t() : pid(), tid() {} diff --git a/include/boost/interprocess/detail/pointer_type.hpp b/include/boost/interprocess/detail/pointer_type.hpp index 549b23f..aa8da55 100644 --- a/include/boost/interprocess/detail/pointer_type.hpp +++ b/include/boost/interprocess/detail/pointer_type.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. +// (C) Copyright Ion Gaztanaga 2005-2012. // (C) Copyright Gennaro Prota 2003 - 2004. // // Distributed under the Boost Software License, Version 1.0. diff --git a/include/boost/interprocess/detail/portable_intermodule_singleton.hpp b/include/boost/interprocess/detail/portable_intermodule_singleton.hpp index eb2a13e..d5c84d4 100644 --- a/include/boost/interprocess/detail/portable_intermodule_singleton.hpp +++ b/include/boost/interprocess/detail/portable_intermodule_singleton.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2009-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2009-2012. 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) // @@ -54,7 +54,7 @@ static void create_tmp_subdir_and_get_pid_based_filepath s += "/"; s += file_prefix; if(creation_time){ - std::string sstamp; + std::string sstamp; get_pid_creation_time_str(sstamp); s += sstamp; } @@ -137,7 +137,7 @@ struct thread_safe_global_map_dependant delete_file(singleton_lock_file_path_); shared_memory_object::remove(shm_name_); } - + const char * const shm_name_; const char * const singleton_lock_file_path_; managed_global_memory & shm_; diff --git a/include/boost/interprocess/detail/posix_time_types_wrk.hpp b/include/boost/interprocess/detail/posix_time_types_wrk.hpp index e4df85a..fa167f5 100644 --- a/include/boost/interprocess/detail/posix_time_types_wrk.hpp +++ b/include/boost/interprocess/detail/posix_time_types_wrk.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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/include/boost/interprocess/detail/preprocessor.hpp b/include/boost/interprocess/detail/preprocessor.hpp index 47b591c..431e96e 100644 --- a/include/boost/interprocess/detail/preprocessor.hpp +++ b/include/boost/interprocess/detail/preprocessor.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2008-2012. 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) // @@ -57,21 +57,10 @@ #ifndef BOOST_NO_RVALUE_REFERENCES - #if defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG) - - #define BOOST_INTERPROCESS_PP_PARAM_INIT(z, n, data) \ - BOOST_PP_CAT(m_p, n) (BOOST_PP_CAT(p, n)) \ - //! - - - #else //#if defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG) - #define BOOST_INTERPROCESS_PP_PARAM_INIT(z, n, data) \ BOOST_PP_CAT(m_p, n) (::boost::forward< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(p, n) )) \ //! - #endif //#if defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG) - #else //#ifndef BOOST_NO_RVALUE_REFERENCES #define BOOST_INTERPROCESS_PP_PARAM_INIT(z, n, data) \ @@ -79,31 +68,104 @@ //! #endif -#define BOOST_INTERPROCESS_PP_PARAM_INC(z, n, data) \ - BOOST_PP_CAT(++m_p, n) \ -//! - #ifndef BOOST_NO_RVALUE_REFERENCES -#if defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG) + #if defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG) -#define BOOST_INTERPROCESS_PP_PARAM_DEFINE(z, n, data) \ - BOOST_PP_CAT(P, n) & BOOST_PP_CAT(m_p, n); \ -//! + namespace boost { + namespace interprocess { + namespace ipcdetail { + template + struct ref_holder; + + template + struct ref_holder + { + ref_holder(T &t) + : t_(t) + {} + T &t_; + T & get() { return t_; } + T & get_lvalue() { return t_; } + }; + + template + struct ref_holder + { + ref_holder(const T &t) + : t_(t) + {} + const T &t_; + const T & get() { return t_; } + const T & get_lvalue() { return t_; } + }; + + template + struct ref_holder + { + ref_holder(const T &t) + : t_(t) + {} + const T &t_; + const T & get() { return t_; } + const T & get_lvalue() { return t_; } + }; + + template + struct ref_holder + { + ref_holder(T &&t) + : t_(t) + {} + T &t_; + T && get() { return ::boost::move(t_); } + T & get_lvalue() { return t_; } + }; + + template + struct ref_holder + { + ref_holder(T &&t) + : t(t) + {} + T &t; + T && get() { return ::boost::move(t_); } + T & get_lvalue() { return t_; } + }; + + } //namespace ipcdetail { + } //namespace interprocess { + } //namespace boost { + + #define BOOST_INTERPROCESS_PP_PARAM_DEFINE(z, n, data) \ + ::boost::interprocess::ipcdetail::ref_holder BOOST_PP_CAT(m_p, n); \ + //! + + #define BOOST_INTERPROCESS_PP_PARAM_INC(z, n, data) \ + BOOST_PP_CAT(++m_p, n).get_lvalue() \ + //! + + #else //BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG + + #define BOOST_INTERPROCESS_PP_PARAM_DEFINE(z, n, data)\ + BOOST_PP_CAT(P, n) && BOOST_PP_CAT(m_p, n); \ + //! + + #define BOOST_INTERPROCESS_PP_PARAM_INC(z, n, data) \ + BOOST_PP_CAT(++m_p, n) \ + //! + + #endif //defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG) #else + #define BOOST_INTERPROCESS_PP_PARAM_DEFINE(z, n, data) \ + BOOST_PP_CAT(P, n) & BOOST_PP_CAT(m_p, n); \ + //! -#define BOOST_INTERPROCESS_PP_PARAM_DEFINE(z, n, data) \ - BOOST_PP_CAT(P, n) && BOOST_PP_CAT(m_p, n); \ -//! + #define BOOST_INTERPROCESS_PP_PARAM_INC(z, n, data) \ + BOOST_PP_CAT(++m_p, n) \ + //! -#endif //defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG) - - -#else -#define BOOST_INTERPROCESS_PP_PARAM_DEFINE(z, n, data) \ - BOOST_PP_CAT(P, n) & BOOST_PP_CAT(m_p, n); \ -//! #endif #define BOOST_INTERPROCESS_PP_PARAM_FORWARD(z, n, data) \ @@ -112,24 +174,26 @@ #if !defined(BOOST_NO_RVALUE_REFERENCES) && defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG) -#include + #define BOOST_INTERPROCESS_PP_MEMBER_FORWARD(z, n, data) BOOST_PP_CAT(this->m_p, n).get() \ + //! -#define BOOST_INTERPROCESS_PP_MEMBER_FORWARD(z, n, data) \ -::boost::container::container_detail::stored_ref< BOOST_PP_CAT(P, n) >::forward( BOOST_PP_CAT(m_p, n) ) \ -//! + #define BOOST_INTERPROCESS_PP_MEMBER_IT_FORWARD(z, n, data) \ + BOOST_PP_CAT(*m_p, n).get_lvalue() \ + //! #else -#define BOOST_INTERPROCESS_PP_MEMBER_FORWARD(z, n, data) \ -::boost::forward< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(m_p, n) ) \ -//! + #define BOOST_INTERPROCESS_PP_MEMBER_FORWARD(z, n, data) \ + ::boost::forward< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(m_p, n) ) \ + //! + + #define BOOST_INTERPROCESS_PP_MEMBER_IT_FORWARD(z, n, data) \ + BOOST_PP_CAT(*m_p, n) \ + //! + #endif //!defined(BOOST_NO_RVALUE_REFERENCES) && defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG) -#define BOOST_INTERPROCESS_PP_MEMBER_IT_FORWARD(z, n, data) \ -BOOST_PP_CAT(*m_p, n) \ -//! - #include #else diff --git a/include/boost/interprocess/detail/ptime_wrk.hpp b/include/boost/interprocess/detail/ptime_wrk.hpp index 8cda3a4..63d9915 100644 --- a/include/boost/interprocess/detail/ptime_wrk.hpp +++ b/include/boost/interprocess/detail/ptime_wrk.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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/include/boost/interprocess/detail/robust_emulation.hpp b/include/boost/interprocess/detail/robust_emulation.hpp index 1feb42d..9fd2229 100644 --- a/include/boost/interprocess/detail/robust_emulation.hpp +++ b/include/boost/interprocess/detail/robust_emulation.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2010-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2010-2012. 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) // @@ -132,7 +132,7 @@ class robust_mutex_lock_file throw interprocess_exception(other_error, "Robust emulation robust_mutex_lock_file constructor failed: create_file filed with unexpected error"); } } - } + } ~robust_mutex_lock_file() { @@ -324,7 +324,7 @@ inline bool robust_spin_mutex::robust_check() return false; } atomic_write32(&this->state, fixing_state); - return true; + return true; } template diff --git a/include/boost/interprocess/detail/segment_manager_helper.hpp b/include/boost/interprocess/detail/segment_manager_helper.hpp index 2b715d8..2325cd3 100644 --- a/include/boost/interprocess/detail/segment_manager_helper.hpp +++ b/include/boost/interprocess/detail/segment_manager_helper.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -130,7 +130,7 @@ struct block_header template CharType *name() const - { + { return const_cast(reinterpret_cast (reinterpret_cast(this) + name_offset())); } @@ -175,7 +175,7 @@ struct block_header { return block_header_from_value(value, sizeof(T), ::boost::alignment_of::value); } static block_header *block_header_from_value(const void *value, std::size_t sz, std::size_t algn) - { + { block_header * hdr = const_cast (reinterpret_cast(reinterpret_cast(value) - @@ -189,7 +189,7 @@ struct block_header template static block_header *from_first_header(Header *header) - { + { block_header * hdr = reinterpret_cast*>(reinterpret_cast(header) + get_rounded_size(size_type(sizeof(Header)), size_type(::boost::alignment_of >::value))); @@ -199,7 +199,7 @@ struct block_header template static Header *to_first_header(block_header *bheader) - { + { Header * hdr = reinterpret_cast(reinterpret_cast(bheader) - get_rounded_size(size_type(sizeof(Header)), size_type(::boost::alignment_of >::value))); @@ -478,7 +478,7 @@ struct segment_manager_iterator_transform , segment_manager_iterator_value_adaptor > { typedef segment_manager_iterator_value_adaptor result_type; - + result_type operator()(const typename Iterator::value_type &arg) const { return result_type(arg); } }; diff --git a/include/boost/interprocess/detail/tmp_dir_helpers.hpp b/include/boost/interprocess/detail/tmp_dir_helpers.hpp index 28e7341..e4e867e 100644 --- a/include/boost/interprocess/detail/tmp_dir_helpers.hpp +++ b/include/boost/interprocess/detail/tmp_dir_helpers.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2007-2012. 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/include/boost/interprocess/detail/transform_iterator.hpp b/include/boost/interprocess/detail/transform_iterator.hpp index 922c875..56bd0e5 100644 --- a/include/boost/interprocess/detail/transform_iterator.hpp +++ b/include/boost/interprocess/detail/transform_iterator.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. +// (C) Copyright Ion Gaztanaga 2005-2012. // (C) Copyright Gennaro Prota 2003 - 2004. // // Distributed under the Boost Software License, Version 1.0. diff --git a/include/boost/interprocess/detail/type_traits.hpp b/include/boost/interprocess/detail/type_traits.hpp index 7a582fe..ade623f 100644 --- a/include/boost/interprocess/detail/type_traits.hpp +++ b/include/boost/interprocess/detail/type_traits.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // (C) Copyright John Maddock 2000. -// (C) Copyright Ion Gaztanaga 2005-2011. +// (C) Copyright Ion Gaztanaga 2005-2012. // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -117,6 +117,12 @@ struct remove_volatile typedef T type; }; +template +struct remove_const_volatile +{ + typedef typename remove_const::type>::type type; +}; + template struct is_same { @@ -136,6 +142,13 @@ struct is_same static const bool value = sizeof(yes_type) == sizeof(is_same_tester(t,u)); }; +template +struct is_cv_same +{ + static const bool value = is_same< typename remove_const_volatile::type + , typename remove_const_volatile::type >::value; +}; + } // namespace ipcdetail } //namespace interprocess { } //namespace boost { diff --git a/include/boost/interprocess/detail/utilities.hpp b/include/boost/interprocess/detail/utilities.hpp index fcb211f..3b486dd 100644 --- a/include/boost/interprocess/detail/utilities.hpp +++ b/include/boost/interprocess/detail/utilities.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. +// (C) Copyright Ion Gaztanaga 2005-2012. // (C) Copyright Gennaro Prota 2003 - 2004. // // Distributed under the Boost Software License, Version 1.0. @@ -31,8 +31,10 @@ #include #include #include +#include #include #include +#include namespace boost { namespace interprocess { @@ -86,7 +88,10 @@ inline SizeType get_truncated_size_po2(SizeType orig_size, SizeType multiple) template struct ct_rounded_size { - static const std::size_t value = ((OrigSize-1)/RoundTo+1)*RoundTo; + BOOST_STATIC_ASSERT((RoundTo != 0)); + static const std::size_t intermediate_value = (OrigSize-1)/RoundTo+1; + BOOST_STATIC_ASSERT(intermediate_value <= std::size_t(-1)/RoundTo); + static const std::size_t value = intermediate_value*RoundTo; }; // Gennaro Prota wrote this. Thanks! @@ -133,6 +138,59 @@ addressof(T& v) &const_cast(reinterpret_cast(v))); } +template +struct sqrt_size_type_max +{ + static const SizeType value = (SizeType(1) << (sizeof(SizeType)*(CHAR_BIT/2)))-1; +}; + +template +inline bool multiplication_overflows(SizeType a, SizeType b) +{ + const SizeType sqrt_size_max = sqrt_size_type_max::value; + return //Fast runtime check + ( (a | b) > sqrt_size_max && + //Slow division check + b && a > SizeType(-1)/b + ); +} + +template +inline bool size_overflows(SizeType count) +{ + //Compile time-check + BOOST_STATIC_ASSERT(SztSizeOfType <= SizeType(-1)); + //Runtime check + return multiplication_overflows(SizeType(SztSizeOfType), count); +} + +template +class pointer_size_t_caster +{ + public: + explicit pointer_size_t_caster(std::size_t sz) + : m_ptr(reinterpret_cast(sz)) + {} + + explicit pointer_size_t_caster(RawPointer p) + : m_ptr(p) + {} + + std::size_t size() const + { return reinterpret_cast(m_ptr); } + + RawPointer pointer() const + { return m_ptr; } + + private: + RawPointer m_ptr; +}; + + +template +inline bool sum_overflows(SizeType a, SizeType b) +{ return SizeType(-1) - a < b; } + //Anti-exception node eraser template class value_eraser @@ -140,7 +198,7 @@ class value_eraser public: value_eraser(Cont & cont, typename Cont::iterator it) : m_cont(cont), m_index_it(it), m_erase(true){} - ~value_eraser() + ~value_eraser() { if(m_erase) m_cont.erase(m_index_it); } void release() { m_erase = false; } diff --git a/include/boost/interprocess/detail/variadic_templates_tools.hpp b/include/boost/interprocess/detail/variadic_templates_tools.hpp index 482a005..5f2a94a 100644 --- a/include/boost/interprocess/detail/variadic_templates_tools.hpp +++ b/include/boost/interprocess/detail/variadic_templates_tools.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2008-2012. 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/include/boost/interprocess/detail/win32_api.hpp b/include/boost/interprocess/detail/win32_api.hpp index c53725c..b367bba 100644 --- a/include/boost/interprocess/detail/win32_api.hpp +++ b/include/boost/interprocess/detail/win32_api.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -50,6 +50,7 @@ static const unsigned long error_invalid_handle = 6L; static const unsigned long error_sharing_violation = 32L; static const unsigned long error_file_not_found = 2u; static const unsigned long error_no_more_files = 18u; +static const unsigned long error_not_locked = 158L; //Retries in CreateFile, see http://support.microsoft.com/kb/316609 static const unsigned int error_sharing_violation_tries = 3u; static const unsigned int error_sharing_violation_sleep_ms = 250u; @@ -61,6 +62,7 @@ static const unsigned long mutex_all_access = (0x000F0000L)|(0x00100000L)|0x static const unsigned long page_readonly = 0x02; static const unsigned long page_readwrite = 0x04; static const unsigned long page_writecopy = 0x08; +static const unsigned long page_noaccess = 0x01; static const unsigned long standard_rights_required = 0x000F0000L; static const unsigned long section_query = 0x0001; @@ -239,17 +241,16 @@ struct wchar_variant } value; }; - struct IUnknown_BIPC - { - public: - virtual long __stdcall QueryInterface( - /* [in] */ const GUID_BIPC &riid, - /* [iid_is][out] */ void **ppvObject) = 0; +struct IUnknown_BIPC +{ + public: + virtual long __stdcall QueryInterface( + const GUID_BIPC &riid, // [in] + void **ppvObject) = 0; // [iid_is][out] - virtual unsigned long __stdcall AddRef( void) = 0; - - virtual unsigned long __stdcall Release( void) = 0; - }; + virtual unsigned long __stdcall AddRef (void) = 0; + virtual unsigned long __stdcall Release(void) = 0; +}; struct IWbemClassObject_BIPC : public IUnknown_BIPC { @@ -357,7 +358,6 @@ struct IWbemClassObject_BIPC : public IUnknown_BIPC }; - struct IWbemContext_BIPC : public IUnknown_BIPC { public: @@ -585,8 +585,6 @@ public: }; - - struct interprocess_overlapped { unsigned long *internal; @@ -661,7 +659,7 @@ struct system_info { unsigned short wProcessorRevision; }; -typedef struct _interprocess_memory_basic_information +struct interprocess_memory_basic_information { void * BaseAddress; void * AllocationBase; @@ -670,16 +668,16 @@ typedef struct _interprocess_memory_basic_information unsigned long State; unsigned long Protect; unsigned long Type; -} interprocess_memory_basic_information; +}; -typedef struct _interprocess_acl +struct interprocess_acl { unsigned char AclRevision; unsigned char Sbz1; unsigned short AclSize; unsigned short AceCount; unsigned short Sbz2; -} interprocess_acl; +}; typedef struct _interprocess_security_descriptor { @@ -876,6 +874,8 @@ extern "C" __declspec(dllimport) int __stdcall DeleteFileA (const char *); extern "C" __declspec(dllimport) int __stdcall MoveFileExA (const char *, const char *, unsigned long); extern "C" __declspec(dllimport) void __stdcall GetSystemInfo (struct system_info *); extern "C" __declspec(dllimport) int __stdcall FlushViewOfFile (void *, std::size_t); +extern "C" __declspec(dllimport) int __stdcall VirtualUnlock (void *, std::size_t); +extern "C" __declspec(dllimport) int __stdcall VirtualProtect (void *, std::size_t, unsigned long, unsigned long *); extern "C" __declspec(dllimport) int __stdcall FlushFileBuffers (void *); extern "C" __declspec(dllimport) int __stdcall GetFileSizeEx (void *, __int64 *size); extern "C" __declspec(dllimport) unsigned long __stdcall FormatMessageA @@ -1033,7 +1033,7 @@ inline bool duplicate_current_process_handle , duplicate_same_access); } -inline long get_file_type(void *hFile) +inline unsigned long get_file_type(void *hFile) { return GetFileType(hFile); } @@ -1137,6 +1137,12 @@ inline void get_system_info(system_info *info) inline bool flush_view_of_file(void *base_addr, std::size_t numbytes) { return 0 != FlushViewOfFile(base_addr, numbytes); } +inline bool virtual_unlock(void *base_addr, std::size_t numbytes) +{ return 0 != VirtualUnlock(base_addr, numbytes); } + +inline bool virtual_protect(void *base_addr, std::size_t numbytes, unsigned long flNewProtect, unsigned long &lpflOldProtect) +{ return 0 != VirtualProtect(base_addr, numbytes, flNewProtect, &lpflOldProtect); } + inline bool flush_file_buffers(void *handle) { return 0 != FlushFileBuffers(handle); } diff --git a/include/boost/interprocess/detail/windows_intermodule_singleton.hpp b/include/boost/interprocess/detail/windows_intermodule_singleton.hpp index a716e27..194e566 100644 --- a/include/boost/interprocess/detail/windows_intermodule_singleton.hpp +++ b/include/boost/interprocess/detail/windows_intermodule_singleton.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2009-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2009-2012. 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) // @@ -68,8 +68,8 @@ class windows_semaphore_based_map //in max_count and initial count parameters. //Also, max count must be bigger than 0 and bigger or equal than initial count. if(sizeof(void*) == sizeof(boost::uint32_t)){ - //This means that for 32 bit processes, a semaphore count (31 usable bits) is - //enough to store 4 byte aligned memory (4GB -> 32 bits - 2 bits = 30 bits). + //This means that for 32 bit processes, a semaphore count (31 usable bits) is + //enough to store 4 byte aligned memory (4GB -> 32 bits - 2 bits = 30 bits). //The max count will hold the pointer value and current semaphore count //will be zero. // @@ -224,7 +224,7 @@ class windows_semaphore_based_map m_sem_count.close(); //Once scoped_lock unlocks the mutex, the destructor will close the handle... } - + private: winapi_mutex_wrapper m_mtx_lock; winapi_semaphore_wrapper m_sem_map; diff --git a/include/boost/interprocess/detail/workaround.hpp b/include/boost/interprocess/detail/workaround.hpp index 884b868..d410e74 100644 --- a/include/boost/interprocess/detail/workaround.hpp +++ b/include/boost/interprocess/detail/workaround.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -27,7 +27,7 @@ #define BOOST_INTERPROCESS_POSIX_PROCESS_SHARED #endif #endif - + #if defined(_POSIX_BARRIERS) && ((_POSIX_BARRIERS - 0) > 0) #define BOOST_INTERPROCESS_POSIX_BARRIERS #endif @@ -39,7 +39,7 @@ #endif //Some platforms have a limited (name length) named semaphore support #elif (defined(__FreeBSD__) && (__FreeBSD__ >= 4)) || defined(__APPLE__) - #define BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES + #define BOOST_INTERPROCESS_POSIX_NAMED_SEMAPHORES #endif #if ((defined _V6_ILP32_OFFBIG) &&(_V6_ILP32_OFFBIG - 0 > 0)) ||\ @@ -90,6 +90,8 @@ // hp-ux tru64 vms freebsd #if defined(__hpux) || defined(__osf__) || defined(__vms) || (defined(__FreeBSD__) && (__FreeBSD__ < 7)) #define BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SHARED_MEMORY + //Some systems have "jailed" environments where shm usage is restricted at runtime + //and temporary file file based shm is possible in those executions. #elif defined(__FreeBSD__) #define BOOST_INTERPROCESS_RUNTIME_FILESYSTEM_BASED_POSIX_SHARED_MEMORY #endif @@ -130,6 +132,29 @@ #define BOOST_INTERPROCESS_TIMEOUT_WHEN_LOCKING_DURATION_MS 10000 #endif +//Other switches +//BOOST_INTERPROCESS_MSG_QUEUE_USES_CIRC_INDEX +//message queue uses a circular queue as index instead of an array (better performance) +//Boost version < 1.52 uses an array, so undef this if you want to communicate +//with processes compiled with those versions. +#define BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX + +//Inline attributes +#if defined(_MSC_VER) + #define BOOST_INTERPROCESS_ALWAYS_INLINE __forceinline +#elif defined (__GNUC__) + #define BOOST_INTERPROCESS_ALWAYS_INLINE __attribute__((__always_inline__)) +#else + #define BOOST_INTERPROCESS_ALWAYS_INLINE inline +#endif + +#if defined(_MSC_VER) + #define BOOST_INTERPROCESS_NEVER_INLINE __declspec(noinline) +#elif defined (__GNUC__) + #define BOOST_INTERPROCESS_NEVER_INLINE __attribute__((__noinline__)) +#endif + + #include #endif //#ifndef BOOST_INTERPROCESS_DETAIL_WORKAROUND_HPP diff --git a/include/boost/interprocess/detail/xsi_shared_memory_device.hpp b/include/boost/interprocess/detail/xsi_shared_memory_device.hpp index ef4b009..b2a2750 100644 --- a/include/boost/interprocess/detail/xsi_shared_memory_device.hpp +++ b/include/boost/interprocess/detail/xsi_shared_memory_device.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2009-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2009-2012. 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) // @@ -74,10 +74,10 @@ class xsi_shared_memory_device { this->swap(moved); } xsi_shared_memory_device &operator=(BOOST_RV_REF(xsi_shared_memory_device) moved) - { + { xsi_shared_memory_device tmp(boost::move(moved)); this->swap(tmp); - return *this; + return *this; } //!Swaps two xsi_shared_memory_device. Does not throw @@ -178,7 +178,7 @@ inline void xsi_shared_memory_device::swap(xsi_shared_memory_device &other) { m_shm.swap(other.m_shm); std::swap(m_mode, other.m_mode); - m_name.swap(other.m_name); + m_name.swap(other.m_name); } inline mapping_handle_t xsi_shared_memory_device::get_mapping_handle() const diff --git a/include/boost/interprocess/detail/xsi_shared_memory_file_wrapper.hpp b/include/boost/interprocess/detail/xsi_shared_memory_file_wrapper.hpp index 14811e7..51af830 100644 --- a/include/boost/interprocess/detail/xsi_shared_memory_file_wrapper.hpp +++ b/include/boost/interprocess/detail/xsi_shared_memory_file_wrapper.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2009-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2009-2012. 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) // @@ -40,7 +40,7 @@ class xsi_shared_memory_file_wrapper { /// @cond BOOST_MOVABLE_BUT_NOT_COPYABLE(xsi_shared_memory_file_wrapper) - /// @endcond + /// @endcond public: xsi_shared_memory_file_wrapper() : xsi_shared_memory() {} @@ -61,10 +61,10 @@ class xsi_shared_memory_file_wrapper { this->swap(moved); } xsi_shared_memory_file_wrapper &operator=(BOOST_RV_REF(xsi_shared_memory_file_wrapper) moved) - { + { xsi_shared_memory_file_wrapper tmp(boost::move(moved)); this->swap(tmp); - return *this; + return *this; } //!Swaps two xsi_shared_memory_file_wrapper. Does not throw diff --git a/include/boost/interprocess/errors.hpp b/include/boost/interprocess/errors.hpp index 9eed55a..345ca31 100644 --- a/include/boost/interprocess/errors.hpp +++ b/include/boost/interprocess/errors.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -183,7 +183,7 @@ static const ec_xlate ec_table[] = }; inline error_code_t lookup_error(native_error_t err) -{ +{ const ec_xlate *cur = &ec_table[0], *end = cur + sizeof(ec_table)/sizeof(ec_xlate); for (;cur != end; ++cur ){ diff --git a/include/boost/interprocess/exceptions.hpp b/include/boost/interprocess/exceptions.hpp index a4f196f..b9ab45b 100644 --- a/include/boost/interprocess/exceptions.hpp +++ b/include/boost/interprocess/exceptions.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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/include/boost/interprocess/file_mapping.hpp b/include/boost/interprocess/file_mapping.hpp index 2a4e4cc..5842860 100644 --- a/include/boost/interprocess/file_mapping.hpp +++ b/include/boost/interprocess/file_mapping.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -61,7 +61,7 @@ class file_mapping { file_mapping tmp(boost::move(moved)); this->swap(tmp); - return *this; + return *this; } //!Swaps to file_mappings. @@ -111,10 +111,10 @@ inline const char *file_mapping::get_name() const { return m_filename.c_str(); } inline void file_mapping::swap(file_mapping &other) -{ +{ std::swap(m_handle, other.m_handle); std::swap(m_mode, other.m_mode); - m_filename.swap(other.m_filename); + m_filename.swap(other.m_filename); } inline mapping_handle_t file_mapping::get_mapping_handle() const diff --git a/include/boost/interprocess/indexes/flat_map_index.hpp b/include/boost/interprocess/indexes/flat_map_index.hpp index bac387e..52bf88a 100644 --- a/include/boost/interprocess/indexes/flat_map_index.hpp +++ b/include/boost/interprocess/indexes/flat_map_index.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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/include/boost/interprocess/indexes/iset_index.hpp b/include/boost/interprocess/indexes/iset_index.hpp index 8fc9146..b1abede 100644 --- a/include/boost/interprocess/indexes/iset_index.hpp +++ b/include/boost/interprocess/indexes/iset_index.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -82,7 +82,7 @@ class iset_index struct intrusive_key_value_less { bool operator()(const intrusive_compare_key_type &i, const value_type &b) const - { + { std::size_t blen = b.name_length(); return (i.m_len < blen) || (i.m_len == blen && @@ -91,7 +91,7 @@ class iset_index } bool operator()(const value_type &b, const intrusive_compare_key_type &i) const - { + { std::size_t blen = b.name_length(); return (blen < i.m_len) || (blen == i.m_len && diff --git a/include/boost/interprocess/indexes/iunordered_set_index.hpp b/include/boost/interprocess/indexes/iunordered_set_index.hpp index 3c5f855..a23c846 100644 --- a/include/boost/interprocess/indexes/iunordered_set_index.hpp +++ b/include/boost/interprocess/indexes/iunordered_set_index.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -58,21 +58,21 @@ struct iunordered_set_index_aux struct equal_function { bool operator()(const intrusive_compare_key_type &i, const value_type &b) const - { + { return (i.m_len == b.name_length()) && (std::char_traits::compare (i.mp_str, b.name(), i.m_len) == 0); } bool operator()(const value_type &b, const intrusive_compare_key_type &i) const - { + { return (i.m_len == b.name_length()) && (std::char_traits::compare (i.mp_str, b.name(), i.m_len) == 0); } bool operator()(const value_type &b1, const value_type &b2) const - { + { return (b1.name_length() == b2.name_length()) && (std::char_traits::compare (b1.name(), b2.name(), b1.name_length()) == 0); @@ -190,7 +190,7 @@ class iunordered_set_index bucket_ptr shunk_p = alloc.allocation_command (boost::interprocess::shrink_in_place | boost::interprocess::nothrow_allocation, received_size, received_size, received_size, buckets).first; - BOOST_ASSERT(buckets == shunk_p); + BOOST_ASSERT(buckets == shunk_p); (void)shunk_p; bucket_ptr buckets_init = buckets + received_size; for(size_type i = 0; i < (old_size - received_size); ++i){ @@ -290,7 +290,7 @@ class iunordered_set_index size_type cur_size = this->size(); size_type cur_count = this->bucket_count(); bucket_ptr old_p = this->bucket_pointer(); - + if(!this->size() && old_p != bucket_ptr(&this->init_bucket)){ this->rehash(bucket_traits(bucket_ptr(&this->init_bucket), 1)); destroy_buckets(this->alloc, old_p, cur_count); @@ -337,7 +337,7 @@ class iunordered_set_index //Strong guarantee: if something goes wrong //we should remove the insertion. // - //We can use the iterator because the hash function + //We can use the iterator because the hash function //can't throw and this means that "reserve" will //throw only because of the memory allocation: //the iterator has not been invalidated. diff --git a/include/boost/interprocess/indexes/map_index.hpp b/include/boost/interprocess/indexes/map_index.hpp index 1bfc7ce..409e4c9 100644 --- a/include/boost/interprocess/indexes/map_index.hpp +++ b/include/boost/interprocess/indexes/map_index.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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/include/boost/interprocess/indexes/null_index.hpp b/include/boost/interprocess/indexes/null_index.hpp index a0353b1..1e1d670 100644 --- a/include/boost/interprocess/indexes/null_index.hpp +++ b/include/boost/interprocess/indexes/null_index.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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/include/boost/interprocess/indexes/unordered_map_index.hpp b/include/boost/interprocess/indexes/unordered_map_index.hpp index 7cf4b85..2fce665 100644 --- a/include/boost/interprocess/indexes/unordered_map_index.hpp +++ b/include/boost/interprocess/indexes/unordered_map_index.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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/include/boost/interprocess/interprocess_fwd.hpp b/include/boost/interprocess/interprocess_fwd.hpp index 68fd89f..42f170a 100644 --- a/include/boost/interprocess/interprocess_fwd.hpp +++ b/include/boost/interprocess/interprocess_fwd.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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/include/boost/interprocess/ipc/message_queue.hpp b/include/boost/interprocess/ipc/message_queue.hpp index 67dd574..4ce5b8a 100644 --- a/include/boost/interprocess/ipc/message_queue.hpp +++ b/include/boost/interprocess/ipc/message_queue.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -99,7 +99,7 @@ class message_queue_t //!Sends a message stored in buffer "buffer" with size "buffer_size" in the //!message queue with priority "priority". If the message queue is full - //!the sender is blocked. Throws interprocess_error on error.*/ + //!the sender is blocked. Throws interprocess_error on error. void send (const void *buffer, size_type buffer_size, unsigned int priority); @@ -161,7 +161,7 @@ class message_queue_t //!Returns false on error. Never throws static bool remove(const char *name); - /// @cond + /// @cond private: typedef boost::posix_time::ptime ptime; bool do_receive(block_t block, @@ -227,9 +227,27 @@ class priority_functor //! //!-> offset_ptr index [max_num_msg] //! An array of pointers with size "max_num_msg" called index. Each pointer -//! points to a preallocated message. The elements of this array are +//! points to a preallocated message. Elements of this array are //! reordered in runtime in the following way: //! +//! IF BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX is defined: +//! +//! When the current number of messages is "cur_num_msg", the array +//! is treated like a circular buffer. Starting from position "cur_first_msg" +//! "cur_num_msg" in a circular way, pointers point to inserted messages and the rest +//! point to free messages. Those "cur_num_msg" pointers are +//! ordered by the priority of the pointed message and by insertion order +//! if two messages have the same priority. So the next message to be +//! used in a "receive" is pointed by index [(cur_first_msg + cur_num_msg-1)%max_num_msg] +//! and the first free message ready to be used in a "send" operation is +//! [cur_first_msg] if circular buffer is extended from front, +//! [(cur_first_msg + cur_num_msg)%max_num_msg] otherwise. +//! +//! This transforms the index in a circular buffer with an embedded free +//! message queue. +//! +//! ELSE (BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX is NOT defined): +//! //! When the current number of messages is "cur_num_msg", the first //! "cur_num_msg" pointers point to inserted messages and the rest //! point to free messages. The first "cur_num_msg" pointers are @@ -237,11 +255,12 @@ class priority_functor //! if two messages have the same priority. So the next message to be //! used in a "receive" is pointed by index [cur_num_msg-1] and the first free //! message ready to be used in a "send" operation is index [cur_num_msg]. -//! This transforms index in a fixed size priority queue with an embedded free +//! +//! This transforms the index in a fixed size priority queue with an embedded free //! message queue. //! //!-> struct message_t -//! { +//! { //! msg_hdr_t header; //! char[max_msg_size] data; //! } messages [max_num_msg]; @@ -252,7 +271,7 @@ class priority_functor template class mq_hdr_t : public ipcdetail::priority_functor -{ +{ typedef VoidPointer void_pointer; typedef msg_hdr_t msg_header; typedef typename boost::intrusive:: @@ -269,17 +288,16 @@ class mq_hdr_t //!Constructor. This object must be constructed in the beginning of the //!shared memory of the size returned by the function "get_mem_size". //!This constructor initializes the needed resources and creates - //!the internal structures like the priority index. This can throw.*/ + //!the internal structures like the priority index. This can throw. mq_hdr_t(size_type max_num_msg, size_type max_msg_size) : m_max_num_msg(max_num_msg), m_max_msg_size(max_msg_size), m_cur_num_msg(0) + #if defined(BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX) + ,m_cur_first_msg(0u) + #endif { this->initialize_memory(); } - //!Returns the inserted message with top priority - msg_header * top_msg() - { return mp_index[m_cur_num_msg-1].get(); } - //!Returns true if the message queue is full bool is_full() const { return m_cur_num_msg == m_max_num_msg; } @@ -292,24 +310,196 @@ class mq_hdr_t void free_top_msg() { --m_cur_num_msg; } - //!Returns the first free msg of the free message queue - msg_header * free_msg() - { return mp_index[m_cur_num_msg].get(); } + #if defined(BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX) + + typedef msg_hdr_ptr_t *iterator; + + size_type end_pos() const + { + const size_type space_until_bufend = m_max_num_msg - m_cur_first_msg; + return space_until_bufend > m_cur_num_msg + ? m_cur_first_msg + m_cur_num_msg : m_cur_num_msg - space_until_bufend; + } + + //!Returns the inserted message with top priority + msg_header &top_msg() + { + size_type pos = this->end_pos(); + return *mp_index[pos ? --pos : m_max_num_msg - 1]; + } + + //!Returns the inserted message with bottom priority + msg_header &bottom_msg() + { return *mp_index[m_cur_first_msg]; } + + iterator inserted_ptr_begin() const + { return &mp_index[m_cur_first_msg]; } + + iterator inserted_ptr_end() const + { return &mp_index[this->end_pos()]; } + + iterator lower_bound(const msg_hdr_ptr_t & value, priority_functor func) + { + iterator begin(this->inserted_ptr_begin()), end(this->inserted_ptr_end()); + if(end < begin){ + iterator idx_end = &mp_index[m_max_num_msg]; + iterator ret = std::lower_bound(begin, idx_end, value, func); + if(idx_end == ret){ + iterator idx_beg = &mp_index[0]; + ret = std::lower_bound(idx_beg, end, value, func); + //sanity check, these cases should not call lower_bound (optimized out) + assert(ret != end); + assert(ret != begin); + return ret; + } + else{ + return ret; + } + } + else{ + return std::lower_bound(begin, end, value, func); + } + } + + msg_header & insert_at(iterator where) + { + iterator inserted_ptr_end = this->inserted_ptr_end(); + iterator inserted_ptr_beg = this->inserted_ptr_begin(); + if(where == inserted_ptr_end){ + ++m_cur_num_msg; + return **inserted_ptr_end; + } + else if(where == inserted_ptr_beg){ + //unsigned integer guarantees underflow + m_cur_first_msg = m_cur_first_msg ? m_cur_first_msg : m_max_num_msg; + --m_cur_first_msg; + ++m_cur_num_msg; + return *mp_index[m_cur_first_msg]; + } + else{ + size_type pos = where - &mp_index[0]; + size_type circ_pos = pos >= m_cur_first_msg ? pos - m_cur_first_msg : pos + (m_max_num_msg - m_cur_first_msg); + //Check if it's more efficient to move back or move front + if(circ_pos < m_cur_num_msg/2){ + //The queue can't be full so m_cur_num_msg == 0 or m_cur_num_msg <= pos + //indicates two step insertion + if(!pos){ + pos = m_max_num_msg; + where = &mp_index[m_max_num_msg-1]; + } + else{ + --where; + } + const bool unique_segment = m_cur_first_msg && m_cur_first_msg <= pos; + size_type first_segment_beg = unique_segment ? m_cur_first_msg : 1u; + size_type first_segment_end = pos; + size_type second_segment_beg = unique_segment || !m_cur_first_msg ? m_max_num_msg : m_cur_first_msg; + size_type second_segment_end = m_max_num_msg; + const msg_hdr_ptr_t backup = *(&mp_index[0] + (unique_segment ? first_segment_beg : second_segment_beg) - 1); + + //First segment + if(!unique_segment){ + std::copy( &mp_index[0] + second_segment_beg + , &mp_index[0] + second_segment_end + , &mp_index[0] + second_segment_beg - 1); + mp_index[m_max_num_msg-1] = mp_index[0]; + } + std::copy( &mp_index[0] + first_segment_beg + , &mp_index[0] + first_segment_end + , &mp_index[0] + first_segment_beg - 1); + *where = backup; + m_cur_first_msg = m_cur_first_msg ? m_cur_first_msg : m_max_num_msg; + --m_cur_first_msg; + ++m_cur_num_msg; + return **where; + } + else{ + //The queue can't be full so end_pos < m_cur_first_msg + //indicates two step insertion + const size_type end_pos = this->end_pos(); + const bool unique_segment = pos < end_pos; + size_type first_segment_beg = pos; + size_type first_segment_end = unique_segment ? end_pos : m_max_num_msg-1; + size_type second_segment_beg = 0u; + size_type second_segment_end = unique_segment ? 0u : end_pos; + const msg_hdr_ptr_t backup = *inserted_ptr_end; + + //First segment + if(!unique_segment){ + std::copy_backward( &mp_index[0] + second_segment_beg + , &mp_index[0] + second_segment_end + , &mp_index[0] + second_segment_end + 1); + mp_index[0] = mp_index[m_max_num_msg-1]; + } + std::copy_backward( &mp_index[0] + first_segment_beg + , &mp_index[0] + first_segment_end + , &mp_index[0] + first_segment_end + 1); + *where = backup; + ++m_cur_num_msg; + return **where; + } + } + } + + #else + + typedef msg_hdr_ptr_t *iterator; + + //!Returns the inserted message with top priority + msg_header &top_msg() + { return *mp_index[m_cur_num_msg-1]; } + + //!Returns the inserted message with bottom priority + msg_header &bottom_msg() + { return *mp_index[0]; } + + iterator inserted_ptr_begin() const + { return &mp_index[0]; } + + iterator inserted_ptr_end() const + { return &mp_index[m_cur_num_msg]; } + + iterator lower_bound(const msg_hdr_ptr_t & value, priority_functor func) + { return std::lower_bound(this->inserted_ptr_begin(), this->inserted_ptr_end(), value, func); } + + msg_header & insert_at(iterator pos) + { + const msg_hdr_ptr_t backup = *inserted_ptr_end(); + std::copy_backward(pos, inserted_ptr_end(), inserted_ptr_end()+1); + *pos = backup; + ++m_cur_num_msg; + return **pos; + } + + #endif //!Inserts the first free message in the priority queue - void queue_free_msg() - { - //Get free msg - msg_hdr_ptr_t free = mp_index[m_cur_num_msg]; + msg_header & queue_free_msg(unsigned int priority) + { //Get priority queue's range - msg_hdr_ptr_t *it = &mp_index[0], *it_end = &mp_index[m_cur_num_msg]; - //Check where the free message should be placed - it = std::lower_bound(it, it_end, free, static_cast&>(*this)); - //Make room in that position - std::copy_backward(it, it_end, it_end+1); + iterator it (inserted_ptr_begin()), it_end(inserted_ptr_end()); + //Optimize for non-priority usage + if(m_cur_num_msg && priority > this->bottom_msg().priority){ + //Check for higher priority than all stored messages + if(priority > this->top_msg().priority){ + it = it_end; + } + else{ + //Since we don't now which free message we will pick + //build a dummy header for searches + msg_header dummy_hdr; + dummy_hdr.priority = priority; + + //Get free msg + msg_hdr_ptr_t dummy_ptr(&dummy_hdr); + + //Check where the free message should be placed + it = this->lower_bound(dummy_ptr, static_cast&>(*this)); + } + + } //Insert the free message in the correct position - *it = free; - ++m_cur_num_msg; + return this->insert_at(it); } //!Returns the number of bytes needed to construct a message queue with @@ -322,7 +512,7 @@ class mq_hdr_t msg_hdr_align = ::boost::alignment_of::value, index_align = ::boost::alignment_of::value, r_hdr_size = ipcdetail::ct_rounded_size::value, - r_index_size = ipcdetail::get_rounded_size(sizeof(msg_hdr_ptr_t)*max_num_msg, msg_hdr_align), + r_index_size = ipcdetail::get_rounded_size(max_num_msg*sizeof(msg_hdr_ptr_t), msg_hdr_align), r_max_msg_size = ipcdetail::get_rounded_size(max_msg_size, msg_hdr_align) + sizeof(msg_header); return r_hdr_size + r_index_size + (max_num_msg*r_max_msg_size) + ipcdetail::managed_open_or_create_impl::ManagedOpenOrCreateUserOffset; @@ -336,7 +526,7 @@ class mq_hdr_t msg_hdr_align = ::boost::alignment_of::value, index_align = ::boost::alignment_of::value, r_hdr_size = ipcdetail::ct_rounded_size::value, - r_index_size = ipcdetail::get_rounded_size(sizeof(msg_hdr_ptr_t)*m_max_num_msg, msg_hdr_align), + r_index_size = ipcdetail::get_rounded_size(m_max_num_msg*sizeof(msg_hdr_ptr_t), msg_hdr_align), r_max_msg_size = ipcdetail::get_rounded_size(m_max_msg_size, msg_hdr_align) + sizeof(msg_header); //Pointer to the index @@ -345,7 +535,7 @@ class mq_hdr_t //Pointer to the first message header msg_header *msg_hdr = reinterpret_cast - (reinterpret_cast(this)+r_hdr_size+r_index_size); + (reinterpret_cast(this)+r_hdr_size+r_index_size); //Initialize the pointer to the index mp_index = index; @@ -373,6 +563,10 @@ class mq_hdr_t interprocess_condition m_cond_recv; //Condition block senders when the queue is full interprocess_condition m_cond_send; + #if defined(BOOST_INTERPROCESS_MSG_QUEUE_CIRCULAR_INDEX) + //Current start offset in the circular index + size_type m_cur_first_msg; + #endif }; @@ -403,7 +597,7 @@ class initialization_func_t new (mptr) mq_hdr_t(m_maxmsg, m_maxmsgsize); } BOOST_CATCH(...){ - return false; + return false; } BOOST_CATCH_END } @@ -433,7 +627,7 @@ inline message_queue_t::message_queue_t(create_only_t create_only, //Create shared memory and execute functor atomically : m_shmem(create_only, name, - get_mem_size(max_msg_size, max_num_msg), + get_mem_size(max_msg_size, max_num_msg), read_write, static_cast(0), //Prepare initialization functor @@ -503,13 +697,13 @@ inline bool message_queue_t::do_send(block_t block, throw interprocess_exception(size_error); } + bool was_empty = false; //--------------------------------------------- scoped_lock lock(p_hdr->m_mutex); //--------------------------------------------- { //If the queue is full execute blocking logic if (p_hdr->is_full()) { - switch(block){ case non_blocking : return false; @@ -536,30 +730,30 @@ inline bool message_queue_t::do_send(block_t block, break; } } - - //Get the first free message from free message queue - ipcdetail::msg_hdr_t *free_msg = p_hdr->free_msg(); - if (free_msg == 0) { - throw interprocess_exception("boost::interprocess::message_queue corrupted"); - } + + was_empty = p_hdr->is_empty(); + //Insert the first free message in the priority queue + ipcdetail::msg_hdr_t &free_msg_hdr = p_hdr->queue_free_msg(priority); + + //Sanity check, free msgs are always cleaned when received + assert(free_msg_hdr.priority == 0); + assert(free_msg_hdr.len == 0); //Copy control data to the free message - free_msg->priority = priority; - free_msg->len = buffer_size; + free_msg_hdr.priority = priority; + free_msg_hdr.len = buffer_size; //Copy user buffer to the message - std::memcpy(free_msg->data(), buffer, buffer_size); - -// bool was_empty = p_hdr->is_empty(); - //Insert the first free message in the priority queue - p_hdr->queue_free_msg(); - - //If this message changes the queue empty state, notify it to receivers -// if (was_empty){ - p_hdr->m_cond_recv.notify_one(); -// } + std::memcpy(free_msg_hdr.data(), buffer, buffer_size); } // Lock end + //Notify outside lock to avoid contention. This might produce some + //spurious wakeups, but it's usually far better than notifying inside. + //If this message changes the queue empty state, notify it to receivers + if (was_empty){ + p_hdr->m_cond_recv.notify_one(); + } + return true; } @@ -600,6 +794,7 @@ inline bool throw interprocess_exception(size_error); } + bool was_full = false; //--------------------------------------------- scoped_lock lock(p_hdr->m_mutex); //--------------------------------------------- @@ -635,51 +830,52 @@ inline bool } } - //Thre is at least message ready to pick, get the top one - ipcdetail::msg_hdr_t *top_msg = p_hdr->top_msg(); - - //Paranoia check - if (top_msg == 0) { - throw interprocess_exception("boost::interprocess::message_queue corrupted"); - } + //There is at least one message ready to pick, get the top one + ipcdetail::msg_hdr_t &top_msg = p_hdr->top_msg(); //Get data from the message - recvd_size = top_msg->len; - priority = top_msg->priority; + recvd_size = top_msg.len; + priority = top_msg.priority; + + //Some cleanup to ease debugging + top_msg.len = 0; + top_msg.priority = 0; //Copy data to receiver's bufers - std::memcpy(buffer, top_msg->data(), recvd_size); + std::memcpy(buffer, top_msg.data(), recvd_size); -// bool was_full = p_hdr->is_full(); + was_full = p_hdr->is_full(); //Free top message and put it in the free message list p_hdr->free_top_msg(); - - //If this reception changes the queue full state, notify senders -// if (was_full){ - p_hdr->m_cond_send.notify_one(); -// } } //Lock end + //Notify outside lock to avoid contention. This might produce some + //spurious wakeups, but it's usually far better than notifying inside. + //If this reception changes the queue full state, notify senders + if (was_full){ + p_hdr->m_cond_send.notify_one(); + } + return true; } template inline typename message_queue_t::size_type message_queue_t::get_max_msg() const -{ +{ ipcdetail::mq_hdr_t *p_hdr = static_cast*>(m_shmem.get_user_address()); return p_hdr ? p_hdr->m_max_num_msg : 0; } template inline typename message_queue_t::size_type message_queue_t::get_max_msg_size() const -{ +{ ipcdetail::mq_hdr_t *p_hdr = static_cast*>(m_shmem.get_user_address()); - return p_hdr ? p_hdr->m_max_msg_size : 0; + return p_hdr ? p_hdr->m_max_msg_size : 0; } template inline typename message_queue_t::size_type message_queue_t::get_num_msg() -{ +{ ipcdetail::mq_hdr_t *p_hdr = static_cast*>(m_shmem.get_user_address()); if(p_hdr){ //--------------------------------------------- @@ -688,7 +884,7 @@ inline typename message_queue_t::size_type message_queue_tm_cur_num_msg; } - return 0; + return 0; } template diff --git a/include/boost/interprocess/managed_external_buffer.hpp b/include/boost/interprocess/managed_external_buffer.hpp index e268e57..1f4a199 100644 --- a/include/boost/interprocess/managed_external_buffer.hpp +++ b/include/boost/interprocess/managed_external_buffer.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -23,7 +23,7 @@ #include //These includes needed to fulfill default template parameters of //predeclarations in interprocess_fwd.hpp -#include +#include #include #include @@ -50,7 +50,7 @@ class basic_managed_external_buffer base_t; BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_managed_external_buffer) /// @endcond - + public: typedef typename base_t::size_type size_type; diff --git a/include/boost/interprocess/managed_heap_memory.hpp b/include/boost/interprocess/managed_heap_memory.hpp index 8710785..868fdc5 100644 --- a/include/boost/interprocess/managed_heap_memory.hpp +++ b/include/boost/interprocess/managed_heap_memory.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -24,7 +24,7 @@ #include //These includes needed to fulfill default template parameters of //predeclarations in interprocess_fwd.hpp -#include +#include #include #include @@ -99,7 +99,7 @@ class basic_managed_heap_memory //!have some extra bytes to allocate new objects. If returns //!false, the heap allocation has failed. bool grow(size_type extra_bytes) - { + { //If memory is reallocated, data will //be automatically copied BOOST_TRY{ @@ -129,7 +129,7 @@ class basic_managed_heap_memory private: //!Frees resources. Never throws. void priv_close() - { + { base_t::destroy_impl(); std::vector().swap(m_heapmem); } diff --git a/include/boost/interprocess/managed_mapped_file.hpp b/include/boost/interprocess/managed_mapped_file.hpp index 5a351ad..eaf441c 100644 --- a/include/boost/interprocess/managed_mapped_file.hpp +++ b/include/boost/interprocess/managed_mapped_file.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -26,7 +26,7 @@ #include //These includes needed to fulfill default template parameters of //predeclarations in interprocess_fwd.hpp -#include +#include #include #include @@ -61,7 +61,7 @@ class basic_managed_mapped_file private: - typedef ipcdetail::create_open_func create_open_func_t; + typedef ipcdetail::create_open_func create_open_func_t; typedef ipcdetail::managed_open_or_create_impl< ipcdetail::file_wrapper , AllocationAlgorithm::Alignment> managed_open_or_create_type; diff --git a/include/boost/interprocess/managed_shared_memory.hpp b/include/boost/interprocess/managed_shared_memory.hpp index 0f74c1a..d52986a 100644 --- a/include/boost/interprocess/managed_shared_memory.hpp +++ b/include/boost/interprocess/managed_shared_memory.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -25,7 +25,7 @@ #include //These includes needed to fulfill default template parameters of //predeclarations in interprocess_fwd.hpp -#include +#include #include namespace boost { diff --git a/include/boost/interprocess/managed_windows_shared_memory.hpp b/include/boost/interprocess/managed_windows_shared_memory.hpp index 414007a..3d621b5 100644 --- a/include/boost/interprocess/managed_windows_shared_memory.hpp +++ b/include/boost/interprocess/managed_windows_shared_memory.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -25,7 +25,7 @@ #include //These includes needed to fulfill default template parameters of //predeclarations in interprocess_fwd.hpp -#include +#include #include #include diff --git a/include/boost/interprocess/managed_xsi_shared_memory.hpp b/include/boost/interprocess/managed_xsi_shared_memory.hpp index dc909f6..a389c36 100644 --- a/include/boost/interprocess/managed_xsi_shared_memory.hpp +++ b/include/boost/interprocess/managed_xsi_shared_memory.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2008-2012. 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) // @@ -28,7 +28,7 @@ #include //These includes needed to fulfill default template parameters of //predeclarations in interprocess_fwd.hpp -#include +#include #include #include diff --git a/include/boost/interprocess/mapped_region.hpp b/include/boost/interprocess/mapped_region.hpp index 522c1e4..6c48c85 100644 --- a/include/boost/interprocess/mapped_region.hpp +++ b/include/boost/interprocess/mapped_region.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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,18 @@ #include #include #include +//Some Unixes use caddr_t instead of void * in madvise +// SunOS Tru64 HP-UX AIX +#if defined(sun) || defined(__sun) || defined(__osf__) || defined(__osf) || defined(_hpux) || defined(hpux) || defined(_AIX) +#define BOOST_INTERPROCESS_MADVISE_USES_CADDR_T +#include +#endif + +//A lot of UNIXes have destructive semantics for MADV_DONTNEED, so +//we need to be careful to allow it. +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__) +#define BOOST_INTERPROCESS_MADV_DONTNEED_HAS_NONDESTRUCTIVE_SEMANTICS +#endif #if defined (BOOST_INTERPROCESS_WINDOWS) # include @@ -49,6 +61,13 @@ namespace boost { namespace interprocess { /// @cond + +//Solaris declares madvise only in some configurations but defines MADV_XXX, a bit confusing. +//Predeclare it here to avoid any compilation error +#if (defined(sun) || defined(__sun)) && defined(MADV_NORMAL) +extern "C" int madvise(caddr_t, size_t, int); +#endif + namespace ipcdetail{ class interprocess_tester; } namespace ipcdetail{ class raw_mapped_region_creator; } @@ -117,6 +136,10 @@ class mapped_region return *this; } + //!Swaps the mapped_region with another + //!mapped region + void swap(mapped_region &other); + //!Returns the size of the mapping. Never throws. std::size_t get_size() const; @@ -135,9 +158,41 @@ class mapped_region //!Never throws. Returns false if operation could not be performed. bool flush(std::size_t mapping_offset = 0, std::size_t numbytes = 0, bool async = true); - //!Swaps the mapped_region with another - //!mapped region - void swap(mapped_region &other); + //!Shrinks current mapped region. If after shrinking there is no longer need for a previously + //!mapped memory page, accessing that page can trigger a segmentation fault. + //!Depending on the OS, this operation might fail (XSI shared memory), it can decommit storage + //!and free a portion of the virtual address space (e.g.POSIX) or this + //!function can release some physical memory wihout freeing any virtual address space(Windows). + //!Returns true on success. Never throws. + bool shrink_by(std::size_t bytes, bool from_back = true); + + //!This enum specifies region usage behaviors that an application can specify + //!to the mapped region implementation. + enum advice_types{ + //!Specifies that the application has no advice to give on its behavior with respect to + //!the region. It is the default characteristic if no advice is given for a range of memory. + advice_normal, + //!Specifies that the application expects to access the region sequentially from + //!lower addresses to higher addresses. The implementation can lower the priority of + //!preceding pages within the region once a page have been accessed. + advice_sequential, + //!Specifies that the application expects to access the region in a random order, + //!and prefetching is likely not advantageous. + advice_random, + //!Specifies that the application expects to access the region in the near future. + //!The implementation can prefetch pages of the region. + advice_willneed, + //!Specifies that the application expects that it will not access the region in the near future. + //!The implementation can unload pages within the range to save system resources. + advice_dontneed + }; + + //!Advises the implementation on the expected behavior of the application with respect to the data + //!in the region. The implementation may use this information to optimize handling of the region data. + //!This function has no effect on the semantics of access to memory in the region, although it may affect + //!the performance of access. + //!If the advise type is not known to the implementation, the function returns false. True otherwise. + bool advise(advice_types advise); //!Returns the size of the page. This size is the minimum memory that //!will be used by the system when mapping a memory mappable source and @@ -152,6 +207,7 @@ class mapped_region void* priv_map_address() const; std::size_t priv_map_size() const; bool priv_flush_param_check(std::size_t mapping_offset, void *&addr, std::size_t &numbytes) const; + bool priv_shrink_param_check(std::size_t bytes, bool from_back, void *&shrink_page_start, std::size_t &shrink_page_bytes); static void priv_size_from_mapping_size (offset_t mapping_size, offset_t offset, offset_t page_offset, std::size_t &size); static offset_t priv_page_offset_addr_fixup(offset_t page_offset, const void *&addr); @@ -226,6 +282,38 @@ inline bool mapped_region::priv_flush_param_check return true; } +inline bool mapped_region::priv_shrink_param_check + (std::size_t bytes, bool from_back, void *&shrink_page_start, std::size_t &shrink_page_bytes) +{ + //Check some errors + if(m_base == 0 || bytes > m_size){ + return false; + } + else if(bytes == m_size){ + this->priv_close(); + return true; + } + else{ + const std::size_t page_size = mapped_region::get_page_size(); + if(from_back){ + const std::size_t new_pages = (m_size + m_page_offset - bytes - 1)/page_size + 1; + shrink_page_start = static_cast(this->priv_map_address()) + new_pages*page_size; + shrink_page_bytes = m_page_offset + m_size - new_pages*page_size; + m_size -= bytes; + } + else{ + shrink_page_start = this->priv_map_address(); + m_page_offset += bytes; + shrink_page_bytes = (m_page_offset/page_size)*page_size; + m_page_offset = m_page_offset % page_size; + m_size -= bytes; + m_base = static_cast(m_base) + bytes; + assert(shrink_page_bytes%page_size == 0); + } + return true; + } +} + inline void mapped_region::priv_size_from_mapping_size (offset_t mapping_size, offset_t offset, offset_t page_offset, std::size_t &size) { @@ -405,6 +493,37 @@ inline bool mapped_region::flush(std::size_t mapping_offset, std::size_t numbyte return true; } +inline bool mapped_region::shrink_by(std::size_t bytes, bool from_back) +{ + void *shrink_page_start; + std::size_t shrink_page_bytes; + if(!this->priv_shrink_param_check(bytes, from_back, shrink_page_start, shrink_page_bytes)){ + return false; + } + else if(shrink_page_bytes){ + //In Windows, we can't decommit the storage or release the virtual address space, + //the best we can do is try to remove some memory from the process working set. + //With a bit of luck we can free some physical memory. + unsigned long old_protect_ignored; + bool b_ret = winapi::virtual_unlock(shrink_page_start, shrink_page_bytes) + || (winapi::get_last_error() == winapi::error_not_locked); + (void)old_protect_ignored; + //Change page protection to forbid any further access + b_ret = b_ret && winapi::virtual_protect + (shrink_page_start, shrink_page_bytes, winapi::page_noaccess, old_protect_ignored); + return b_ret; + } + else{ + return true; + } +} + +inline bool mapped_region::advise(advice_types) +{ + //Windows has no madvise/posix_madvise equivalent + return false; +} + inline void mapped_region::priv_close() { if(m_base){ @@ -503,7 +622,13 @@ inline mapped_region::mapped_region //Create new mapping int prot = 0; - int flags = 0; + int flags = + #ifdef MAP_NOSYNC + //Avoid excessive syncing in BSD systems + MAP_NOSYNC; + #else + 0; + #endif switch(mode) { @@ -562,14 +687,107 @@ inline mapped_region::mapped_region } } +inline bool mapped_region::shrink_by(std::size_t bytes, bool from_back) +{ + void *shrink_page_start = 0; + std::size_t shrink_page_bytes = 0; + if(m_is_xsi || !this->priv_shrink_param_check(bytes, from_back, shrink_page_start, shrink_page_bytes)){ + return false; + } + else if(shrink_page_bytes){ + //In UNIX we can decommit and free virtual address space. + return 0 == munmap(shrink_page_start, shrink_page_bytes); + } + else{ + return true; + } +} + inline bool mapped_region::flush(std::size_t mapping_offset, std::size_t numbytes, bool async) { void *addr; - if(!this->priv_flush_param_check(mapping_offset, addr, numbytes)){ + if(m_is_xsi || !this->priv_flush_param_check(mapping_offset, addr, numbytes)){ return false; } //Flush it all - return msync( addr, numbytes, async ? MS_ASYNC : MS_SYNC) == 0; + return msync(addr, numbytes, async ? MS_ASYNC : MS_SYNC) == 0; +} + +inline bool mapped_region::advise(advice_types advice) +{ + int unix_advice = 0; + //Modes; 0: none, 2: posix, 1: madvise + const unsigned int mode_none = 0; + const unsigned int mode_padv = 1; + const unsigned int mode_madv = 2; + unsigned int mode = mode_none; + //Choose advice either from POSIX (preferred) or native Unix + switch(advice){ + case advice_normal: + #if defined(POSIX_MADV_NORMAL) + unix_advice = POSIX_MADV_NORMAL; + mode = mode_padv; + #elif defined(MADV_NORMAL) + unix_advice = MADV_NORMAL; + mode = mode_madv; + #endif + break; + case advice_sequential: + #if defined(POSIX_MADV_SEQUENTIAL) + unix_advice = POSIX_MADV_SEQUENTIAL; + mode = mode_padv; + #elif defined(MADV_SEQUENTIAL) + unix_advice = MADV_SEQUENTIAL; + mode = mode_madv; + #endif + break; + case advice_random: + #if defined(POSIX_MADV_RANDOM) + unix_advice = POSIX_MADV_RANDOM; + mode = mode_padv; + #elif defined(MADV_RANDOM) + unix_advice = MADV_RANDOM; + mode = mode_madv; + #endif + break; + case advice_willneed: + #if defined(POSIX_MADV_WILLNEED) + unix_advice = POSIX_MADV_WILLNEED; + mode = mode_padv; + #elif defined(MADV_WILLNEED) + unix_advice = MADV_WILLNEED; + mode = mode_madv; + #endif + break; + case advice_dontneed: + #if defined(POSIX_MADV_DONTNEED) + unix_advice = POSIX_MADV_DONTNEED; + mode = mode_padv; + #elif defined(MADV_DONTNEED) && defined(BOOST_INTERPROCESS_MADV_DONTNEED_HAS_NONDESTRUCTIVE_SEMANTICS) + unix_advice = MADV_DONTNEED; + mode = mode_madv; + #endif + break; + default: + return false; + } + switch(mode){ + #if defined(POSIX_MADV_NORMAL) + case mode_padv: + return 0 == posix_madvise(this->priv_map_address(), this->priv_map_size(), unix_advice); + #endif + #if defined(MADV_NORMAL) + case mode_madv: + return 0 == madvise( + #if defined(BOOST_INTERPROCESS_MADVISE_USES_CADDR_T) + (caddr_t) + #endif + this->priv_map_address(), this->priv_map_size(), unix_advice); + #endif + default: + return false; + + } } inline void mapped_region::priv_close() diff --git a/include/boost/interprocess/mem_algo/detail/mem_algo_common.hpp b/include/boost/interprocess/mem_algo/detail/mem_algo_common.hpp index 91d7981..203686b 100644 --- a/include/boost/interprocess/mem_algo/detail/mem_algo_common.hpp +++ b/include/boost/interprocess/mem_algo/detail/mem_algo_common.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -40,6 +41,37 @@ namespace boost { namespace interprocess { namespace ipcdetail { +template +class basic_multiallocation_chain + : public boost::container::container_detail:: + basic_multiallocation_chain +{ + BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_multiallocation_chain) + typedef boost::container::container_detail:: + basic_multiallocation_chain base_t; + public: + + basic_multiallocation_chain() + : base_t() + {} + + basic_multiallocation_chain(BOOST_RV_REF(basic_multiallocation_chain) other) + : base_t(::boost::move(static_cast(other))) + {} + + basic_multiallocation_chain& operator=(BOOST_RV_REF(basic_multiallocation_chain) other) + { + this->base_t::operator=(::boost::move(static_cast(other))); + return *this; + } + + void *pop_front() + { + return boost::interprocess::ipcdetail::to_raw_pointer(this->base_t::pop_front()); + } +}; + + //!This class implements several allocation functions shared by different algorithms //!(aligned allocation, multiple allocation...). template @@ -199,7 +231,7 @@ class memory_algorithm_common static void* allocate_aligned (MemoryAlgorithm *memory_algo, size_type nbytes, size_type alignment) { - + //Ensure power of 2 if ((alignment & (alignment - size_type(1u))) != 0){ //Alignment is not power of two @@ -215,7 +247,7 @@ class memory_algorithm_common if(nbytes > UsableByPreviousChunk) nbytes -= UsableByPreviousChunk; - + //We can find a aligned portion if we allocate a block that has alignment //nbytes + alignment bytes or more. size_type minimum_allocation = max_value @@ -436,101 +468,108 @@ class memory_algorithm_common } else{ for(size_type i = 0; i < n_elements; ++i){ + if(multiplication_overflows(elem_sizes[i], sizeof_element)){ + total_request_units = 0; + break; + } elem_units = memory_algo->priv_get_total_units(elem_sizes[i]*sizeof_element); elem_units = ptr_size_units > elem_units ? ptr_size_units : elem_units; + if(sum_overflows(total_request_units, elem_units)){ + total_request_units = 0; + break; + } total_request_units += elem_units; } } multiallocation_chain chain; + if(total_request_units && !multiplication_overflows(total_request_units, Alignment)){ + size_type low_idx = 0; + while(low_idx < n_elements){ + size_type total_bytes = total_request_units*Alignment - AllocatedCtrlBytes + UsableByPreviousChunk; + size_type min_allocation = (!sizeof_element) + ? elem_units + : memory_algo->priv_get_total_units(elem_sizes[low_idx]*sizeof_element); + min_allocation = min_allocation*Alignment - AllocatedCtrlBytes + UsableByPreviousChunk; - size_type low_idx = 0; - while(low_idx < n_elements){ - size_type total_bytes = total_request_units*Alignment - AllocatedCtrlBytes + UsableByPreviousChunk; - size_type min_allocation = (!sizeof_element) - ? elem_units - : memory_algo->priv_get_total_units(elem_sizes[low_idx]*sizeof_element); - min_allocation = min_allocation*Alignment - AllocatedCtrlBytes + UsableByPreviousChunk; - - size_type received_size; - std::pair ret = memory_algo->priv_allocate - (boost::interprocess::allocate_new, min_allocation, total_bytes, received_size, 0); - if(!ret.first){ - break; - } - - block_ctrl *block = memory_algo->priv_get_block(ret.first); - size_type received_units = (size_type)block->m_size; - char *block_address = reinterpret_cast(block); - - size_type total_used_units = 0; -// block_ctrl *prev_block = 0; - while(total_used_units < received_units){ - if(sizeof_element){ - elem_units = memory_algo->priv_get_total_units(elem_sizes[low_idx]*sizeof_element); - elem_units = ptr_size_units > elem_units ? ptr_size_units : elem_units; - } - if(total_used_units + elem_units > received_units) + size_type received_size; + std::pair ret = memory_algo->priv_allocate + (boost::interprocess::allocate_new, min_allocation, total_bytes, received_size, 0); + if(!ret.first){ break; - total_request_units -= elem_units; - //This is the position where the new block must be created - block_ctrl *new_block = reinterpret_cast(block_address); - assert_alignment(new_block); + } - //The last block should take all the remaining space - if((low_idx + 1) == n_elements || - (total_used_units + elem_units + - ((!sizeof_element) - ? elem_units - : std::max(memory_algo->priv_get_total_units(elem_sizes[low_idx+1]*sizeof_element), ptr_size_units)) - ) > received_units){ - //By default, the new block will use the rest of the buffer - new_block->m_size = received_units - total_used_units; - memory_algo->priv_mark_new_allocated_block(new_block); + block_ctrl *block = memory_algo->priv_get_block(ret.first); + size_type received_units = (size_type)block->m_size; + char *block_address = reinterpret_cast(block); - //If the remaining units are bigger than needed and we can - //split it obtaining a new free memory block do it. - if((received_units - total_used_units) >= (elem_units + MemoryAlgorithm::BlockCtrlUnits)){ - size_type shrunk_received; - size_type shrunk_request = elem_units*Alignment - AllocatedCtrlBytes + UsableByPreviousChunk; - bool shrink_ok = shrink - (memory_algo - ,memory_algo->priv_get_user_buffer(new_block) - ,shrunk_request - ,shrunk_request - ,shrunk_received); - (void)shrink_ok; - //Shrink must always succeed with passed parameters - BOOST_ASSERT(shrink_ok); - //Some sanity checks - BOOST_ASSERT(shrunk_request == shrunk_received); - BOOST_ASSERT(elem_units == ((shrunk_request-UsableByPreviousChunk)/Alignment + AllocatedCtrlUnits)); - //"new_block->m_size" must have been reduced to elem_units by "shrink" - BOOST_ASSERT(new_block->m_size == elem_units); - //Now update the total received units with the reduction - received_units = elem_units + total_used_units; + size_type total_used_units = 0; + while(total_used_units < received_units){ + if(sizeof_element){ + elem_units = memory_algo->priv_get_total_units(elem_sizes[low_idx]*sizeof_element); + elem_units = ptr_size_units > elem_units ? ptr_size_units : elem_units; } - } - else{ - new_block->m_size = elem_units; - memory_algo->priv_mark_new_allocated_block(new_block); - } + if(total_used_units + elem_units > received_units) + break; + total_request_units -= elem_units; + //This is the position where the new block must be created + block_ctrl *new_block = reinterpret_cast(block_address); + assert_alignment(new_block); - block_address += new_block->m_size*Alignment; - total_used_units += (size_type)new_block->m_size; - //Check we have enough room to overwrite the intrusive pointer - BOOST_ASSERT((new_block->m_size*Alignment - AllocatedCtrlUnits) >= sizeof(void_pointer)); - void_pointer p = new(memory_algo->priv_get_user_buffer(new_block))void_pointer(0); - chain.push_back(p); - ++low_idx; - //prev_block = new_block; + //The last block should take all the remaining space + if((low_idx + 1) == n_elements || + (total_used_units + elem_units + + ((!sizeof_element) + ? elem_units + : std::max(memory_algo->priv_get_total_units(elem_sizes[low_idx+1]*sizeof_element), ptr_size_units)) + ) > received_units){ + //By default, the new block will use the rest of the buffer + new_block->m_size = received_units - total_used_units; + memory_algo->priv_mark_new_allocated_block(new_block); + + //If the remaining units are bigger than needed and we can + //split it obtaining a new free memory block do it. + if((received_units - total_used_units) >= (elem_units + MemoryAlgorithm::BlockCtrlUnits)){ + size_type shrunk_received; + size_type shrunk_request = elem_units*Alignment - AllocatedCtrlBytes + UsableByPreviousChunk; + bool shrink_ok = shrink + (memory_algo + ,memory_algo->priv_get_user_buffer(new_block) + ,shrunk_request + ,shrunk_request + ,shrunk_received); + (void)shrink_ok; + //Shrink must always succeed with passed parameters + BOOST_ASSERT(shrink_ok); + //Some sanity checks + BOOST_ASSERT(shrunk_request == shrunk_received); + BOOST_ASSERT(elem_units == ((shrunk_request-UsableByPreviousChunk)/Alignment + AllocatedCtrlUnits)); + //"new_block->m_size" must have been reduced to elem_units by "shrink" + BOOST_ASSERT(new_block->m_size == elem_units); + //Now update the total received units with the reduction + received_units = elem_units + total_used_units; + } + } + else{ + new_block->m_size = elem_units; + memory_algo->priv_mark_new_allocated_block(new_block); + } + + block_address += new_block->m_size*Alignment; + total_used_units += (size_type)new_block->m_size; + //Check we have enough room to overwrite the intrusive pointer + BOOST_ASSERT((new_block->m_size*Alignment - AllocatedCtrlUnits) >= sizeof(void_pointer)); + void_pointer p = new(memory_algo->priv_get_user_buffer(new_block))void_pointer(0); + chain.push_back(p); + ++low_idx; + } + //Sanity check + BOOST_ASSERT(total_used_units == received_units); + } + + if(low_idx != n_elements){ + priv_deallocate_many(memory_algo, boost::move(chain)); } - //Sanity check - BOOST_ASSERT(total_used_units == received_units); - } - - if(low_idx != n_elements){ - priv_deallocate_many(memory_algo, boost::move(chain)); } return boost::move(chain); } @@ -538,9 +577,7 @@ class memory_algorithm_common static void priv_deallocate_many(MemoryAlgorithm *memory_algo, multiallocation_chain chain) { while(!chain.empty()){ - void *addr = to_raw_pointer(chain.front()); - chain.pop_front(); - memory_algo->priv_deallocate(addr); + memory_algo->priv_deallocate(to_raw_pointer(chain.pop_front())); } } }; diff --git a/include/boost/interprocess/mem_algo/detail/simple_seq_fit_impl.hpp b/include/boost/interprocess/mem_algo/detail/simple_seq_fit_impl.hpp index c36916b..51fc557 100644 --- a/include/boost/interprocess/mem_algo/detail/simple_seq_fit_impl.hpp +++ b/include/boost/interprocess/mem_algo/detail/simple_seq_fit_impl.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -60,7 +60,7 @@ class simple_seq_fit_impl simple_seq_fit_impl(); simple_seq_fit_impl(const simple_seq_fit_impl &); simple_seq_fit_impl &operator=(const simple_seq_fit_impl &); - + typedef typename boost::intrusive:: pointer_traits::template rebind_pointer::type char_ptr; @@ -96,7 +96,7 @@ class simple_seq_fit_impl //!This block's memory size (including block_ctrl //!header) in BasicSize units size_type m_size; - + size_type get_user_bytes() const { return this->m_size*Alignment - BlockCtrlBytes; } @@ -426,7 +426,7 @@ void simple_seq_fit_impl::shrink_to_fit() (void)addr; BOOST_ASSERT(addr); BOOST_ASSERT(received_size == last_units*Alignment - AllocatedCtrlBytes); - + //Shrink it m_header.m_size /= Alignment; m_header.m_size -= last->m_size; @@ -463,7 +463,7 @@ void *simple_seq_fit_impl:: template inline void simple_seq_fit_impl::priv_add_segment(void *addr, size_type size) -{ +{ algo_impl_t::assert_alignment(addr); //Check size BOOST_ASSERT(!(size < MinBlockSize)); @@ -523,7 +523,7 @@ inline void simple_seq_fit_impl::zero_free_memory() //Iterate through all free portions do{ - //Just clear user the memory part reserved for the user + //Just clear user the memory part reserved for the user std::memset( priv_get_user_buffer(block) , 0 , block->get_user_bytes()); @@ -583,7 +583,7 @@ inline void* simple_seq_fit_impl:: template inline void* simple_seq_fit_impl:: allocate_aligned(size_type nbytes, size_type alignment) -{ +{ //----------------------- boost::interprocess::scoped_lock guard(m_header); //----------------------- @@ -698,7 +698,7 @@ void* simple_seq_fit_impl:: size_type needs_backwards = ipcdetail::get_rounded_size(preferred_size - extra_forward, Alignment); - + if(!only_preferred_backwards){ max_value(ipcdetail::get_rounded_size(min_size - extra_forward, Alignment) ,min_value(prev->get_user_bytes(), needs_backwards)); @@ -710,7 +710,7 @@ void* simple_seq_fit_impl:: if(!priv_expand(reuse_ptr, received_size, received_size, received_size)){ BOOST_ASSERT(0); } - + //We need a minimum size to split the previous one if((prev->get_user_bytes() - needs_backwards) > 2*BlockCtrlBytes){ block_ctrl *new_block = reinterpret_cast @@ -750,9 +750,7 @@ inline void simple_seq_fit_impl:: boost::interprocess::scoped_lock guard(m_header); //----------------------- while(!chain.empty()){ - void *addr = chain.front(); - chain.pop_front(); - this->priv_deallocate(addr); + this->priv_deallocate(to_raw_pointer(chain.pop_front())); } } @@ -969,7 +967,7 @@ inline bool simple_seq_fit_impl:: //We can fill expand. Merge both blocks, block->m_next = next_block->m_next; block->m_size = merged_size; - + //Find the previous free block of next_block block_ctrl *prev = &m_header.m_root; while(ipcdetail::to_raw_pointer(prev->m_next) != next_block){ @@ -978,7 +976,7 @@ inline bool simple_seq_fit_impl:: //Now insert merged block in the free list //This allows reusing allocation logic in this function - m_header.m_allocated -= old_block_size*Alignment; + m_header.m_allocated -= old_block_size*Alignment; prev->m_next = block; //Now use check and allocate to do the allocation logic @@ -992,7 +990,7 @@ inline bool simple_seq_fit_impl:: BOOST_ASSERT(0); return false; } - return true; + return true; } template inline @@ -1071,9 +1069,9 @@ void simple_seq_fit_impl::priv_deallocate(void* addr) size_type total_size = Alignment*block->m_size; BOOST_ASSERT(m_header.m_allocated >= total_size); - + //Update used memory count - m_header.m_allocated -= total_size; + m_header.m_allocated -= total_size; //Let's find the previous and the next block of the block to deallocate //This ordering comparison must be done with original pointers diff --git a/include/boost/interprocess/mem_algo/rbtree_best_fit.hpp b/include/boost/interprocess/mem_algo/rbtree_best_fit.hpp index 7ccc642..f864114 100644 --- a/include/boost/interprocess/mem_algo/rbtree_best_fit.hpp +++ b/include/boost/interprocess/mem_algo/rbtree_best_fit.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -88,8 +88,7 @@ class rbtree_best_fit typedef MutexFamily mutex_family; //!Pointer type to be used with the rest of the Interprocess framework typedef VoidPointer void_pointer; - typedef boost::container::container_detail:: - basic_multiallocation_chain multiallocation_chain; + typedef ipcdetail::basic_multiallocation_chain multiallocation_chain; typedef typename boost::intrusive::pointer_traits::difference_type difference_type; typedef typename boost::make_unsigned::type size_type; @@ -132,7 +131,7 @@ class rbtree_best_fit { return size < block.m_size; } bool operator()(const block_ctrl &block, size_type size) const - { return block.m_size < size; } + { return block.m_size < size; } }; //!Shared mutex to protect memory allocate/deallocate @@ -157,7 +156,7 @@ class rbtree_best_fit } m_header; friend class ipcdetail::memory_algorithm_common; - + typedef ipcdetail::memory_algorithm_common algo_impl_t; public: @@ -339,7 +338,7 @@ class rbtree_best_fit void priv_add_segment(void *addr, size_type size); public: - + static const size_type Alignment = !MemAlignment ? size_type(::boost::alignment_of< ::boost::detail::max_align>::value) : size_type(MemAlignment) @@ -386,7 +385,7 @@ inline typename rbtree_best_fit::size_ty template void rbtree_best_fit:: priv_add_segment(void *addr, size_type size) -{ +{ //Check alignment algo_impl_t::check_alignment(addr); //Check size @@ -570,7 +569,7 @@ void rbtree_best_fit::shrink_to_fit() size_type shrunk_border_offset = (size_type)(reinterpret_cast(last_block) - reinterpret_cast(this)) + EndCtrlBlockBytes; - + block_ctrl *new_end_block = last_block; algo_impl_t::assert_alignment(new_end_block); @@ -672,7 +671,7 @@ bool rbtree_best_fit:: template inline void* rbtree_best_fit:: allocate(size_type nbytes) -{ +{ //----------------------- boost::interprocess::scoped_lock guard(m_header); //----------------------- @@ -884,7 +883,7 @@ void* rbtree_best_fit:: received_size = needs_backwards_aligned + received_size; m_header.m_allocated += needs_backwards_aligned; - + //Check alignment algo_impl_t::assert_alignment(new_block); @@ -1044,7 +1043,7 @@ bool rbtree_best_fit:: //The block must be marked as allocated and the sizes must be equal BOOST_ASSERT(priv_is_allocated_block(block)); //BOOST_ASSERT(old_block_units == priv_tail_size(block)); - + //Put this to a safe value received_size = (old_block_units - AllocatedCtrlUnits)*Alignment + UsableByPreviousChunk; if(received_size >= preferred_size || received_size >= min_size) @@ -1298,7 +1297,7 @@ void* rbtree_best_fit::priv_check_and_al m_header.m_imultiset.erase(it_old); m_header.m_imultiset.insert(m_header.m_imultiset.begin(), *rem_block); } - + } else if (block->m_size >= nunits){ m_header.m_imultiset.erase(it_old); @@ -1318,7 +1317,7 @@ void* rbtree_best_fit::priv_check_and_al //Clear the memory occupied by the tree hook, since this won't be //cleared with zero_free_memory TreeHook *t = static_cast(block); - //Just clear the memory part reserved for the user + //Just clear the memory part reserved for the user std::size_t tree_hook_offset_in_block = (char*)t - (char*)block; //volatile char *ptr = char *ptr = reinterpret_cast(block)+tree_hook_offset_in_block; @@ -1344,7 +1343,7 @@ void rbtree_best_fit::priv_deallocate(vo if(!addr) return; block_ctrl *block = priv_get_block(addr); - + //The blocks must be marked as allocated and the sizes must be equal BOOST_ASSERT(priv_is_allocated_block(block)); // BOOST_ASSERT(block->m_size == priv_tail_size(block)); diff --git a/include/boost/interprocess/mem_algo/simple_seq_fit.hpp b/include/boost/interprocess/mem_algo/simple_seq_fit.hpp index 1085ca0..601c57b 100644 --- a/include/boost/interprocess/mem_algo/simple_seq_fit.hpp +++ b/include/boost/interprocess/mem_algo/simple_seq_fit.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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/include/boost/interprocess/offset_ptr.hpp b/include/boost/interprocess/offset_ptr.hpp index ac8da2c..752c435 100644 --- a/include/boost/interprocess/offset_ptr.hpp +++ b/include/boost/interprocess/offset_ptr.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -44,6 +44,175 @@ struct has_trivial_destructor; namespace interprocess { +/// @cond +namespace ipcdetail { + + template + union offset_ptr_internal + { + explicit offset_ptr_internal(OffsetType off) + : m_offset(off) + {} + OffsetType m_offset; //Distance between this object and pointee address + typename ::boost::aligned_storage + < sizeof(OffsetType) + , (OffsetAlignment == offset_type_alignment) ? + ::boost::alignment_of::value : OffsetAlignment + >::type alignment_helper; + }; + + //Note: using the address of a local variable to point to another address + //is not standard conforming and this can be optimized-away by the compiler. + //Non-inlining is a method to remain illegal but correct + + //Undef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_XXX if your compiler can inline + //this code without breaking the library + + //////////////////////////////////////////////////////////////////////// + // + // offset_ptr_to_raw_pointer + // + //////////////////////////////////////////////////////////////////////// + #define BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_PTR + #define BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_PTR + + template + #ifndef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_PTR + BOOST_INTERPROCESS_NEVER_INLINE + #elif defined(NDEBUG) + inline + #endif + void * offset_ptr_to_raw_pointer(const volatile void *this_ptr, std::size_t offset) + { + typedef pointer_size_t_caster caster_t; + #ifndef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_PTR + if(offset == 1){ + return 0; + } + else{ + caster_t caster((void*)this_ptr); + return caster_t(caster.size() + offset).pointer(); + } + #else + caster_t caster((void*)this_ptr); + return caster_t((caster.size() + offset) & -std::size_t(offset != 1)).pointer(); + #endif + } + + #ifdef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_PTR + #undef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_PTR + #endif + #ifdef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_PTR + #undef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_PTR + #endif + + //////////////////////////////////////////////////////////////////////// + // + // offset_ptr_to_offset + // + //////////////////////////////////////////////////////////////////////// + #define BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_OFF + //Branchless seems slower in x86 + //#define BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF + + template + #ifndef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_OFF + BOOST_INTERPROCESS_NEVER_INLINE + #elif defined(NDEBUG) + inline + #endif + std::size_t offset_ptr_to_offset(const volatile void *ptr, const volatile void *this_ptr) + { + typedef pointer_size_t_caster caster_t; + #ifndef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF + //offset == 1 && ptr != 0 is not legal for this pointer + if(!ptr){ + return 1; + } + else{ + caster_t this_caster((void*)this_ptr); + caster_t ptr_caster((void*)ptr); + std::size_t offset = ptr_caster.size() - this_caster.size(); + BOOST_ASSERT(offset != 1); + return offset; + } + #else + caster_t this_caster((void*)this_ptr); + caster_t ptr_caster((void*)ptr); + std::size_t offset = (ptr_caster.size() - this_caster.size() - 1) & -std::size_t(ptr != 0); + ++offset; + return offset; + #endif + } + + #ifdef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_OFF + #undef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_OFF + #endif + #ifdef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF + #undef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF + #endif + + //////////////////////////////////////////////////////////////////////// + // + // offset_ptr_to_offset_from_other + // + //////////////////////////////////////////////////////////////////////// + #define BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_OFF_FROM_OTHER + //Branchless seems slower in x86 + //#define BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF_FROM_OTHER + + template + #ifndef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_OFF_FROM_OTHER + BOOST_INTERPROCESS_NEVER_INLINE + #elif defined(NDEBUG) + inline + #endif + std::size_t offset_ptr_to_offset_from_other + (const volatile void *this_ptr, const volatile void *other_ptr, std::size_t other_offset) + { + typedef pointer_size_t_caster caster_t; + #ifndef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF_FROM_OTHER + if(other_offset == 1){ + return 1; + } + else{ + caster_t this_caster((void*)this_ptr); + caster_t other_caster((void*)other_ptr); + std::size_t offset = other_caster.size() - this_caster.size() + other_offset; + BOOST_ASSERT(offset != 1); + return offset; + } + #else + caster_t this_caster((void*)this_ptr); + caster_t other_caster((void*)other_ptr); + std::size_t offset = (other_caster.size() - this_caster.size()) & -std::size_t(other_offset != 1); + offset += other_offset; + return offset; + #endif + } + + #ifdef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_OFF_FROM_OTHER + #undef BOOST_INTERPROCESS_OFFSET_PTR_INLINE_TO_OFF_FROM_OTHER + #endif + #ifdef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF_FROM_OTHER + #undef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF_FROM_OTHER + #endif + + //////////////////////////////////////////////////////////////////////// + // + // Let's assume cast to void and cv cast don't change any target address + // + //////////////////////////////////////////////////////////////////////// + template + struct offset_ptr_maintains_address + { + static const bool value = ipcdetail::is_cv_same::value + || ipcdetail::is_cv_same::value; + }; + +} //namespace ipcdetail { +/// @endcond + //!A smart pointer that stores the offset between between the pointer and the //!the object it points. This allows offset allows special properties, since //!the pointer is independent from the address address of the pointee, if the @@ -74,69 +243,111 @@ class offset_ptr public: //Public Functions + //!Default constructor (null pointer). + //!Never throws. + offset_ptr() + : internal(1) + {} + //!Constructor from raw pointer (allows "0" pointer conversion). //!Never throws. - offset_ptr(pointer ptr = 0) { this->set_offset(ptr); } + offset_ptr(pointer ptr) + : internal(static_cast(ipcdetail::offset_ptr_to_offset<0>(ptr, this))) + {} //!Constructor from other pointer. //!Never throws. template offset_ptr( T *ptr , typename ipcdetail::enable_if< ipcdetail::is_convertible >::type * = 0) - { this->set_offset(static_cast(ptr)); } + : internal(static_cast + (ipcdetail::offset_ptr_to_offset<0>(static_cast(ptr), this))) + {} //!Constructor from other offset_ptr //!Never throws. offset_ptr(const offset_ptr& ptr) - { this->set_offset(ptr.get()); } + : internal(static_cast + (ipcdetail::offset_ptr_to_offset_from_other<0>(this, &ptr, ptr.internal.m_offset))) + {} //!Constructor from other offset_ptr. If pointers of pointee types are //!convertible, offset_ptrs will be convertibles. Never throws. - template - offset_ptr( const offset_ptr &ptr - , typename ipcdetail::enable_if< ipcdetail::is_convertible >::type * = 0) - { this->set_offset(static_cast(ptr.get())); } + template + offset_ptr( const offset_ptr &ptr + #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + , typename ipcdetail::enable_if_c< ipcdetail::is_convertible::value + && ipcdetail::offset_ptr_maintains_address::value + >::type * = 0 + #endif + ) + : internal(static_cast + (ipcdetail::offset_ptr_to_offset_from_other<0>(this, &ptr, ptr.get_offset()))) + {} + + #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + + //!Constructor from other offset_ptr. If pointers of pointee types are + //!convertible, offset_ptrs will be convertibles. Never throws. + template + offset_ptr( const offset_ptr &ptr + , typename ipcdetail::enable_if_c< ipcdetail::is_convertible::value + && !ipcdetail::offset_ptr_maintains_address::value + >::type * = 0) + : internal(static_cast + (ipcdetail::offset_ptr_to_offset<0>(static_cast(ptr.get()), this))) + {} + + #endif //!Emulates static_cast operator. //!Never throws. template offset_ptr(const offset_ptr & r, ipcdetail::static_cast_tag) - { this->set_offset(static_cast(r.get())); } + : internal(static_cast + (ipcdetail::offset_ptr_to_offset<0>(static_cast(r.get()), this))) + {} //!Emulates const_cast operator. //!Never throws. template offset_ptr(const offset_ptr & r, ipcdetail::const_cast_tag) - { this->set_offset(const_cast(r.get())); } + : internal(static_cast + (ipcdetail::offset_ptr_to_offset<0>(const_cast(r.get()), this))) + {} //!Emulates dynamic_cast operator. //!Never throws. template offset_ptr(const offset_ptr & r, ipcdetail::dynamic_cast_tag) - { this->set_offset(dynamic_cast(r.get())); } + : internal(static_cast + (ipcdetail::offset_ptr_to_offset<0>(dynamic_cast(r.get()), this))) + {} //!Emulates reinterpret_cast operator. //!Never throws. template offset_ptr(const offset_ptr & r, ipcdetail::reinterpret_cast_tag) - { this->set_offset(reinterpret_cast(r.get())); } + : internal(static_cast + (ipcdetail::offset_ptr_to_offset<0>(reinterpret_cast(r.get()), this))) + {} //!Obtains raw pointer from offset. //!Never throws. - pointer get()const - { return this->to_raw_pointer(); } + pointer get() const + { return (pointer)ipcdetail::offset_ptr_to_raw_pointer<0>(this, this->internal.m_offset); } offset_type get_offset() const - { return internal.m_offset; } + { return this->internal.m_offset; } //!Pointer-like -> operator. It can return 0 pointer. //!Never throws. - pointer operator->() const + pointer operator->() const { return this->get(); } //!Dereferencing operator, if it is a null offset_ptr behavior //! is undefined. Never throws. - reference operator* () const + reference operator* () const { pointer p = this->get(); reference r = *p; @@ -145,26 +356,56 @@ class offset_ptr //!Indexing operator. //!Never throws. - template - reference operator[](T idx) const + reference operator[](difference_type idx) const { return this->get()[idx]; } //!Assignment from pointer (saves extra conversion). //!Never throws. offset_ptr& operator= (pointer from) - { this->set_offset(from); return *this; } + { + this->internal.m_offset = + static_cast(ipcdetail::offset_ptr_to_offset<0>(from, this)); + return *this; + } //!Assignment from other offset_ptr. //!Never throws. - offset_ptr& operator= (const offset_ptr & pt) - { pointer p(pt.get()); (void)p; this->set_offset(p); return *this; } + offset_ptr& operator= (const offset_ptr & ptr) + { + this->internal.m_offset = + static_cast(ipcdetail::offset_ptr_to_offset_from_other<0>(this, &ptr, ptr.internal.m_offset)); + return *this; + } //!Assignment from related offset_ptr. If pointers of pointee types //! are assignable, offset_ptrs will be assignable. Never throws. - template - typename ipcdetail::enable_if, offset_ptr&>::type - operator= (const offset_ptr & ptr) - { this->set_offset(static_cast(ptr.get())); return *this; } + template + #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + typename ipcdetail::enable_if_c< ipcdetail::is_convertible::value + && ipcdetail::offset_ptr_maintains_address::value + , offset_ptr&>::type + #else + offset_ptr& + #endif + operator= (const offset_ptr &ptr) + { + this->internal.m_offset = + static_cast(ipcdetail::offset_ptr_to_offset_from_other<0>(this, &ptr, ptr.get_offset())); + return *this; + } + + #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + template + typename ipcdetail::enable_if_c::value + && !ipcdetail::offset_ptr_maintains_address::value + , offset_ptr&>::type + operator= (const offset_ptr &ptr) + { + this->internal.m_offset = + static_cast(ipcdetail::offset_ptr_to_offset<0>(static_cast(ptr.get()), this)); + return *this; + } + #endif //!offset_ptr += difference_type. //!Never throws. @@ -173,8 +414,7 @@ class offset_ptr //!offset_ptr -= difference_type. //!Never throws. - template - offset_ptr &operator-= (T offset) + offset_ptr &operator-= (difference_type offset) { this->dec_offset(offset * sizeof (PointedType)); return *this; } //!++offset_ptr. @@ -185,7 +425,11 @@ class offset_ptr //!offset_ptr++. //!Never throws. offset_ptr operator++ (int) - { offset_ptr temp(*this); ++*this; return temp; } + { + offset_ptr tmp(*this); + this->inc_offset(sizeof (PointedType)); + return tmp; + } //!--offset_ptr. //!Never throws. @@ -195,17 +439,21 @@ class offset_ptr //!offset_ptr--. //!Never throws. offset_ptr operator-- (int) - { offset_ptr temp(*this); --*this; return temp; } + { + offset_ptr tmp(*this); + this->dec_offset(sizeof (PointedType)); + return tmp; + } //!safe bool conversion operator. //!Never throws. - operator unspecified_bool_type() const - { return this->get()? &self_t::unspecified_bool_type_func : 0; } + operator unspecified_bool_type() const + { return this->internal.m_offset != 1? &self_t::unspecified_bool_type_func : 0; } //!Not operator. Not needed in theory, but improves portability. //!Never throws bool operator! () const - { return this->get() == 0; } + { return this->internal.m_offset == 1; } //!Compatibility with pointer_traits //! @@ -220,23 +468,23 @@ class offset_ptr //!difference_type + offset_ptr //!operation - friend offset_ptr operator+(difference_type diff, const offset_ptr& right) - { offset_ptr tmp(right); tmp += diff; return tmp; } + friend offset_ptr operator+(difference_type diff, offset_ptr right) + { right += diff; return right; } //!offset_ptr + difference_type //!operation - friend offset_ptr operator+(const offset_ptr& left, difference_type diff) - { offset_ptr tmp(left); tmp += diff; return tmp; } + friend offset_ptr operator+(offset_ptr left, difference_type diff) + { left += diff; return left; } //!offset_ptr - diff //!operation - friend offset_ptr operator-(const offset_ptr &left, difference_type diff) - { offset_ptr tmp(left); tmp -= diff; return tmp; } + friend offset_ptr operator-(offset_ptr left, difference_type diff) + { left -= diff; return left; } //!offset_ptr - diff //!operation - friend offset_ptr operator-(difference_type diff, const offset_ptr &right) - { offset_ptr tmp(right); tmp -= diff; return tmp; } + friend offset_ptr operator-(difference_type diff, offset_ptr right) + { right -= diff; return right; } //!offset_ptr - offset_ptr //!operation @@ -309,63 +557,13 @@ class offset_ptr private: /// @cond - - //Note: using the address of a local variable to point to another address - //is not standard conforming and this can be optimized-away by the compiler. - //Non-inlining is a method to remain illegal and correct - #if defined(_MSC_VER) - __declspec(noinline) //this workaround is needed for MSVC compilers - #elif defined (__GNUC__)//this workaround is needed for GCC - __attribute__((__noinline__)) - #endif - void set_offset(const PointedType *ptr) - { - #if defined (__GNUC__) - //asm(""); //Prevents the function to be optimized-away (provokes an special "side-effect") - #endif - //offset == 1 && ptr != 0 is not legal for this pointer - if(!ptr){ - internal.m_offset = 1; - } - else{ - internal.m_offset = (OffsetType)((const char*)ptr - (const char*)(this)); - BOOST_ASSERT(internal.m_offset != 1); - } - } - - #if defined(_MSC_VER) && (_MSC_VER >= 1400) - __declspec(noinline) - #elif defined (__GNUC__) - __attribute__((__noinline__)) - #endif - PointedType * to_raw_pointer() const - { - #if defined (__GNUC__) - //asm(""); //Prevents the function to be optimized-away (provokes an special "side-effect") - #endif - return static_cast( - static_cast( - (internal.m_offset == 1) ? - 0 : - (const_cast(reinterpret_cast(this)) + internal.m_offset) - ) - ); - } - void inc_offset(DifferenceType bytes) { internal.m_offset += bytes; } void dec_offset(DifferenceType bytes) { internal.m_offset -= bytes; } - union internal_type{ - OffsetType m_offset; //Distance between this object and pointee address - typename ::boost::aligned_storage - < sizeof(OffsetType) - , (OffsetAlignment == offset_type_alignment) ? - ::boost::alignment_of::value : OffsetAlignment - >::type alignment_helper; - } internal; + ipcdetail::offset_ptr_internal internal; /// @endcond }; @@ -387,36 +585,36 @@ inline std::basic_istream & operator>> template inline boost::interprocess::offset_ptr static_pointer_cast(const boost::interprocess::offset_ptr & r) -{ +{ return boost::interprocess::offset_ptr - (r, boost::interprocess::ipcdetail::static_cast_tag()); + (r, boost::interprocess::ipcdetail::static_cast_tag()); } //!Simulation of const_cast between pointers. Never throws. template inline boost::interprocess::offset_ptr const_pointer_cast(const boost::interprocess::offset_ptr & r) -{ +{ return boost::interprocess::offset_ptr - (r, boost::interprocess::ipcdetail::const_cast_tag()); + (r, boost::interprocess::ipcdetail::const_cast_tag()); } //!Simulation of dynamic_cast between pointers. Never throws. template inline boost::interprocess::offset_ptr dynamic_pointer_cast(const boost::interprocess::offset_ptr & r) -{ +{ return boost::interprocess::offset_ptr - (r, boost::interprocess::ipcdetail::dynamic_cast_tag()); + (r, boost::interprocess::ipcdetail::dynamic_cast_tag()); } //!Simulation of reinterpret_cast between pointers. Never throws. template inline boost::interprocess::offset_ptr reinterpret_pointer_cast(const boost::interprocess::offset_ptr & r) -{ +{ return boost::interprocess::offset_ptr - (r, boost::interprocess::ipcdetail::reinterpret_cast_tag()); + (r, boost::interprocess::ipcdetail::reinterpret_cast_tag()); } } //namespace interprocess { @@ -437,17 +635,17 @@ struct has_trivial_destructor< boost::interprocess::offset_ptr > static const bool value = true; }; -//#if !defined(_MSC_VER) || (_MSC_VER >= 1400) + namespace interprocess { -//#endif + //!to_raw_pointer() enables boost::mem_fn to recognize offset_ptr. //!Never throws. template inline T * to_raw_pointer(boost::interprocess::offset_ptr const & p) -{ return p.get(); } -//#if !defined(_MSC_VER) || (_MSC_VER >= 1400) +{ return ipcdetail::to_raw_pointer(p); } + } //namespace interprocess -//#endif + /// @endcond } //namespace boost { @@ -479,28 +677,34 @@ struct pointer_plus_bits; template struct pointer_plus_bits, NumBits> { - typedef boost::interprocess::offset_ptr pointer; + typedef boost::interprocess::offset_ptr pointer; + typedef ::boost::interprocess::pointer_size_t_caster caster_t; //Bits are stored in the lower bits of the pointer except the LSB, //because this bit is used to represent the null pointer. - static const std::size_t Mask = ((std::size_t(1) << NumBits)-1)<<1u; + static const std::size_t Mask = ((std::size_t(1) << NumBits) - 1) << 1u; static pointer get_pointer(const pointer &n) - { return reinterpret_cast(std::size_t(n.get()) & ~std::size_t(Mask)); } - - static void set_pointer(pointer &n, pointer p) { - std::size_t pint = std::size_t(p.get()); - BOOST_ASSERT(0 == (std::size_t(pint) & Mask)); - n = reinterpret_cast(pint | (std::size_t(n.get()) & std::size_t(Mask))); + caster_t caster(n.get()); + return pointer(caster_t(caster.size() & ~Mask).pointer()); + } + + static void set_pointer(pointer &n, const pointer &p) + { + caster_t n_caster(n.get()); + caster_t p_caster(p.get()); + BOOST_ASSERT(0 == (p_caster.size() & Mask)); + n = caster_t(p_caster.size() | (n_caster.size() & Mask)).pointer(); } static std::size_t get_bits(const pointer &n) - { return(std::size_t(n.get()) & std::size_t(Mask)) >> 1u; } + { return (caster_t(n.get()).size() & Mask) >> 1u; } static void set_bits(pointer &n, std::size_t b) { BOOST_ASSERT(b < (std::size_t(1) << NumBits)); - n = reinterpret_cast(std::size_t(get_pointer(n).get()) | (b << 1u)); + caster_t n_caster(n.get()); + n = caster_t((n_caster.size() & ~Mask) | (b << 1u)).pointer(); } }; @@ -510,8 +714,6 @@ struct pointer_plus_bits, NumBits> template struct pointer_to_other; - - //Backwards compatibility with pointer_to_other template struct pointer_to_other diff --git a/include/boost/interprocess/permissions.hpp b/include/boost/interprocess/permissions.hpp index 745f8a8..4266b24 100644 --- a/include/boost/interprocess/permissions.hpp +++ b/include/boost/interprocess/permissions.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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/include/boost/interprocess/segment_manager.hpp b/include/boost/interprocess/segment_manager.hpp index 8680a95..61c9367 100644 --- a/include/boost/interprocess/segment_manager.hpp +++ b/include/boost/interprocess/segment_manager.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -69,9 +69,9 @@ class segment_manager_base typedef typename MemoryAlgorithm::void_pointer void_pointer; typedef typename MemoryAlgorithm::mutex_family mutex_family; typedef MemoryAlgorithm memory_algorithm; - + /// @cond - + //Experimental. Don't use typedef typename MemoryAlgorithm::multiallocation_chain multiallocation_chain; typedef typename MemoryAlgorithm::difference_type difference_type; @@ -165,7 +165,7 @@ class segment_manager_base //!Allocates nbytes bytes. Throws boost::interprocess::bad_alloc //!on failure void * allocate(size_type nbytes) - { + { void * ret = MemoryAlgorithm::allocate(nbytes); if(!ret) throw bad_alloc(); @@ -180,7 +180,7 @@ class segment_manager_base //!Allocates nbytes bytes. This function is only used in //!single-segment management. Throws bad_alloc when fails void * allocate_aligned(size_type nbytes, size_type alignment) - { + { void * ret = MemoryAlgorithm::allocate_aligned(nbytes, alignment); if(!ret) throw bad_alloc(); @@ -293,7 +293,7 @@ class segment_manager_base void prot_anonymous_destroy(const void *object, ipcdetail::in_place_interface &table) { - //Get control data from associated with this object + //Get control data from associated with this object typedef ipcdetail::block_header block_header_t; block_header_t *ctrl_data = block_header_t::block_header_from_value(object, table.size, table.alignment); @@ -407,7 +407,7 @@ class segment_manager //!"size" is the size of the memory segment where //!the segment manager is being constructed. //!Can throw - segment_manager(size_type size) + explicit segment_manager(size_type size) : Base(size, priv_get_reserved_bytes()) , m_header(static_cast(get_this_pointer())) { @@ -446,7 +446,7 @@ class segment_manager //!Returns throwing "construct" proxy //!object template - typename construct_proxy::type + typename construct_proxy::type construct(char_ptr_holder_t name) { return typename construct_proxy::type (this, name, false, true); } @@ -466,27 +466,27 @@ class segment_manager //!Returns no throwing "search or construct" //!proxy object template - typename construct_proxy::type + typename construct_proxy::type find_or_construct(char_ptr_holder_t name, std::nothrow_t) { return typename construct_proxy::type (this, name, true, false); } //!Returns throwing "construct from iterators" proxy object template - typename construct_iter_proxy::type + typename construct_iter_proxy::type construct_it(char_ptr_holder_t name) { return typename construct_iter_proxy::type (this, name, false, true); } //!Returns throwing "search or construct from iterators" //!proxy object template - typename construct_iter_proxy::type + typename construct_iter_proxy::type find_or_construct_it(char_ptr_holder_t name) { return typename construct_iter_proxy::type (this, name, true, true); } //!Returns no throwing "construct from iterators" //!proxy object template - typename construct_iter_proxy::type + typename construct_iter_proxy::type construct_it(char_ptr_holder_t name, std::nothrow_t) { return typename construct_iter_proxy::type (this, name, false, false); } @@ -575,18 +575,18 @@ class segment_manager //!creation of "num" named objects in the managed memory segment. //!Can throw boost::interprocess::bad_alloc if there is no enough memory. void reserve_named_objects(size_type num) - { + { //------------------------------- scoped_lock guard(m_header); //------------------------------- - m_header.m_named_index.reserve(num); + m_header.m_named_index.reserve(num); } //!Preallocates needed index resources to optimize the //!creation of "num" unique objects in the managed memory segment. //!Can throw boost::interprocess::bad_alloc if there is no enough memory. void reserve_unique_objects(size_type num) - { + { //------------------------------- scoped_lock guard(m_header); //------------------------------- @@ -596,32 +596,32 @@ class segment_manager //!Calls shrink_to_fit in both named and unique object indexes //!to try to free unused memory from those indexes. void shrink_to_fit_indexes() - { + { //------------------------------- scoped_lock guard(m_header); //------------------------------- - m_header.m_named_index.shrink_to_fit(); - m_header.m_unique_index.shrink_to_fit(); + m_header.m_named_index.shrink_to_fit(); + m_header.m_unique_index.shrink_to_fit(); } //!Returns the number of named objects stored in //!the segment. size_type get_num_named_objects() - { + { //------------------------------- scoped_lock guard(m_header); //------------------------------- - return m_header.m_named_index.size(); + return m_header.m_named_index.size(); } //!Returns the number of unique objects stored in //!the segment. size_type get_num_unique_objects() - { + { //------------------------------- scoped_lock guard(m_header); //------------------------------- - return m_header.m_unique_index.size(); + return m_header.m_unique_index.size(); } //!Obtains the minimum size needed by the @@ -713,7 +713,7 @@ class segment_manager //!returned pair is 0. template std::pair priv_find_impl (const CharType* name, bool lock) - { + { //The name can't be null, no anonymous object can be found by name BOOST_ASSERT(name != 0); ipcdetail::placement_destroy table; @@ -805,7 +805,7 @@ class segment_manager return 0; } CharType *name = static_cast(ctrl_data->template name()); - + //Sanity checks BOOST_ASSERT(ctrl_data->sizeof_char() == sizeof(CharType)); BOOST_ASSERT(ctrl_data->m_num_char == std::char_traits::length(name)); @@ -951,7 +951,7 @@ class segment_manager typedef ipcdetail::index_key index_key_t; typedef typename index_type::iterator index_it; typedef typename index_type::value_type intrusive_value_type; - + //------------------------------- scoped_lock guard(m_header); //------------------------------- @@ -972,7 +972,7 @@ class segment_manager void *memory = iv; void *values = ctrl_data->value(); std::size_t num = ctrl_data->m_value_bytes/table.size; - + //Sanity check BOOST_ASSERT((ctrl_data->m_value_bytes % table.size) == 0); BOOST_ASSERT(sizeof(CharT) == ctrl_data->sizeof_char()); @@ -1184,7 +1184,7 @@ class segment_manager //the memory allocation as the intrusive value is built in that //memory value_eraser v_eraser(index, it); - + //Construct array, this can throw ipcdetail::array_construct(ptr, num, table); @@ -1197,7 +1197,7 @@ class segment_manager //!Generic named new function for //!named functions template - void * priv_generic_named_construct(unsigned char type, + void * priv_generic_named_construct(unsigned char type, const CharT *name, size_type num, bool try2find, @@ -1346,7 +1346,7 @@ class segment_manager { named_index_t m_named_index; unique_index_t m_unique_index; - + header_t(Base *restricted_segment_mngr) : m_named_index (restricted_segment_mngr) , m_unique_index(restricted_segment_mngr) diff --git a/include/boost/interprocess/shared_memory_object.hpp b/include/boost/interprocess/shared_memory_object.hpp index f3bc7ba..c501ee1 100644 --- a/include/boost/interprocess/shared_memory_object.hpp +++ b/include/boost/interprocess/shared_memory_object.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -87,10 +87,10 @@ class shared_memory_object //!After the call, "moved" does not represent any shared memory. //!Does not throw shared_memory_object &operator=(BOOST_RV_REF(shared_memory_object) moved) - { + { shared_memory_object tmp(boost::move(moved)); this->swap(tmp); - return *this; + return *this; } //!Swaps the shared_memory_objects. Does not throw @@ -99,7 +99,7 @@ class shared_memory_object //!Erases a shared memory object from the system. //!Returns false on error. Never throws static bool remove(const char *name); - + //!Sets the size of the shared memory mapping void truncate(offset_t length); @@ -157,10 +157,10 @@ inline bool shared_memory_object::get_size(offset_t &size) const { return ipcdetail::get_file_size((file_handle_t)m_handle, size); } inline void shared_memory_object::swap(shared_memory_object &other) -{ +{ std::swap(m_handle, other.m_handle); std::swap(m_mode, other.m_mode); - m_filename.swap(other.m_filename); + m_filename.swap(other.m_filename); } inline mapping_handle_t shared_memory_object::get_mapping_handle() const diff --git a/include/boost/interprocess/smart_ptr/deleter.hpp b/include/boost/interprocess/smart_ptr/deleter.hpp index 3a07ccd..8447bf1 100644 --- a/include/boost/interprocess/smart_ptr/deleter.hpp +++ b/include/boost/interprocess/smart_ptr/deleter.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2011. +// (C) Copyright Ion Gaztanaga 2007-2012. // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/include/boost/interprocess/smart_ptr/detail/shared_count.hpp b/include/boost/interprocess/smart_ptr/detail/shared_count.hpp index 7daaee6..f0006fb 100644 --- a/include/boost/interprocess/smart_ptr/detail/shared_count.hpp +++ b/include/boost/interprocess/smart_ptr/detail/shared_count.hpp @@ -4,7 +4,7 @@ // // (C) Copyright Peter Dimov and Multi Media Ltd. 2001, 2002, 2003 // (C) Copyright Peter Dimov 2004-2005 -// (C) Copyright Ion Gaztanaga 2006-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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) // @@ -116,7 +116,7 @@ class shared_count } ~shared_count() // nothrow - { + { if(m_pi) m_pi->release(); } diff --git a/include/boost/interprocess/smart_ptr/detail/sp_counted_base.hpp b/include/boost/interprocess/smart_ptr/detail/sp_counted_base.hpp index 24d96ee..d03965c 100644 --- a/include/boost/interprocess/smart_ptr/detail/sp_counted_base.hpp +++ b/include/boost/interprocess/smart_ptr/detail/sp_counted_base.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2011. +// (C) Copyright Ion Gaztanaga 2007-2012. // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/include/boost/interprocess/smart_ptr/detail/sp_counted_base_atomic.hpp b/include/boost/interprocess/smart_ptr/detail/sp_counted_base_atomic.hpp index edb39ee..74f65f1 100644 --- a/include/boost/interprocess/smart_ptr/detail/sp_counted_base_atomic.hpp +++ b/include/boost/interprocess/smart_ptr/detail/sp_counted_base_atomic.hpp @@ -9,7 +9,7 @@ // Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd. // Copyright 2004-2005 Peter Dimov -// Copyright 2007-2011 Ion Gaztanaga +// Copyright 2007-2012 Ion Gaztanaga // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at diff --git a/include/boost/interprocess/smart_ptr/enable_shared_from_this.hpp b/include/boost/interprocess/smart_ptr/enable_shared_from_this.hpp index 9c8c791..d9f16ae 100644 --- a/include/boost/interprocess/smart_ptr/enable_shared_from_this.hpp +++ b/include/boost/interprocess/smart_ptr/enable_shared_from_this.hpp @@ -3,7 +3,7 @@ // This file is the adaptation for Interprocess of boost/enable_shared_from_this.hpp // // (C) Copyright Peter Dimov 2002 -// (C) Copyright Ion Gaztanaga 2006. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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/include/boost/interprocess/smart_ptr/intrusive_ptr.hpp b/include/boost/interprocess/smart_ptr/intrusive_ptr.hpp index f6d5c8b..897c5da 100644 --- a/include/boost/interprocess/smart_ptr/intrusive_ptr.hpp +++ b/include/boost/interprocess/smart_ptr/intrusive_ptr.hpp @@ -3,7 +3,7 @@ // This file is the adaptation for Interprocess of boost/intrusive_ptr.hpp // // (C) Copyright Peter Dimov 2001, 2002 -// (C) Copyright Ion Gaztanaga 2006. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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) // @@ -125,7 +125,7 @@ class intrusive_ptr this_type(rhs).swap(*this); return *this; } - + //!Returns a reference to the internal pointer. //!Does not throw pointer &get() @@ -219,9 +219,9 @@ bool operator!=(const typename intrusive_ptr::pointer &a, template inline bool operator<(intrusive_ptr const & a, intrusive_ptr const & b) -{ +{ return std::less::pointer>() - (a.get(), b.get()); + (a.get(), b.get()); } //!Exchanges the contents of the two intrusive_ptrs. diff --git a/include/boost/interprocess/smart_ptr/scoped_ptr.hpp b/include/boost/interprocess/smart_ptr/scoped_ptr.hpp index a3755d3..8a2ba36 100644 --- a/include/boost/interprocess/smart_ptr/scoped_ptr.hpp +++ b/include/boost/interprocess/smart_ptr/scoped_ptr.hpp @@ -4,7 +4,7 @@ // // (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. // (C) Copyright Peter Dimov 2001, 2002 -// (C) Copyright Ion Gaztanaga 2006. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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/include/boost/interprocess/smart_ptr/shared_ptr.hpp b/include/boost/interprocess/smart_ptr/shared_ptr.hpp index 5ede547..302eb14 100644 --- a/include/boost/interprocess/smart_ptr/shared_ptr.hpp +++ b/include/boost/interprocess/smart_ptr/shared_ptr.hpp @@ -4,7 +4,7 @@ // // (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. // (C) Copyright Peter Dimov 2001, 2002, 2003 -// (C) Copyright Ion Gaztanaga 2006-2011. +// (C) Copyright Ion Gaztanaga 2006-2012. // 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) @@ -52,7 +52,7 @@ inline void sp_enable_shared_from_this (shared_count const & pn ,enable_shared_from_this *pe ,T *ptr) - + { (void)ptr; if(pe != 0){ @@ -125,7 +125,7 @@ class shared_ptr //!Requirements: Deleter and A's copy constructor must not throw. explicit shared_ptr(const pointer&p, const VoidAllocator &a = VoidAllocator(), const Deleter &d = Deleter()) : m_pn(p, a, d) - { + { //Check that the pointer passed is of the same type that //the pointer the allocator defines or it's a raw pointer typedef typename boost::intrusive:: @@ -223,15 +223,15 @@ class shared_ptr //!This is equivalent to: //!this_type().swap(*this); void reset() - { - this_type().swap(*this); + { + this_type().swap(*this); } //!This is equivalent to: //!this_type(p, a, d).swap(*this); template void reset(const Pointer &p, const VoidAllocator &a = VoidAllocator(), const Deleter &d = Deleter()) - { + { //Check that the pointer passed is of the same type that //the pointer the allocator defines or it's a raw pointer typedef typename boost::intrusive:: @@ -239,7 +239,7 @@ class shared_ptr rebind_pointer::type ParameterPointer; BOOST_STATIC_ASSERT((ipcdetail::is_same::value) || (ipcdetail::is_pointer::value)); - this_type(p, a, d).swap(*this); + this_type(p, a, d).swap(*this); } template diff --git a/include/boost/interprocess/smart_ptr/unique_ptr.hpp b/include/boost/interprocess/smart_ptr/unique_ptr.hpp index 89cdb1e..e6503e2 100644 --- a/include/boost/interprocess/smart_ptr/unique_ptr.hpp +++ b/include/boost/interprocess/smart_ptr/unique_ptr.hpp @@ -5,7 +5,7 @@ // This file is the adaptation for Interprocess of // Howard Hinnant's unique_ptr emulation code. // -// (C) Copyright Ion Gaztanaga 2006. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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) // @@ -272,7 +272,7 @@ class unique_ptr //!Returns: A reference to the stored deleter. //! //!Throws: nothing. - deleter_reference get_deleter() + deleter_reference get_deleter() { return ptr_.second(); } //!Returns: A const reference to the stored deleter. @@ -328,7 +328,7 @@ class unique_ptr BOOST_MOVABLE_BUT_NOT_COPYABLE(unique_ptr) template unique_ptr(unique_ptr&); template unique_ptr(U&, typename ipcdetail::unique_ptr_error::type = 0); - + template unique_ptr& operator=(unique_ptr&); template typename ipcdetail::unique_ptr_error::type operator=(U&); /// @endcond diff --git a/include/boost/interprocess/smart_ptr/weak_ptr.hpp b/include/boost/interprocess/smart_ptr/weak_ptr.hpp index 5202ede..99c8a63 100644 --- a/include/boost/interprocess/smart_ptr/weak_ptr.hpp +++ b/include/boost/interprocess/smart_ptr/weak_ptr.hpp @@ -3,7 +3,7 @@ // This file is the adaptation for Interprocess of boost/weak_ptr.hpp // // (C) Copyright Peter Dimov 2001, 2002, 2003 -// (C) Copyright Ion Gaztanaga 2006-2011. +// (C) Copyright Ion Gaztanaga 2006-2012. // 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) @@ -99,7 +99,7 @@ class weak_ptr template weak_ptr(weak_ptr const & r) : m_pn(r.m_pn) // never throws - { + { //Construct a temporary shared_ptr so that nobody //can destroy the value while constructing this const shared_ptr &ref = r.lock(); @@ -126,7 +126,7 @@ class weak_ptr //!implied guarantees) via different means, without creating a temporary. template weak_ptr & operator=(weak_ptr const & r) // never throws - { + { //Construct a temporary shared_ptr so that nobody //can destroy the value while constructing this const shared_ptr &ref = r.lock(); @@ -174,7 +174,7 @@ class weak_ptr //!testing purposes, not for production code. long use_count() const // never throws { return m_pn.use_count(); } - + //!Returns: Returns: use_count() == 0. //! //!Throws: nothing. @@ -199,7 +199,7 @@ class weak_ptr template bool _internal_less(weak_ptr const & rhs) const { return m_pn < rhs.m_pn; } - + template void _internal_assign(const ipcdetail::shared_count & pn2) { diff --git a/include/boost/interprocess/streams/bufferstream.hpp b/include/boost/interprocess/streams/bufferstream.hpp index 3ae9f5e..2ef0ec2 100644 --- a/include/boost/interprocess/streams/bufferstream.hpp +++ b/include/boost/interprocess/streams/bufferstream.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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,7 +8,7 @@ // ////////////////////////////////////////////////////////////////////////////// // -// This file comes from SGI's sstream file. Modified by Ion Gaztanaga 2005. +// This file comes from SGI's sstream file. Modified by Ion Gaztanaga 2005-2012. // Changed internal SGI string to a buffer. Added efficient // internal buffer get/set/swap functions, so that we can obtain/establish the // internal buffer without any reallocation or copy. Kill those temporaries! @@ -42,7 +42,7 @@ #include #include #include -#include // char traits +#include // char traits #include // ptrdiff_t #include #include @@ -177,7 +177,7 @@ class basic_bufferbuf { bool in = false; bool out = false; - + const std::ios_base::openmode inout = std::ios_base::in | std::ios_base::out; diff --git a/include/boost/interprocess/streams/vectorstream.hpp b/include/boost/interprocess/streams/vectorstream.hpp index 3cee720..0c9f540 100644 --- a/include/boost/interprocess/streams/vectorstream.hpp +++ b/include/boost/interprocess/streams/vectorstream.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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,7 +8,7 @@ // ////////////////////////////////////////////////////////////////////////////// // -// This file comes from SGI's sstream file. Modified by Ion Gaztanaga 2005. +// This file comes from SGI's sstream file. Modified by Ion Gaztanaga 2005-2012. // Changed internal SGI string to a generic, templatized vector. Added efficient // internal buffer get/set/swap functions, so that we can obtain/establish the // internal buffer without any reallocation or copy. Kill those temporaries! @@ -43,7 +43,7 @@ #include #include #include -#include // char traits +#include // char traits #include // ptrdiff_t #include #include @@ -100,7 +100,7 @@ class basic_vectorbuf //!This function resets the read/write position in the stream. //!Does not throw. void swap_vector(vector_type &vect) - { + { if (this->m_mode & std::ios_base::out){ //Update high water if necessary //And resize vector to remove extra size @@ -119,7 +119,7 @@ class basic_vectorbuf //!Returns a const reference to the internal vector. //!Does not throw. const vector_type &vector() const - { + { if (this->m_mode & std::ios_base::out){ if (mp_high_water < base_t::pptr()){ //Restore the vector's size if necessary diff --git a/include/boost/interprocess/sync/detail/condition_algorithm_8a.hpp b/include/boost/interprocess/sync/detail/condition_algorithm_8a.hpp index eaad671..09643b4 100644 --- a/include/boost/interprocess/sync/detail/condition_algorithm_8a.hpp +++ b/include/boost/interprocess/sync/detail/condition_algorithm_8a.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -14,6 +14,7 @@ #include #include #include +#include #include namespace boost { @@ -161,6 +162,15 @@ namespace ipcdetail { // mutex_type &get_mtx_unblock_lock() // }; // +// Must be initialized as following +// +// get_nwaiters_blocked() == 0 +// get_nwaiters_gone() == 0 +// get_nwaiters_to_unblock() == 0 +// get_sem_block_queue() == initial count 0 +// get_sem_block_lock() == initial count 1 +// get_mtx_unblock_lock() (unlocked) +// template class condition_algorithm_8a { @@ -174,16 +184,10 @@ class condition_algorithm_8a typedef typename ConditionMembers::mutex_type mutex_type; typedef typename ConditionMembers::integer_type integer_type; - // nwaiters_blocked == 0 - // nwaiters_gone() == 0 - // nwaiters_to_unblock == 0 - // sem_block_queue() == initial count 0 - // sem_block_lock() == initial count 1 - // mtx_unblock_lock (unlocked) - public: - template - static bool wait (ConditionMembers &data, bool timeout_enabled, const boost::posix_time::ptime &abs_time, InterprocessMutex &mut); + template + static bool wait ( ConditionMembers &data, Lock &lock + , bool timeout_enabled, const boost::posix_time::ptime &abs_time); static void signal(ConditionMembers &data, bool broadcast); }; @@ -235,9 +239,13 @@ inline void condition_algorithm_8a::signal(ConditionMembers &d } template -template +template inline bool condition_algorithm_8a::wait - (ConditionMembers &data, bool tout_enabled, const boost::posix_time::ptime &abs_time, InterprocessMutex &mtxExternal) + ( ConditionMembers &data + , Lock &lock + , bool tout_enabled + , const boost::posix_time::ptime &abs_time + ) { //Initialize to avoid warnings integer_type nsignals_was_left = 0; @@ -247,19 +255,13 @@ inline bool condition_algorithm_8a::wait ++data.get_nwaiters_blocked(); data.get_sem_block_lock().post(); - struct scoped_unlock - { - InterprocessMutex & mut; - scoped_unlock(InterprocessMutex & m) - : mut(m) - { m.unlock(); } + //Unlock external lock and program for relock + lock_inverter inverted_lock(lock); + scoped_lock > external_unlock(inverted_lock); - ~scoped_unlock() - { mut.lock(); } - } unlocker(mtxExternal); - - - bool bTimedOut = tout_enabled ? !data.get_sem_block_queue().timed_wait(abs_time) : (data.get_sem_block_queue().wait(), false); + bool bTimedOut = tout_enabled + ? !data.get_sem_block_queue().timed_wait(abs_time) + : (data.get_sem_block_queue().wait(), false); { scoped_lock locker(data.get_mtx_unblock_lock()); @@ -290,7 +292,7 @@ inline bool condition_algorithm_8a::wait data.get_nwaiters_gone() = 0; } //locker's destructor triggers data.get_mtx_unblock_lock().unlock() - } + } if ( 1 == nsignals_was_left ) { if ( 0 != nwaiters_was_gone ) { @@ -302,11 +304,87 @@ inline bool condition_algorithm_8a::wait data.get_sem_block_lock().post(); // open the gate } - //mtxExternal.lock(); called from unlocker + //lock.lock(); called from unlocker destructor return ( bTimedOut ) ? false : true; } + +template +class condition_8a_wrapper +{ + //Non-copyable + condition_8a_wrapper(const condition_8a_wrapper &); + condition_8a_wrapper &operator=(const condition_8a_wrapper &); + + ConditionMembers m_data; + typedef ipcdetail::condition_algorithm_8a algo_type; + + public: + + condition_8a_wrapper(){} + + ~condition_8a_wrapper(){} + + ConditionMembers & get_members() + { return m_data; } + + const ConditionMembers & get_members() const + { return m_data; } + + void notify_one() + { algo_type::signal(m_data, false); } + + void notify_all() + { algo_type::signal(m_data, true); } + + template + void wait(L& lock) + { + if (!lock) + throw lock_exception(); + algo_type::wait(m_data, lock, false, boost::posix_time::ptime()); + } + + template + void wait(L& lock, Pr pred) + { + if (!lock) + throw lock_exception(); + + while (!pred()) + algo_type::wait(m_data, lock, false, boost::posix_time::ptime()); + } + + template + bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time) + { + if(abs_time == boost::posix_time::pos_infin){ + this->wait(lock); + return true; + } + if (!lock) + throw lock_exception(); + return algo_type::wait(m_data, lock, true, abs_time); + } + + template + bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred) + { + if(abs_time == boost::posix_time::pos_infin){ + this->wait(lock, pred); + return true; + } + if (!lock) + throw lock_exception(); + while (!pred()){ + if (!algo_type::wait(m_data, lock, true, abs_time)) + return pred(); + } + return true; + } +}; + } //namespace ipcdetail } //namespace interprocess } //namespace boost diff --git a/include/boost/interprocess/sync/detail/condition_any_algorithm.hpp b/include/boost/interprocess/sync/detail/condition_any_algorithm.hpp new file mode 100644 index 0000000..a276f82 --- /dev/null +++ b/include/boost/interprocess/sync/detail/condition_any_algorithm.hpp @@ -0,0 +1,224 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2012-2012. 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_DETAIL_CONDITION_ANY_ALGORITHM_HPP +#define BOOST_INTERPROCESS_DETAIL_CONDITION_ANY_ALGORITHM_HPP + +#include +#include +#include +#include +#include + +namespace boost { +namespace interprocess { +namespace ipcdetail { + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +// +// Condition variable 'any' (able to use any type of external mutex) +// +// The code is based on Howard E. Hinnant's ISO C++ N2406 paper. +// Many thanks to Howard for his support and comments. +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + +// Required interface for ConditionAnyMembers +// class ConditionAnyMembers +// { +// typedef implementation_defined mutex_type; +// typedef implementation_defined condvar_type; +// +// condvar &get_condvar() +// mutex_type &get_mutex() +// }; +// +// Must be initialized as following +// +// get_condvar() [no threads blocked] +// get_mutex() [unlocked] + +template +class condition_any_algorithm +{ + private: + condition_any_algorithm(); + ~condition_any_algorithm(); + condition_any_algorithm(const condition_any_algorithm &); + condition_any_algorithm &operator=(const condition_any_algorithm &); + + typedef typename ConditionAnyMembers::mutex_type mutex_type; + typedef typename ConditionAnyMembers::condvar_type condvar_type; + + template + static void do_wait(ConditionAnyMembers &data, Lock& lock); + + template + static bool do_timed_wait(ConditionAnyMembers &data, Lock& lock, const boost::posix_time::ptime &abs_time); + + public: + template + static bool wait ( ConditionAnyMembers &data, Lock &mut + , bool timeout_enabled, const boost::posix_time::ptime &abs_time); + static void signal( ConditionAnyMembers &data, bool broadcast); +}; + +template +void condition_any_algorithm::signal(ConditionAnyMembers &data, bool broadcast) +{ + scoped_lock internal_lock(data.get_mutex()); + if(broadcast){ + data.get_condvar().notify_all(); + } + else{ + data.get_condvar().notify_one(); + } +} + +template +template +bool condition_any_algorithm::wait + ( ConditionAnyMembers &data + , Lock &lock + , bool tout_enabled + , const boost::posix_time::ptime &abs_time) +{ + if(tout_enabled){ + return condition_any_algorithm::do_timed_wait(data, lock, abs_time); + } + else{ + condition_any_algorithm::do_wait(data, lock); + return true; + } +} + +template +template +void condition_any_algorithm::do_wait + (ConditionAnyMembers &data, Lock& lock) +{ + //lock internal before unlocking external to avoid race with a notifier + scoped_lock internal_lock(data.get_mutex()); + { + lock_inverter inverted_lock(lock); + scoped_lock > external_unlock(inverted_lock); + { //unlock internal first to avoid deadlock with near simultaneous waits + scoped_lock internal_unlock; + internal_lock.swap(internal_unlock); + data.get_condvar().wait(internal_unlock); + } + } +} + +template +template +bool condition_any_algorithm::do_timed_wait + (ConditionAnyMembers &data, Lock& lock, const boost::posix_time::ptime &abs_time) +{ + //lock internal before unlocking external to avoid race with a notifier + scoped_lock internal_lock(data.get_mutex()); + { + //Unlock external lock and program for relock + lock_inverter inverted_lock(lock); + scoped_lock > external_unlock(inverted_lock); + { //unlock internal first to avoid deadlock with near simultaneous waits + scoped_lock internal_unlock; + internal_lock.swap(internal_unlock); + return data.get_condvar().timed_wait(internal_unlock, abs_time); + } + } +} + + +template +class condition_any_wrapper +{ + //Non-copyable + condition_any_wrapper(const condition_any_wrapper &); + condition_any_wrapper &operator=(const condition_any_wrapper &); + + ConditionAnyMembers m_data; + typedef ipcdetail::condition_any_algorithm algo_type; + + public: + + condition_any_wrapper(){} + + ~condition_any_wrapper(){} + + ConditionAnyMembers & get_members() + { return m_data; } + + const ConditionAnyMembers & get_members() const + { return m_data; } + + void notify_one() + { algo_type::signal(m_data, false); } + + void notify_all() + { algo_type::signal(m_data, true); } + + template + void wait(L& lock) + { + if (!lock) + throw lock_exception(); + algo_type::wait(m_data, lock, false, boost::posix_time::ptime()); + } + + template + void wait(L& lock, Pr pred) + { + if (!lock) + throw lock_exception(); + + while (!pred()) + algo_type::wait(m_data, lock, false, boost::posix_time::ptime()); + } + + template + bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time) + { + if(abs_time == boost::posix_time::pos_infin){ + this->wait(lock); + return true; + } + if (!lock) + throw lock_exception(); + return algo_type::wait(m_data, lock, true, abs_time); + } + + template + bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred) + { + if(abs_time == boost::posix_time::pos_infin){ + this->wait(lock, pred); + return true; + } + if (!lock) + throw lock_exception(); + while (!pred()){ + if (!algo_type::wait(m_data, lock, true, abs_time)) + return pred(); + } + return true; + } +}; + +} //namespace ipcdetail +} //namespace interprocess +} //namespace boost + +#include + +#endif //BOOST_INTERPROCESS_DETAIL_CONDITION_ANY_ALGORITHM_HPP diff --git a/include/boost/interprocess/sync/detail/locks.hpp b/include/boost/interprocess/sync/detail/locks.hpp new file mode 100644 index 0000000..fbb003a --- /dev/null +++ b/include/boost/interprocess/sync/detail/locks.hpp @@ -0,0 +1,66 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2012-2012. 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_DETAIL_LOCKS_HPP +#define BOOST_INTERPROCESS_DETAIL_LOCKS_HPP + +#include +#include + +namespace boost { +namespace interprocess { +namespace ipcdetail { + +template +class internal_mutex_lock +{ + typedef void (internal_mutex_lock::*unspecified_bool_type)(); + public: + + typedef typename Lock::mutex_type::internal_mutex_type mutex_type; + + + internal_mutex_lock(Lock &l) + : l_(l) + {} + + mutex_type* mutex() const + { return l_ ? &l_.mutex()->internal_mutex() : 0; } + + void lock() { l_.lock(); } + + void unlock() { l_.unlock(); } + + operator unspecified_bool_type() const + { return l_ ? &internal_mutex_lock::lock : 0; } + + private: + Lock &l_; +}; + +template +class lock_inverter +{ + Lock &l_; + public: + lock_inverter(Lock &l) + : l_(l) + {} + void lock() { l_.unlock(); } + void unlock() { l_.lock(); } +}; + +} //namespace ipcdetail +} //namespace interprocess +} //namespace boost + +#include + +#endif //BOOST_INTERPROCESS_DETAIL_LOCKS_HPP diff --git a/include/boost/interprocess/sync/file_lock.hpp b/include/boost/interprocess/sync/file_lock.hpp index e0f7546..ef1c68a 100644 --- a/include/boost/interprocess/sync/file_lock.hpp +++ b/include/boost/interprocess/sync/file_lock.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -64,10 +64,10 @@ class file_lock //!After the call, "moved" does not represent any file mapping. //!Does not throw file_lock &operator=(BOOST_RV_REF(file_lock) moved) - { + { file_lock tmp(boost::move(moved)); this->swap(tmp); - return *this; + return *this; } //!Closes a file lock. Does not throw. @@ -81,7 +81,7 @@ class file_lock m_file_hnd = other.m_file_hnd; other.m_file_hnd = tmp; } - + //Exclusive locking //!Effects: The calling thread tries to obtain exclusive ownership of the mutex, @@ -171,7 +171,7 @@ class file_lock bool timed_acquire_file_lock_sharable (file_handle_t hnd, bool &acquired, const boost::posix_time::ptime &abs_time) - { + { //Obtain current count and target time boost::posix_time::ptime now = microsec_clock::universal_time(); using namespace boost::detail; diff --git a/include/boost/interprocess/sync/interprocess_condition.hpp b/include/boost/interprocess/sync/interprocess_condition.hpp index 9d0bea6..c30e870 100644 --- a/include/boost/interprocess/sync/interprocess_condition.hpp +++ b/include/boost/interprocess/sync/interprocess_condition.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -54,6 +55,11 @@ class named_condition; //!This class is a condition variable that can be placed in shared memory or //!memory mapped files. +//!Destroys the object of type std::condition_variable_any +//! +//!Unlike std::condition_variable in C++11, it is NOT safe to invoke the destructor if all +//!threads have been only notified. It is required that they have exited their respective wait +//!functions. class interprocess_condition { /// @cond @@ -62,13 +68,16 @@ class interprocess_condition interprocess_condition &operator=(const interprocess_condition &); friend class named_condition; /// @endcond + public: //!Constructs a interprocess_condition. On error throws interprocess_exception. - interprocess_condition(){} + interprocess_condition() + {} //!Destroys *this //!liberating system resources. - ~interprocess_condition(){} + ~interprocess_condition() + {} //!If there is a thread waiting on *this, change that //!thread's state to ready. Otherwise there is no effect. @@ -85,10 +94,9 @@ class interprocess_condition //!this->notify_one() or this->notify_all(), and then reacquires the lock. template void wait(L& lock) - { - if (!lock) - throw lock_exception(); - this->do_wait(*lock.mutex()); + { + ipcdetail::internal_mutex_lock internal_lock(lock); + m_condition.wait(internal_lock); } //!The same as: @@ -96,11 +104,8 @@ class interprocess_condition template void wait(L& lock, Pr pred) { - if (!lock) - throw lock_exception(); - - while (!pred()) - this->do_wait(*lock.mutex()); + ipcdetail::internal_mutex_lock internal_lock(lock); + m_condition.wait(internal_lock, pred); } //!Releases the lock on the interprocess_mutex object associated with lock, blocks @@ -111,13 +116,8 @@ class interprocess_condition template bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time) { - if(abs_time == boost::posix_time::pos_infin){ - this->wait(lock); - return true; - } - if (!lock) - throw lock_exception(); - return this->do_timed_wait(abs_time, *lock.mutex()); + ipcdetail::internal_mutex_lock internal_lock(lock); + return m_condition.timed_wait(internal_lock, abs_time); } //!The same as: while (!pred()) { @@ -126,28 +126,12 @@ class interprocess_condition template bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred) { - if(abs_time == boost::posix_time::pos_infin){ - this->wait(lock, pred); - return true; - } - if (!lock) - throw lock_exception(); - while (!pred()){ - if (!this->do_timed_wait(abs_time, *lock.mutex())) - return pred(); - } - - return true; + ipcdetail::internal_mutex_lock internal_lock(lock); + return m_condition.timed_wait(internal_lock, abs_time, pred); } /// @cond - void do_wait(interprocess_mutex &mut) - { m_condition.do_wait(mut.mutex); } - - bool do_timed_wait(const boost::posix_time::ptime &abs_time, interprocess_mutex &mut) - { return m_condition.do_timed_wait(abs_time, mut.mutex); } - private: #if defined (BOOST_INTERPROCESS_USE_GENERIC_EMULATION) #undef BOOST_INTERPROCESS_USE_GENERIC_EMULATION diff --git a/include/boost/interprocess/sync/interprocess_condition_any.hpp b/include/boost/interprocess/sync/interprocess_condition_any.hpp new file mode 100644 index 0000000..dd20794 --- /dev/null +++ b/include/boost/interprocess/sync/interprocess_condition_any.hpp @@ -0,0 +1,129 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2012-2012. 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_ANY_HPP +#define BOOST_INTERPROCESS_CONDITION_ANY_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +/// @cond + +#include +#include + +#include +#include +#include +#include +#include + +/// @endcond + +//!\file +//!Describes process-shared variables interprocess_condition_any class + +namespace boost { + +namespace posix_time +{ class ptime; } + +namespace interprocess { + +//!This class is a condition variable that can be placed in shared memory or +//!memory mapped files. +//! +//!The interprocess_condition_any class is a generalization of interprocess_condition. +//!Whereas interprocess_condition works only on Locks with mutex_type == interprocess_mutex +//!interprocess_condition_any can operate on any user-defined lock that meets the BasicLockable +//!requirements (lock()/unlock() member functions). +//! +//!Unlike std::condition_variable_any in C++11, it is NOT safe to invoke the destructor if all +//!threads have been only notified. It is required that they have exited their respective wait +//!functions. +class interprocess_condition_any +{ + /// @cond + //Non-copyable + interprocess_condition_any(const interprocess_condition_any &); + interprocess_condition_any &operator=(const interprocess_condition_any &); + + class members + { + public: + typedef interprocess_condition condvar_type; + typedef interprocess_mutex mutex_type; + + condvar_type &get_condvar() { return m_cond; } + mutex_type &get_mutex() { return m_mut; } + + private: + condvar_type m_cond; + mutex_type m_mut; + }; + + ipcdetail::condition_any_wrapper m_cond; + + /// @endcond + public: + //!Constructs a interprocess_condition_any. On error throws interprocess_exception. + interprocess_condition_any(){} + + //!Destroys *this + //!liberating system resources. + ~interprocess_condition_any(){} + + //!If there is a thread waiting on *this, change that + //!thread's state to ready. Otherwise there is no effect. + void notify_one() + { m_cond.notify_one(); } + + //!Change the state of all threads waiting on *this to ready. + //!If there are no waiting threads, notify_all() has no effect. + void notify_all() + { m_cond.notify_all(); } + + //!Releases the lock on the interprocess_mutex object associated with lock, blocks + //!the current thread of execution until readied by a call to + //!this->notify_one() or this->notify_all(), and then reacquires the lock. + template + void wait(L& lock) + { m_cond.wait(lock); } + + //!The same as: + //!while (!pred()) wait(lock) + template + void wait(L& lock, Pr pred) + { m_cond.wait(lock, pred); } + + //!Releases the lock on the interprocess_mutex object associated with lock, blocks + //!the current thread of execution until readied by a call to + //!this->notify_one() or this->notify_all(), or until time abs_time is reached, + //!and then reacquires the lock. + //!Returns: false if time abs_time is reached, otherwise true. + template + bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time) + { return m_cond.timed_wait(lock, abs_time); } + + //!The same as: while (!pred()) { + //! if (!timed_wait(lock, abs_time)) return pred(); + //! } return true; + template + bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred) + { return m_cond.timed_wait(lock, abs_time, pred); } +}; + +} //namespace interprocess +} // namespace boost + +#include + +#endif // BOOST_INTERPROCESS_CONDITION_ANY_HPP diff --git a/include/boost/interprocess/sync/interprocess_mutex.hpp b/include/boost/interprocess/sync/interprocess_mutex.hpp index 8110c84..5615e8b 100644 --- a/include/boost/interprocess/sync/interprocess_mutex.hpp +++ b/include/boost/interprocess/sync/interprocess_mutex.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -70,6 +70,25 @@ class interprocess_mutex interprocess_mutex(const interprocess_mutex &); interprocess_mutex &operator=(const interprocess_mutex &); friend class interprocess_condition; + + public: + #if defined(BOOST_INTERPROCESS_USE_GENERIC_EMULATION) + #undef BOOST_INTERPROCESS_USE_GENERIC_EMULATION + typedef ipcdetail::spin_mutex internal_mutex_type; + private: + friend class ipcdetail::robust_emulation_helpers::mutex_traits; + void take_ownership(){ m_mutex.take_ownership(); } + public: + #elif defined(BOOST_INTERPROCESS_USE_POSIX) + #undef BOOST_INTERPROCESS_USE_POSIX + typedef ipcdetail::posix_mutex internal_mutex_type; + #elif defined(BOOST_INTERPROCESS_USE_WINDOWS) + #undef BOOST_INTERPROCESS_USE_WINDOWS + typedef ipcdetail::windows_mutex internal_mutex_type; + #else + #error "Unknown platform for interprocess_mutex" + #endif + /// @endcond public: @@ -107,23 +126,16 @@ class interprocess_mutex //!Effects: The calling thread releases the exclusive ownership of the mutex. //!Throws: interprocess_exception on error. void unlock(); - /// @cond - private: - #if defined(BOOST_INTERPROCESS_USE_GENERIC_EMULATION) - #undef BOOST_INTERPROCESS_USE_GENERIC_EMULATION - friend class ipcdetail::robust_emulation_helpers::mutex_traits; - void take_ownership(){ mutex.take_ownership(); } - ipcdetail::spin_mutex mutex; - #elif defined(BOOST_INTERPROCESS_USE_POSIX) - #undef BOOST_INTERPROCESS_USE_POSIX - ipcdetail::posix_mutex mutex; - #elif defined(BOOST_INTERPROCESS_USE_WINDOWS) - #undef BOOST_INTERPROCESS_USE_WINDOWS - ipcdetail::windows_mutex mutex; - #else - #error "Unknown platform for interprocess_mutex" - #endif + /// @cond + internal_mutex_type &internal_mutex() + { return m_mutex; } + + const internal_mutex_type &internal_mutex() const + { return m_mutex; } + + private: + internal_mutex_type m_mutex; /// @endcond }; @@ -144,23 +156,25 @@ inline void interprocess_mutex::lock() boost::posix_time::ptime wait_time = boost::posix_time::microsec_clock::universal_time() + boost::posix_time::milliseconds(BOOST_INTERPROCESS_TIMEOUT_WHEN_LOCKING_DURATION_MS); - if (!mutex.timed_lock(wait_time)) + if (!m_mutex.timed_lock(wait_time)) { - throw interprocess_exception(timeout_when_locking_error, "Interprocess mutex timeout when locking. Possible deadlock: owner died without unlocking?"); + throw interprocess_exception(timeout_when_locking_error + , "Interprocess mutex timeout when locking. Possible deadlock: " + "owner died without unlocking?"); } #else - mutex.lock(); + m_mutex.lock(); #endif } inline bool interprocess_mutex::try_lock() -{ return mutex.try_lock(); } +{ return m_mutex.try_lock(); } inline bool interprocess_mutex::timed_lock(const boost::posix_time::ptime &abs_time) -{ return mutex.timed_lock(abs_time); } +{ return m_mutex.timed_lock(abs_time); } inline void interprocess_mutex::unlock() -{ mutex.unlock(); } +{ m_mutex.unlock(); } } //namespace interprocess { } //namespace boost { diff --git a/include/boost/interprocess/sync/interprocess_recursive_mutex.hpp b/include/boost/interprocess/sync/interprocess_recursive_mutex.hpp index 3079108..1c5dad3 100644 --- a/include/boost/interprocess/sync/interprocess_recursive_mutex.hpp +++ b/include/boost/interprocess/sync/interprocess_recursive_mutex.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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/include/boost/interprocess/sync/interprocess_semaphore.hpp b/include/boost/interprocess/sync/interprocess_semaphore.hpp index 2a2f34f..2fe0581 100644 --- a/include/boost/interprocess/sync/interprocess_semaphore.hpp +++ b/include/boost/interprocess/sync/interprocess_semaphore.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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/include/boost/interprocess/sync/interprocess_sharable_mutex.hpp b/include/boost/interprocess/sync/interprocess_sharable_mutex.hpp new file mode 100644 index 0000000..880563c --- /dev/null +++ b/include/boost/interprocess/sync/interprocess_sharable_mutex.hpp @@ -0,0 +1,347 @@ +////////////////////////////////////////////////////////////////////////////// +// Code based on Howard Hinnant's shared_mutex class +// +// (C) Copyright Howard Hinnant 2007-2010. Distributed under the Boost +// Software License, Version 1.0. (see http://www.boost.org/LICENSE_1_0.txt) +// +// (C) Copyright Ion Gaztanaga 2005-2012. 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_SHARABLE_MUTEX_HPP +#define BOOST_INTERPROCESS_SHARABLE_MUTEX_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include + + +//!\file +//!Describes interprocess_sharable_mutex class + +namespace boost { +namespace interprocess { + +//!Wraps a interprocess_sharable_mutex that can be placed in shared memory and can be +//!shared between processes. Allows timed lock tries +class interprocess_sharable_mutex +{ + //Non-copyable + interprocess_sharable_mutex(const interprocess_sharable_mutex &); + interprocess_sharable_mutex &operator=(const interprocess_sharable_mutex &); + + friend class interprocess_condition; + public: + + //!Constructs the sharable lock. + //!Throws interprocess_exception on error. + interprocess_sharable_mutex(); + + //!Destroys the sharable lock. + //!Does not throw. + ~interprocess_sharable_mutex(); + + //Exclusive locking + + //!Effects: The calling thread tries to obtain exclusive ownership of the mutex, + //! and if another thread has exclusive or sharable ownership of + //! the mutex, it waits until it can obtain the ownership. + //!Throws: interprocess_exception on error. + void lock(); + + //!Effects: The calling thread tries to acquire exclusive ownership of the mutex + //! without waiting. If no other thread has exclusive or sharable + //! ownership of the mutex this succeeds. + //!Returns: If it can acquire exclusive ownership immediately returns true. + //! If it has to wait, returns false. + //!Throws: interprocess_exception on error. + bool try_lock(); + + //!Effects: The calling thread tries to acquire exclusive ownership of the mutex + //! waiting if necessary until no other thread has exclusive or sharable + //! ownership of the mutex or abs_time is reached. + //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. + //!Throws: interprocess_exception on error. + bool timed_lock(const boost::posix_time::ptime &abs_time); + + //!Precondition: The thread must have exclusive ownership of the mutex. + //!Effects: The calling thread releases the exclusive ownership of the mutex. + //!Throws: An exception derived from interprocess_exception on error. + void unlock(); + + //Sharable locking + + //!Effects: The calling thread tries to obtain sharable ownership of the mutex, + //! and if another thread has exclusive ownership of the mutex, + //! waits until it can obtain the ownership. + //!Throws: interprocess_exception on error. + void lock_sharable(); + + //!Effects: The calling thread tries to acquire sharable ownership of the mutex + //! without waiting. If no other thread has exclusive ownership + //! of the mutex this succeeds. + //!Returns: If it can acquire sharable ownership immediately returns true. If it + //! has to wait, returns false. + //!Throws: interprocess_exception on error. + bool try_lock_sharable(); + + //!Effects: The calling thread tries to acquire sharable ownership of the mutex + //! waiting if necessary until no other thread has exclusive + //! ownership of the mutex or abs_time is reached. + //!Returns: If acquires sharable ownership, returns true. Otherwise returns false. + //!Throws: interprocess_exception on error. + bool timed_lock_sharable(const boost::posix_time::ptime &abs_time); + + //!Precondition: The thread must have sharable ownership of the mutex. + //!Effects: The calling thread releases the sharable ownership of the mutex. + //!Throws: An exception derived from interprocess_exception on error. + void unlock_sharable(); + + /// @cond + private: + typedef scoped_lock scoped_lock_t; + + //Pack all the control data in a word to be able + //to use atomic instructions in the future + struct control_word_t + { + unsigned exclusive_in : 1; + unsigned num_shared : sizeof(unsigned)*CHAR_BIT-1; + } m_ctrl; + + interprocess_mutex m_mut; + interprocess_condition m_first_gate; + interprocess_condition m_second_gate; + + private: + //Rollback structures for exceptions or failure return values + struct exclusive_rollback + { + exclusive_rollback(control_word_t &ctrl + ,interprocess_condition &first_gate) + : mp_ctrl(&ctrl), m_first_gate(first_gate) + {} + + void release() + { mp_ctrl = 0; } + + ~exclusive_rollback() + { + if(mp_ctrl){ + mp_ctrl->exclusive_in = 0; + m_first_gate.notify_all(); + } + } + control_word_t *mp_ctrl; + interprocess_condition &m_first_gate; + }; + + template + struct base_constants_t + { + static const unsigned max_readers + = ~(unsigned(1) << (sizeof(unsigned)*CHAR_BIT-1)); + }; + typedef base_constants_t<0> constants; + /// @endcond +}; + +/// @cond + +template +const unsigned interprocess_sharable_mutex::base_constants_t::max_readers; + +inline interprocess_sharable_mutex::interprocess_sharable_mutex() +{ + this->m_ctrl.exclusive_in = 0; + this->m_ctrl.num_shared = 0; +} + +inline interprocess_sharable_mutex::~interprocess_sharable_mutex() +{} + +inline void interprocess_sharable_mutex::lock() +{ + scoped_lock_t lock(m_mut); + + //The exclusive lock must block in the first gate + //if an exclusive lock has been acquired + while (this->m_ctrl.exclusive_in){ + this->m_first_gate.wait(lock); + } + + //Mark that exclusive lock has been acquired + this->m_ctrl.exclusive_in = 1; + + //Prepare rollback + exclusive_rollback rollback(this->m_ctrl, this->m_first_gate); + + //Now wait until all readers are gone + while (this->m_ctrl.num_shared){ + this->m_second_gate.wait(lock); + } + rollback.release(); +} + +inline bool interprocess_sharable_mutex::try_lock() +{ + scoped_lock_t lock(m_mut, try_to_lock); + + //If we can't lock or any has there is any exclusive + //or sharable mark return false; + if(!lock.owns() + || this->m_ctrl.exclusive_in + || this->m_ctrl.num_shared){ + return false; + } + this->m_ctrl.exclusive_in = 1; + return true; +} + +inline bool interprocess_sharable_mutex::timed_lock + (const boost::posix_time::ptime &abs_time) +{ + if(abs_time == boost::posix_time::pos_infin){ + this->lock(); + return true; + } + scoped_lock_t lock(m_mut, abs_time); + if(!lock.owns()) return false; + + //The exclusive lock must block in the first gate + //if an exclusive lock has been acquired + while (this->m_ctrl.exclusive_in){ + if(!this->m_first_gate.timed_wait(lock, abs_time)){ + if(this->m_ctrl.exclusive_in){ + return false; + } + break; + } + } + + //Mark that exclusive lock has been acquired + this->m_ctrl.exclusive_in = 1; + + //Prepare rollback + exclusive_rollback rollback(this->m_ctrl, this->m_first_gate); + + //Now wait until all readers are gone + while (this->m_ctrl.num_shared){ + if(!this->m_second_gate.timed_wait(lock, abs_time)){ + if(this->m_ctrl.num_shared){ + return false; + } + break; + } + } + rollback.release(); + return true; +} + +inline void interprocess_sharable_mutex::unlock() +{ + scoped_lock_t lock(m_mut); + this->m_ctrl.exclusive_in = 0; + this->m_first_gate.notify_all(); +} + +//Sharable locking + +inline void interprocess_sharable_mutex::lock_sharable() +{ + scoped_lock_t lock(m_mut); + + //The sharable lock must block in the first gate + //if an exclusive lock has been acquired + //or there are too many sharable locks + while(this->m_ctrl.exclusive_in + || this->m_ctrl.num_shared == constants::max_readers){ + this->m_first_gate.wait(lock); + } + + //Increment sharable count + ++this->m_ctrl.num_shared; +} + +inline bool interprocess_sharable_mutex::try_lock_sharable() +{ + scoped_lock_t lock(m_mut, try_to_lock); + + //The sharable lock must fail + //if an exclusive lock has been acquired + //or there are too many sharable locks + if(!lock.owns() + || this->m_ctrl.exclusive_in + || this->m_ctrl.num_shared == constants::max_readers){ + return false; + } + + //Increment sharable count + ++this->m_ctrl.num_shared; + return true; +} + +inline bool interprocess_sharable_mutex::timed_lock_sharable + (const boost::posix_time::ptime &abs_time) +{ + if(abs_time == boost::posix_time::pos_infin){ + this->lock_sharable(); + return true; + } + scoped_lock_t lock(m_mut, abs_time); + if(!lock.owns()) return false; + + //The sharable lock must block in the first gate + //if an exclusive lock has been acquired + //or there are too many sharable locks + while (this->m_ctrl.exclusive_in + || this->m_ctrl.num_shared == constants::max_readers){ + if(!this->m_first_gate.timed_wait(lock, abs_time)){ + if(this->m_ctrl.exclusive_in + || this->m_ctrl.num_shared == constants::max_readers){ + return false; + } + break; + } + } + + //Increment sharable count + ++this->m_ctrl.num_shared; + return true; +} + +inline void interprocess_sharable_mutex::unlock_sharable() +{ + scoped_lock_t lock(m_mut); + //Decrement sharable count + --this->m_ctrl.num_shared; + if (this->m_ctrl.num_shared == 0){ + this->m_second_gate.notify_one(); + } + //Check if there are blocked sharables because of + //there were too many sharables + else if(this->m_ctrl.num_shared == (constants::max_readers-1)){ + this->m_first_gate.notify_all(); + } +} + +/// @endcond + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_SHARABLE_MUTEX_HPP diff --git a/include/boost/interprocess/sync/interprocess_upgradable_mutex.hpp b/include/boost/interprocess/sync/interprocess_upgradable_mutex.hpp index 8d5a452..303bee6 100644 --- a/include/boost/interprocess/sync/interprocess_upgradable_mutex.hpp +++ b/include/boost/interprocess/sync/interprocess_upgradable_mutex.hpp @@ -1,6 +1,8 @@ -////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// Code based on Howard Hinnant's upgrade_mutex class +// +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -249,7 +251,7 @@ class interprocess_upgradable_mutex if(mp_ctrl){ //Recover upgradable lock mp_ctrl->upgradable_in = 1; - ++mp_ctrl->num_upr_shar; + ++mp_ctrl->num_upr_shar; //Execute the second half of exclusive locking mp_ctrl->exclusive_in = 0; } @@ -333,8 +335,12 @@ inline bool interprocess_upgradable_mutex::timed_lock //The exclusive lock must block in the first gate //if an exclusive or upgradable lock has been acquired while (this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in){ - if(!this->m_first_gate.timed_wait(lock, abs_time)) - return !(this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in); + if(!this->m_first_gate.timed_wait(lock, abs_time)){ + if(this->m_ctrl.exclusive_in || this->m_ctrl.upgradable_in){ + return false; + } + break; + } } //Mark that exclusive lock has been acquired @@ -346,7 +352,10 @@ inline bool interprocess_upgradable_mutex::timed_lock //Now wait until all readers are gone while (this->m_ctrl.num_upr_shar){ if(!this->m_second_gate.timed_wait(lock, abs_time)){ - return !(this->m_ctrl.num_upr_shar); + if(this->m_ctrl.num_upr_shar){ + return false; + } + break; } } rollback.release(); @@ -418,9 +427,12 @@ inline bool interprocess_upgradable_mutex::timed_lock_upgradable || this->m_ctrl.upgradable_in || this->m_ctrl.num_upr_shar == constants::max_readers){ if(!this->m_first_gate.timed_wait(lock, abs_time)){ - return!(this->m_ctrl.exclusive_in - || this->m_ctrl.upgradable_in - || this->m_ctrl.num_upr_shar == constants::max_readers); + if((this->m_ctrl.exclusive_in + || this->m_ctrl.upgradable_in + || this->m_ctrl.num_upr_shar == constants::max_readers)){ + return false; + } + break; } } @@ -492,9 +504,12 @@ inline bool interprocess_upgradable_mutex::timed_lock_sharable //or there are too many sharable locks while (this->m_ctrl.exclusive_in || this->m_ctrl.num_upr_shar == constants::max_readers){ - if(!this->m_first_gate.timed_wait(lock, abs_time)){ - return!(this->m_ctrl.exclusive_in - || this->m_ctrl.num_upr_shar == constants::max_readers); + if(!this->m_first_gate.timed_wait(lock, abs_time)){ + if(this->m_ctrl.exclusive_in + || this->m_ctrl.num_upr_shar == constants::max_readers){ + return false; + } + break; } } @@ -561,7 +576,7 @@ inline void interprocess_upgradable_mutex::unlock_upgradable_and_lock() //Simulate unlock_upgradable() without //notifying sharables. this->m_ctrl.upgradable_in = 0; - --this->m_ctrl.num_upr_shar; + --this->m_ctrl.num_upr_shar; //Execute the second half of exclusive locking this->m_ctrl.exclusive_in = 1; @@ -584,7 +599,7 @@ inline bool interprocess_upgradable_mutex::try_unlock_upgradable_and_lock() } //Now unlock upgradable and mark exclusive this->m_ctrl.upgradable_in = 0; - --this->m_ctrl.num_upr_shar; + --this->m_ctrl.num_upr_shar; this->m_ctrl.exclusive_in = 1; return true; } @@ -592,13 +607,17 @@ inline bool interprocess_upgradable_mutex::try_unlock_upgradable_and_lock() inline bool interprocess_upgradable_mutex::timed_unlock_upgradable_and_lock (const boost::posix_time::ptime &abs_time) { + if(abs_time == boost::posix_time::pos_infin){ + this->unlock_upgradable_and_lock(); + return true; + } scoped_lock_t lock(m_mut, abs_time); if(!lock.owns()) return false; //Simulate unlock_upgradable() without //notifying sharables. this->m_ctrl.upgradable_in = 0; - --this->m_ctrl.num_upr_shar; + --this->m_ctrl.num_upr_shar; //Execute the second half of exclusive locking this->m_ctrl.exclusive_in = 1; @@ -607,7 +626,10 @@ inline bool interprocess_upgradable_mutex::timed_unlock_upgradable_and_lock while (this->m_ctrl.num_upr_shar){ if(!this->m_second_gate.timed_wait(lock, abs_time)){ - return !(this->m_ctrl.num_upr_shar); + if(this->m_ctrl.num_upr_shar){ + return false; + } + break; } } rollback.release(); diff --git a/include/boost/interprocess/sync/lock_options.hpp b/include/boost/interprocess/sync/lock_options.hpp index 74f3399..1139d83 100644 --- a/include/boost/interprocess/sync/lock_options.hpp +++ b/include/boost/interprocess/sync/lock_options.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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/include/boost/interprocess/sync/mutex_family.hpp b/include/boost/interprocess/sync/mutex_family.hpp index b153ffe..0636de0 100644 --- a/include/boost/interprocess/sync/mutex_family.hpp +++ b/include/boost/interprocess/sync/mutex_family.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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/include/boost/interprocess/sync/named_condition.hpp b/include/boost/interprocess/sync/named_condition.hpp index ca0205a..7c570f4 100644 --- a/include/boost/interprocess/sync/named_condition.hpp +++ b/include/boost/interprocess/sync/named_condition.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -22,6 +22,7 @@ #include #include #include +#include #if !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS) #include #define BOOST_INTERPROCESS_USE_WINDOWS @@ -153,24 +154,38 @@ inline void named_condition::notify_all() template inline void named_condition::wait(L& lock) -{ m_cond.wait(lock); } +{ + ipcdetail::internal_mutex_lock internal_lock(lock); + m_cond.wait(internal_lock); +} template inline void named_condition::wait(L& lock, Pr pred) -{ m_cond.wait(lock, pred); } +{ + ipcdetail::internal_mutex_lock internal_lock(lock); + m_cond.wait(internal_lock, pred); +} template inline bool named_condition::timed_wait (L& lock, const boost::posix_time::ptime &abs_time) -{ return m_cond.timed_wait(lock, abs_time); } +{ + ipcdetail::internal_mutex_lock internal_lock(lock); + return m_cond.timed_wait(internal_lock, abs_time); +} template inline bool named_condition::timed_wait (L& lock, const boost::posix_time::ptime &abs_time, Pr pred) -{ return m_cond.timed_wait(lock, abs_time, pred); } +{ + ipcdetail::internal_mutex_lock internal_lock(lock); + return m_cond.timed_wait(internal_lock, abs_time, pred); +} inline bool named_condition::remove(const char *name) -{ return condition_type::remove(name); } +{ + return condition_type::remove(name); +} /// @endcond diff --git a/include/boost/interprocess/sync/named_condition_any.hpp b/include/boost/interprocess/sync/named_condition_any.hpp new file mode 100644 index 0000000..f8f204b --- /dev/null +++ b/include/boost/interprocess/sync/named_condition_any.hpp @@ -0,0 +1,151 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2012. 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_CONDITION_ANY_HPP +#define BOOST_INTERPROCESS_NAMED_CONDITION_ANY_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#if !defined(BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION) && defined (BOOST_INTERPROCESS_WINDOWS) + #include + #define BOOST_INTERPROCESS_USE_WINDOWS +#else + #include +#endif + +//!\file +//!Describes a named condition class for inter-process synchronization + +namespace boost { +namespace interprocess { + +/// @cond +namespace ipcdetail{ class interprocess_tester; } +/// @endcond + +//! A global condition variable that can be created by name. +//! This condition variable is designed to work with named_mutex and +//! can't be placed in shared memory or memory mapped files. +class named_condition_any +{ + /// @cond + //Non-copyable + named_condition_any(); + named_condition_any(const named_condition_any &); + named_condition_any &operator=(const named_condition_any &); + /// @endcond + public: + //!Creates a global condition with a name. + //!If the condition can't be created throws interprocess_exception + named_condition_any(create_only_t, const char *name, const permissions &perm = permissions()) + : m_cond(create_only_t(), name, perm) + {} + + //!Opens or creates a global condition with a name. + //!If the condition is created, this call is equivalent to + //!named_condition_any(create_only_t, ... ) + //!If the condition is already created, this call is equivalent + //!named_condition_any(open_only_t, ... ) + //!Does not throw + named_condition_any(open_or_create_t, const char *name, const permissions &perm = permissions()) + : m_cond(open_or_create_t(), name, perm) + {} + + //!Opens a global condition with a name if that condition is previously + //!created. If it is not previously created this function throws + //!interprocess_exception. + named_condition_any(open_only_t, const char *name) + : m_cond(open_only_t(), name) + {} + + //!Destroys *this and indicates that the calling process is finished using + //!the resource. The destructor function will deallocate + //!any system resources allocated by the system for use by this process for + //!this resource. The resource can still be opened again calling + //!the open constructor overload. To erase the resource from the system + //!use remove(). + ~named_condition_any() + {} + + //!If there is a thread waiting on *this, change that + //!thread's state to ready. Otherwise there is no effect.*/ + void notify_one() + { m_cond.notify_one(); } + + //!Change the state of all threads waiting on *this to ready. + //!If there are no waiting threads, notify_all() has no effect. + void notify_all() + { m_cond.notify_all(); } + + //!Releases the lock on the named_mutex object associated with lock, blocks + //!the current thread of execution until readied by a call to + //!this->notify_one() or this->notify_all(), and then reacquires the lock. + template + void wait(L& lock) + { return m_cond.wait(lock); } + + //!The same as: + //!while (!pred()) wait(lock) + template + void wait(L& lock, Pr pred) + { return m_cond.wait(lock, pred); } + + //!Releases the lock on the named_mutex object associated with lock, blocks + //!the current thread of execution until readied by a call to + //!this->notify_one() or this->notify_all(), or until time abs_time is reached, + //!and then reacquires the lock. + //!Returns: false if time abs_time is reached, otherwise true. + template + bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time) + { return m_cond.timed_wait(lock, abs_time); } + + //!The same as: while (!pred()) { + //! if (!timed_wait(lock, abs_time)) return pred(); + //! } return true; + template + bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred) + { return m_cond.timed_wait(lock, abs_time, pred); } + + //!Erases a named condition from the system. + //!Returns false on error. Never throws. + static bool remove(const char *name) + { return condition_any_type::remove(name); } + + /// @cond + private: + #if defined(BOOST_INTERPROCESS_USE_WINDOWS) + typedef ipcdetail::windows_named_condition_any condition_any_type; + #else + typedef ipcdetail::shm_named_condition_any condition_any_type; + #endif + condition_any_type m_cond; + + friend class ipcdetail::interprocess_tester; + void dont_close_on_destruction() + { ipcdetail::interprocess_tester::dont_close_on_destruction(m_cond); } + /// @endcond +}; + +} //namespace interprocess +} //namespace boost + +#include + +#endif // BOOST_INTERPROCESS_NAMED_CONDITION_ANY_HPP diff --git a/include/boost/interprocess/sync/named_mutex.hpp b/include/boost/interprocess/sync/named_mutex.hpp index c34193c..7deb400 100644 --- a/include/boost/interprocess/sync/named_mutex.hpp +++ b/include/boost/interprocess/sync/named_mutex.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -108,21 +108,20 @@ class named_mutex friend class ipcdetail::interprocess_tester; void dont_close_on_destruction(); + public: #if defined(BOOST_INTERPROCESS_USE_POSIX_SEMAPHORES) - typedef ipcdetail::posix_named_mutex impl_t; - impl_t m_mut; + typedef ipcdetail::posix_named_mutex internal_mutex_type; #undef BOOST_INTERPROCESS_USE_POSIX_SEMAPHORES #elif defined(BOOST_INTERPROCESS_USE_WINDOWS) - typedef ipcdetail::windows_named_mutex impl_t; - impl_t m_mut; + typedef ipcdetail::windows_named_mutex internal_mutex_type; #undef BOOST_INTERPROCESS_USE_WINDOWS #else - typedef ipcdetail::shm_named_mutex impl_t; - impl_t m_mut; - public: - interprocess_mutex *mutex() const - { return m_mut.mutex(); } + typedef ipcdetail::shm_named_mutex internal_mutex_type; #endif + internal_mutex_type &internal_mutex() + { return m_mut; } + + internal_mutex_type m_mut; /// @endcond }; @@ -160,7 +159,7 @@ inline bool named_mutex::timed_lock(const boost::posix_time::ptime &abs_time) { return m_mut.timed_lock(abs_time); } inline bool named_mutex::remove(const char *name) -{ return impl_t::remove(name); } +{ return internal_mutex_type::remove(name); } /// @endcond diff --git a/include/boost/interprocess/sync/named_recursive_mutex.hpp b/include/boost/interprocess/sync/named_recursive_mutex.hpp index 2d4b9b2..5849a92 100644 --- a/include/boost/interprocess/sync/named_recursive_mutex.hpp +++ b/include/boost/interprocess/sync/named_recursive_mutex.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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/include/boost/interprocess/sync/named_semaphore.hpp b/include/boost/interprocess/sync/named_semaphore.hpp index 39c9096..1477245 100644 --- a/include/boost/interprocess/sync/named_semaphore.hpp +++ b/include/boost/interprocess/sync/named_semaphore.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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/include/boost/interprocess/sync/named_sharable_mutex.hpp b/include/boost/interprocess/sync/named_sharable_mutex.hpp new file mode 100644 index 0000000..fb5790f --- /dev/null +++ b/include/boost/interprocess/sync/named_sharable_mutex.hpp @@ -0,0 +1,231 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2012. 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_SHARABLE_MUTEX_HPP +#define BOOST_INTERPROCESS_NAMED_SHARABLE_MUTEX_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//!\file +//!Describes a named sharable mutex class for inter-process synchronization + +namespace boost { +namespace interprocess { + +/// @cond +namespace ipcdetail{ class interprocess_tester; } +/// @endcond + +class named_condition; + +//!A sharable mutex with a global name, so it can be found from different +//!processes. This mutex can't be placed in shared memory, and +//!each process should have it's own named sharable mutex. +class named_sharable_mutex +{ + /// @cond + //Non-copyable + named_sharable_mutex(); + named_sharable_mutex(const named_sharable_mutex &); + named_sharable_mutex &operator=(const named_sharable_mutex &); + /// @endcond + public: + + //!Creates a global sharable mutex with a name. + //!If the sharable mutex can't be created throws interprocess_exception + named_sharable_mutex(create_only_t create_only, const char *name, const permissions &perm = permissions()); + + //!Opens or creates a global sharable mutex with a name. + //!If the sharable mutex is created, this call is equivalent to + //!named_sharable_mutex(create_only_t, ...) + //!If the sharable mutex is already created, this call is equivalent to + //!named_sharable_mutex(open_only_t, ... ). + named_sharable_mutex(open_or_create_t open_or_create, const char *name, const permissions &perm = permissions()); + + //!Opens a global sharable mutex with a name if that sharable mutex + //!is previously. + //!created. If it is not previously created this function throws + //!interprocess_exception. + named_sharable_mutex(open_only_t open_only, const char *name); + + //!Destroys *this and indicates that the calling process is finished using + //!the resource. The destructor function will deallocate + //!any system resources allocated by the system for use by this process for + //!this resource. The resource can still be opened again calling + //!the open constructor overload. To erase the resource from the system + //!use remove(). + ~named_sharable_mutex(); + + //Exclusive locking + + //!Effects: The calling thread tries to obtain exclusive ownership of the mutex, + //! and if another thread has exclusive or sharable ownership of + //! the mutex, it waits until it can obtain the ownership. + //!Throws: interprocess_exception on error. + void lock(); + + //!Effects: The calling thread tries to acquire exclusive ownership of the mutex + //! without waiting. If no other thread has exclusive or sharable + //! ownership of the mutex this succeeds. + //!Returns: If it can acquire exclusive ownership immediately returns true. + //! If it has to wait, returns false. + //!Throws: interprocess_exception on error. + bool try_lock(); + + //!Effects: The calling thread tries to acquire exclusive ownership of the mutex + //! waiting if necessary until no other thread has exclusive, or sharable + //! ownership of the mutex or abs_time is reached. + //!Returns: If acquires exclusive ownership, returns true. Otherwise returns false. + //!Throws: interprocess_exception on error. + bool timed_lock(const boost::posix_time::ptime &abs_time); + + //!Precondition: The thread must have exclusive ownership of the mutex. + //!Effects: The calling thread releases the exclusive ownership of the mutex. + //!Throws: An exception derived from interprocess_exception on error. + void unlock(); + + //Sharable locking + + //!Effects: The calling thread tries to obtain sharable ownership of the mutex, + //! and if another thread has exclusive ownership of the mutex, + //! waits until it can obtain the ownership. + //!Throws: interprocess_exception on error. + void lock_sharable(); + + //!Effects: The calling thread tries to acquire sharable ownership of the mutex + //! without waiting. If no other thread has exclusive ownership + //! of the mutex this succeeds. + //!Returns: If it can acquire sharable ownership immediately returns true. If it + //! has to wait, returns false. + //!Throws: interprocess_exception on error. + bool try_lock_sharable(); + + //!Effects: The calling thread tries to acquire sharable ownership of the mutex + //! waiting if necessary until no other thread has exclusive + //! ownership of the mutex or abs_time is reached. + //!Returns: If acquires sharable ownership, returns true. Otherwise returns false. + //!Throws: interprocess_exception on error. + bool timed_lock_sharable(const boost::posix_time::ptime &abs_time); + + //!Precondition: The thread must have sharable ownership of the mutex. + //!Effects: The calling thread releases the sharable ownership of the mutex. + //!Throws: An exception derived from interprocess_exception on error. + void unlock_sharable(); + + //!Erases a named sharable mutex from the system. + //!Returns false on error. Never throws. + static bool remove(const char *name); + + /// @cond + private: + friend class ipcdetail::interprocess_tester; + void dont_close_on_destruction(); + + interprocess_sharable_mutex *mutex() const + { return static_cast(m_shmem.get_user_address()); } + + ipcdetail::managed_open_or_create_impl m_shmem; + typedef ipcdetail::named_creation_functor construct_func_t; + /// @endcond +}; + +/// @cond + +inline named_sharable_mutex::~named_sharable_mutex() +{} + +inline named_sharable_mutex::named_sharable_mutex + (create_only_t, const char *name, const permissions &perm) + : m_shmem (create_only + ,name + ,sizeof(interprocess_sharable_mutex) + + ipcdetail::managed_open_or_create_impl:: + ManagedOpenOrCreateUserOffset + ,read_write + ,0 + ,construct_func_t(ipcdetail::DoCreate) + ,perm) +{} + +inline named_sharable_mutex::named_sharable_mutex + (open_or_create_t, const char *name, const permissions &perm) + : m_shmem (open_or_create + ,name + ,sizeof(interprocess_sharable_mutex) + + ipcdetail::managed_open_or_create_impl:: + ManagedOpenOrCreateUserOffset + ,read_write + ,0 + ,construct_func_t(ipcdetail::DoOpenOrCreate) + ,perm) +{} + +inline named_sharable_mutex::named_sharable_mutex + (open_only_t, const char *name) + : m_shmem (open_only + ,name + ,read_write + ,0 + ,construct_func_t(ipcdetail::DoOpen)) +{} + +inline void named_sharable_mutex::dont_close_on_destruction() +{ ipcdetail::interprocess_tester::dont_close_on_destruction(m_shmem); } + +inline void named_sharable_mutex::lock() +{ this->mutex()->lock(); } + +inline void named_sharable_mutex::unlock() +{ this->mutex()->unlock(); } + +inline bool named_sharable_mutex::try_lock() +{ return this->mutex()->try_lock(); } + +inline bool named_sharable_mutex::timed_lock + (const boost::posix_time::ptime &abs_time) +{ return this->mutex()->timed_lock(abs_time); } + +inline void named_sharable_mutex::lock_sharable() +{ this->mutex()->lock_sharable(); } + +inline void named_sharable_mutex::unlock_sharable() +{ this->mutex()->unlock_sharable(); } + +inline bool named_sharable_mutex::try_lock_sharable() +{ return this->mutex()->try_lock_sharable(); } + +inline bool named_sharable_mutex::timed_lock_sharable + (const boost::posix_time::ptime &abs_time) +{ return this->mutex()->timed_lock_sharable(abs_time); } + +inline bool named_sharable_mutex::remove(const char *name) +{ return shared_memory_object::remove(name); } + +/// @endcond + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_NAMED_SHARABLE_MUTEX_HPP diff --git a/include/boost/interprocess/sync/named_upgradable_mutex.hpp b/include/boost/interprocess/sync/named_upgradable_mutex.hpp index c45fd08..d75f706 100644 --- a/include/boost/interprocess/sync/named_upgradable_mutex.hpp +++ b/include/boost/interprocess/sync/named_upgradable_mutex.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -56,7 +56,7 @@ class named_upgradable_mutex //!If the upgradable mutex can't be created throws interprocess_exception named_upgradable_mutex(create_only_t create_only, const char *name, const permissions &perm = permissions()); - //!Opens or creates a global upgradable mutex with a name, and an initial count. + //!Opens or creates a global upgradable mutex with a name. //!If the upgradable mutex is created, this call is equivalent to //!named_upgradable_mutex(create_only_t, ...) //!If the upgradable mutex is already created, this call is equivalent to @@ -215,6 +215,12 @@ class named_upgradable_mutex //!Throws: An exception derived from interprocess_exception on error. bool try_unlock_sharable_and_lock(); + //!Precondition: The thread must have sharable ownership of the mutex. + //!Effects: The thread atomically releases sharable ownership and tries to acquire + //! upgradable ownership. This operation will fail if there are threads with sharable + //! or upgradable ownership, but it will maintain sharable ownership. + //!Returns: If acquires upgradable ownership, returns true. Otherwise returns false. + //!Throws: An exception derived from interprocess_exception on error. bool try_unlock_sharable_and_lock_upgradable(); //!Erases a named upgradable mutex from the system. @@ -288,13 +294,7 @@ inline bool named_upgradable_mutex::try_lock() inline bool named_upgradable_mutex::timed_lock (const boost::posix_time::ptime &abs_time) -{ - if(abs_time == boost::posix_time::pos_infin){ - this->lock(); - return true; - } - return this->mutex()->timed_lock(abs_time); -} +{ return this->mutex()->timed_lock(abs_time); } inline void named_upgradable_mutex::lock_upgradable() { this->mutex()->lock_upgradable(); } @@ -307,13 +307,7 @@ inline bool named_upgradable_mutex::try_lock_upgradable() inline bool named_upgradable_mutex::timed_lock_upgradable (const boost::posix_time::ptime &abs_time) -{ - if(abs_time == boost::posix_time::pos_infin){ - this->lock_upgradable(); - return true; - } - return this->mutex()->timed_lock_upgradable(abs_time); -} +{ return this->mutex()->timed_lock_upgradable(abs_time); } inline void named_upgradable_mutex::lock_sharable() { this->mutex()->lock_sharable(); } @@ -326,13 +320,7 @@ inline bool named_upgradable_mutex::try_lock_sharable() inline bool named_upgradable_mutex::timed_lock_sharable (const boost::posix_time::ptime &abs_time) -{ - if(abs_time == boost::posix_time::pos_infin){ - this->lock_sharable(); - return true; - } - return this->mutex()->timed_lock_sharable(abs_time); -} +{ return this->mutex()->timed_lock_sharable(abs_time); } inline void named_upgradable_mutex::unlock_and_lock_upgradable() { this->mutex()->unlock_and_lock_upgradable(); } diff --git a/include/boost/interprocess/sync/null_mutex.hpp b/include/boost/interprocess/sync/null_mutex.hpp index afe444e..d9f69a6 100644 --- a/include/boost/interprocess/sync/null_mutex.hpp +++ b/include/boost/interprocess/sync/null_mutex.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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/include/boost/interprocess/sync/posix/condition.hpp b/include/boost/interprocess/sync/posix/condition.hpp index 48be099..2deea0f 100644 --- a/include/boost/interprocess/sync/posix/condition.hpp +++ b/include/boost/interprocess/sync/posix/condition.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -19,7 +19,7 @@ #include #include -#include +#include #include #include #include @@ -145,21 +145,21 @@ inline posix_condition::~posix_condition() { int res = 0; res = pthread_cond_destroy(&m_condition); - BOOST_ASSERT(res == 0); + BOOST_ASSERT(res == 0); (void)res; } inline void posix_condition::notify_one() { int res = 0; res = pthread_cond_signal(&m_condition); - BOOST_ASSERT(res == 0); + BOOST_ASSERT(res == 0); (void)res; } inline void posix_condition::notify_all() { int res = 0; res = pthread_cond_broadcast(&m_condition); - BOOST_ASSERT(res == 0); + BOOST_ASSERT(res == 0); (void)res; } inline void posix_condition::do_wait(posix_mutex &mut) @@ -167,7 +167,7 @@ inline void posix_condition::do_wait(posix_mutex &mut) pthread_mutex_t* pmutex = &mut.m_mut; int res = 0; res = pthread_cond_wait(&m_condition, pmutex); - BOOST_ASSERT(res == 0); + BOOST_ASSERT(res == 0); (void)res; } inline bool posix_condition::do_timed_wait diff --git a/include/boost/interprocess/sync/posix/mutex.hpp b/include/boost/interprocess/sync/posix/mutex.hpp index 393807c..344c5e9 100644 --- a/include/boost/interprocess/sync/posix/mutex.hpp +++ b/include/boost/interprocess/sync/posix/mutex.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -35,7 +35,7 @@ #include #include -#include +#include #include #include #include @@ -140,6 +140,7 @@ inline void posix_mutex::unlock() { int res = 0; res = pthread_mutex_unlock(&m_mut); + (void)res; BOOST_ASSERT(res == 0); } diff --git a/include/boost/interprocess/sync/posix/named_mutex.hpp b/include/boost/interprocess/sync/posix/named_mutex.hpp index 931c731..1b03b7d 100644 --- a/include/boost/interprocess/sync/posix/named_mutex.hpp +++ b/include/boost/interprocess/sync/posix/named_mutex.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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/include/boost/interprocess/sync/posix/named_semaphore.hpp b/include/boost/interprocess/sync/posix/named_semaphore.hpp index f0327a4..0b7ca8b 100644 --- a/include/boost/interprocess/sync/posix/named_semaphore.hpp +++ b/include/boost/interprocess/sync/posix/named_semaphore.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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/include/boost/interprocess/sync/posix/pthread_helpers.hpp b/include/boost/interprocess/sync/posix/pthread_helpers.hpp index bcbc44b..9e989d5 100644 --- a/include/boost/interprocess/sync/posix/pthread_helpers.hpp +++ b/include/boost/interprocess/sync/posix/pthread_helpers.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -19,8 +19,8 @@ #include #include -#include -#include +#include +#include namespace boost { namespace interprocess { @@ -86,7 +86,7 @@ namespace ipcdetail{ void release() {mp_mut = 0; } - private: + private: pthread_mutex_t *mp_mut; }; @@ -105,7 +105,7 @@ namespace ipcdetail{ void release() { mp_cond = 0; } - private: + private: pthread_cond_t *mp_cond; }; @@ -151,7 +151,7 @@ namespace ipcdetail{ void release() {mp_barrier = 0; } - private: + private: pthread_barrier_t *mp_barrier; }; diff --git a/include/boost/interprocess/sync/posix/ptime_to_timespec.hpp b/include/boost/interprocess/sync/posix/ptime_to_timespec.hpp index 7d78735..3e20dc7 100644 --- a/include/boost/interprocess/sync/posix/ptime_to_timespec.hpp +++ b/include/boost/interprocess/sync/posix/ptime_to_timespec.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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/include/boost/interprocess/sync/posix/recursive_mutex.hpp b/include/boost/interprocess/sync/posix/recursive_mutex.hpp index 456c9a4..385d714 100644 --- a/include/boost/interprocess/sync/posix/recursive_mutex.hpp +++ b/include/boost/interprocess/sync/posix/recursive_mutex.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -31,7 +31,7 @@ #include #include -#include +#include #include #include #include @@ -130,7 +130,7 @@ inline void posix_recursive_mutex::unlock() { int res = 0; res = pthread_mutex_unlock(&m_mut); - BOOST_ASSERT(res == 0); + BOOST_ASSERT(res == 0); (void)res; } } //namespace ipcdetail { diff --git a/include/boost/interprocess/sync/posix/semaphore.hpp b/include/boost/interprocess/sync/posix/semaphore.hpp index b7f62cc..5d7dfa8 100644 --- a/include/boost/interprocess/sync/posix/semaphore.hpp +++ b/include/boost/interprocess/sync/posix/semaphore.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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/include/boost/interprocess/sync/posix/semaphore_wrapper.hpp b/include/boost/interprocess/sync/posix/semaphore_wrapper.hpp index 22184cd..f6aef56 100644 --- a/include/boost/interprocess/sync/posix/semaphore_wrapper.hpp +++ b/include/boost/interprocess/sync/posix/semaphore_wrapper.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -103,7 +103,7 @@ inline bool semaphore_open inline void semaphore_close(sem_t *handle) { int ret = sem_close(handle); - if(ret != 0){ + if(ret != 0){ BOOST_ASSERT(0); } } @@ -138,7 +138,7 @@ inline void semaphore_init(sem_t *handle, unsigned int initialCount) inline void semaphore_destroy(sem_t *handle) { int ret = sem_destroy(handle); - if(ret != 0){ + if(ret != 0){ BOOST_ASSERT(0); } } diff --git a/include/boost/interprocess/sync/scoped_lock.hpp b/include/boost/interprocess/sync/scoped_lock.hpp index 61fe93e..5709f6f 100644 --- a/include/boost/interprocess/sync/scoped_lock.hpp +++ b/include/boost/interprocess/sync/scoped_lock.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -157,7 +157,7 @@ class scoped_lock //! a)if try_unlock_upgradable_and_lock() returns true then mutex() obtains //! the value from upgr.release() and owns() is set to true. //! b)if try_unlock_upgradable_and_lock() returns false then upgr is - //! unaffected and this scoped_lock construction as the same effects as + //! unaffected and this scoped_lock construction as the same effects as //! a default construction. //! c)Else upgr.owns() is false. mutex() obtains the value from upgr.release() //! and owns() is set to false @@ -259,7 +259,7 @@ class scoped_lock //! mutex after the assignment (and scop will not), but the mutex's lock //! count will be decremented by one. scoped_lock &operator=(BOOST_RV_REF(scoped_lock) scop) - { + { if(this->owns()) this->unlock(); m_locked = scop.owns(); diff --git a/include/boost/interprocess/sync/sharable_lock.hpp b/include/boost/interprocess/sync/sharable_lock.hpp index 9342e45..1130195 100644 --- a/include/boost/interprocess/sync/sharable_lock.hpp +++ b/include/boost/interprocess/sync/sharable_lock.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -189,7 +189,7 @@ class sharable_lock //! before the assignment. In this case, this will own the mutex after the assignment //! (and upgr will not), but the mutex's lock count will be decremented by one. sharable_lock &operator=(BOOST_RV_REF(sharable_lock) upgr) - { + { if(this->owns()) this->unlock(); m_locked = upgr.owns(); @@ -203,7 +203,7 @@ class sharable_lock //!Notes: The sharable_lock changes from a state of not owning the //! mutex, to owning the mutex, blocking if necessary. void lock() - { + { if(!mp_mutex || m_locked) throw lock_exception(); mp_mutex->lock_sharable(); @@ -219,7 +219,7 @@ class sharable_lock //! mutex_type does not support try_lock_sharable(), this function will //! fail at compile time if instantiated, but otherwise have no effect. bool try_lock() - { + { if(!mp_mutex || m_locked) throw lock_exception(); m_locked = mp_mutex->try_lock_sharable(); @@ -236,7 +236,7 @@ class sharable_lock //! timed_lock_sharable(), this function will fail at compile time if //! instantiated, but otherwise have no effect. bool timed_lock(const boost::posix_time::ptime& abs_time) - { + { if(!mp_mutex || m_locked) throw lock_exception(); m_locked = mp_mutex->timed_lock_sharable(abs_time); diff --git a/include/boost/interprocess/sync/shm/named_condition.hpp b/include/boost/interprocess/sync/shm/named_condition.hpp index 9d7cd77..a31b5b3 100644 --- a/include/boost/interprocess/sync/shm/named_condition.hpp +++ b/include/boost/interprocess/sync/shm/named_condition.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -29,8 +29,11 @@ #include #include #if defined (BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES) -#include -#include + #include + #include + #include +#else + #include #endif @@ -122,106 +125,35 @@ class shm_named_condition /// @cond private: - struct condition_holder - { - interprocess_condition cond_; - //If named_mutex is implemented using semaphores - //we need to store an additional mutex - #if defined (BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES) - interprocess_mutex mutex_; - #endif - }; - - interprocess_condition *condition() const - { return &static_cast(m_shmem.get_user_address())->cond_; } - - template - class lock_inverter - { - Lock &l_; - public: - lock_inverter(Lock &l) - : l_(l) - {} - void lock() { l_.unlock(); } - void unlock() { l_.lock(); } - }; - - //If named mutex uses POSIX semaphores, then the shm based condition variable - //must use it's internal lock to wait, as sem_t does not store a pthread_mutex_t - //instance needed by pthread_mutex_cond_t #if defined (BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES) - interprocess_mutex *mutex() const - { return &static_cast(m_shmem.get_user_address())->mutex_; } + class internal_condition_members + { + public: + typedef interprocess_mutex mutex_type; + typedef interprocess_condition condvar_type; + + condvar_type& get_condvar() { return m_cond; } + mutex_type& get_mutex() { return m_mtx; } - template - void do_wait(Lock& lock) - { - //shm_named_condition only works with named_mutex - BOOST_STATIC_ASSERT((is_convertible::value == true)); - - //lock internal before unlocking external to avoid race with a notifier - scoped_lock internal_lock(*this->mutex()); - lock_inverter inverted_lock(lock); - scoped_lock > external_unlock(inverted_lock); + private: + mutex_type m_mtx; + condvar_type m_cond; + }; - //unlock internal first to avoid deadlock with near simultaneous waits - scoped_lock internal_unlock; - internal_lock.swap(internal_unlock); - this->condition()->wait(internal_unlock); - } - - template - bool do_timed_wait(Lock& lock, const boost::posix_time::ptime &abs_time) - { - //shm_named_condition only works with named_mutex - BOOST_STATIC_ASSERT((is_convertible::value == true)); - //lock internal before unlocking external to avoid race with a notifier - scoped_lock internal_lock(*this->mutex(), abs_time); - if(!internal_lock) return false; - lock_inverter inverted_lock(lock); - scoped_lock > external_unlock(inverted_lock); - - //unlock internal first to avoid deadlock with near simultaneous waits - scoped_lock internal_unlock; - internal_lock.swap(internal_unlock); - return this->condition()->timed_wait(internal_unlock, abs_time); - } - #else //defined (BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES) - template - class lock_wrapper - { - typedef void (lock_wrapper::*unspecified_bool_type)(); - public: - - typedef interprocess_mutex mutex_type; - - lock_wrapper(Lock &l) - : l_(l) - {} - - mutex_type* mutex() const - { return l_.mutex()->mutex(); } - - void lock() { l_.lock(); } - - void unlock() { l_.unlock(); } - - operator unspecified_bool_type() const - { return l_ ? &lock_wrapper::lock : 0; } - - private: - Lock &l_; - }; + typedef ipcdetail::condition_any_wrapper internal_condition; + #else //defined (BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES) + typedef interprocess_condition internal_condition; #endif //defined (BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES) + internal_condition m_cond; + friend class boost::interprocess::ipcdetail::interprocess_tester; void dont_close_on_destruction(); managed_open_or_create_impl m_shmem; template friend class boost::interprocess::ipcdetail::named_creation_functor; - typedef boost::interprocess::ipcdetail::named_creation_functor construct_func_t; + typedef boost::interprocess::ipcdetail::named_creation_functor construct_func_t; /// @endcond }; @@ -233,7 +165,7 @@ inline shm_named_condition::~shm_named_condition() inline shm_named_condition::shm_named_condition(create_only_t, const char *name, const permissions &perm) : m_shmem (create_only ,name - ,sizeof(condition_holder) + + ,sizeof(internal_condition) + managed_open_or_create_impl:: ManagedOpenOrCreateUserOffset ,read_write @@ -245,7 +177,7 @@ inline shm_named_condition::shm_named_condition(create_only_t, const char *name, inline shm_named_condition::shm_named_condition(open_or_create_t, const char *name, const permissions &perm) : m_shmem (open_or_create ,name - ,sizeof(condition_holder) + + ,sizeof(internal_condition) + managed_open_or_create_impl:: ManagedOpenOrCreateUserOffset ,read_write @@ -268,102 +200,65 @@ inline void shm_named_condition::dont_close_on_destruction() #if defined(BOOST_INTERPROCESS_NAMED_MUTEX_USES_POSIX_SEMAPHORES) inline void shm_named_condition::notify_one() -{ - scoped_lock internal_lock(*this->mutex()); - this->condition()->notify_one(); -} +{ m_cond.notify_one(); } inline void shm_named_condition::notify_all() -{ - scoped_lock internal_lock(*this->mutex()); - this->condition()->notify_all(); -} +{ m_cond.notify_all(); } template inline void shm_named_condition::wait(L& lock) -{ - if (!lock) - throw lock_exception(); - this->do_wait(lock); -} +{ m_cond.wait(lock); } template inline void shm_named_condition::wait(L& lock, Pr pred) -{ - if (!lock) - throw lock_exception(); - while (!pred()) - this->do_wait(lock); -} +{ m_cond.wait(lock, pred); } template inline bool shm_named_condition::timed_wait (L& lock, const boost::posix_time::ptime &abs_time) -{ - if(abs_time == boost::posix_time::pos_infin){ - this->wait(lock); - return true; - } - if (!lock) - throw lock_exception(); - return this->do_timed_wait(lock, abs_time); -} +{ return m_cond.timed_wait(lock, abs_time); } template inline bool shm_named_condition::timed_wait (L& lock, const boost::posix_time::ptime &abs_time, Pr pred) -{ - if(abs_time == boost::posix_time::pos_infin){ - this->wait(lock, pred); - return true; - } - if (!lock) - throw lock_exception(); - - while (!pred()){ - if(!this->do_timed_wait(lock, abs_time)){ - return pred(); - } - } - return true; -} +{ return m_cond.timed_wait(lock, abs_time, pred); } #else inline void shm_named_condition::notify_one() -{ this->condition()->notify_one(); } +{ m_cond.notify_one(); } inline void shm_named_condition::notify_all() -{ this->condition()->notify_all(); } +{ m_cond.notify_all(); } template inline void shm_named_condition::wait(L& lock) { - lock_wrapper newlock(lock); - this->condition()->wait(newlock); + internal_mutex_lock internal_lock(lock); + m_cond.wait(internal_lock); } template inline void shm_named_condition::wait(L& lock, Pr pred) { - lock_wrapper newlock(lock); - this->condition()->wait(newlock, pred); + internal_mutex_lock internal_lock(lock); + m_cond.wait(internal_lock, pred); } template inline bool shm_named_condition::timed_wait (L& lock, const boost::posix_time::ptime &abs_time) { - lock_wrapper newlock(lock); - return this->condition()->timed_wait(newlock, abs_time); + internal_mutex_lock internal_lock(lock); + return m_cond.timed_wait(internal_lock, abs_time); } template inline bool shm_named_condition::timed_wait (L& lock, const boost::posix_time::ptime &abs_time, Pr pred) { - lock_wrapper newlock(lock); - return this->condition()->timed_wait(newlock, abs_time, pred); + internal_mutex_lock internal_lock(lock); + return m_cond.timed_wait(internal_lock, abs_time, pred); } #endif diff --git a/include/boost/interprocess/sync/shm/named_condition_any.hpp b/include/boost/interprocess/sync/shm/named_condition_any.hpp new file mode 100644 index 0000000..74692ea --- /dev/null +++ b/include/boost/interprocess/sync/shm/named_condition_any.hpp @@ -0,0 +1,192 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2005-2012. 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_SHM_NAMED_CONDITION_ANY_HPP +#define BOOST_INTERPROCESS_SHM_NAMED_CONDITION_ANY_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//!\file +//!Describes process-shared variables interprocess_condition class + +namespace boost { +namespace interprocess { +namespace ipcdetail { + +/// @cond +class interprocess_tester; +/// @endcond + +//! A global condition variable that can be created by name. +//! This condition variable is designed to work with named_mutex and +//! can't be placed in shared memory or memory mapped files. +class shm_named_condition_any +{ + /// @cond + //Non-copyable + shm_named_condition_any(); + shm_named_condition_any(const shm_named_condition_any &); + shm_named_condition_any &operator=(const shm_named_condition_any &); + /// @endcond + public: + //!Creates a global condition with a name. + //!If the condition can't be created throws interprocess_exception + shm_named_condition_any(create_only_t create_only, const char *name, const permissions &perm = permissions()) + : m_shmem (create_only + ,name + ,sizeof(internal_condition) + + managed_open_or_create_impl:: + ManagedOpenOrCreateUserOffset + ,read_write + ,0 + ,construct_func_t(DoCreate) + ,perm) + {} + + //!Opens or creates a global condition with a name. + //!If the condition is created, this call is equivalent to + //!shm_named_condition_any(create_only_t, ... ) + //!If the condition is already created, this call is equivalent + //!shm_named_condition_any(open_only_t, ... ) + //!Does not throw + shm_named_condition_any(open_or_create_t open_or_create, const char *name, const permissions &perm = permissions()) + : m_shmem (open_or_create + ,name + ,sizeof(internal_condition) + + managed_open_or_create_impl:: + ManagedOpenOrCreateUserOffset + ,read_write + ,0 + ,construct_func_t(DoOpenOrCreate) + ,perm) + {} + + //!Opens a global condition with a name if that condition is previously + //!created. If it is not previously created this function throws + //!interprocess_exception. + shm_named_condition_any(open_only_t open_only, const char *name) + : m_shmem (open_only + ,name + ,read_write + ,0 + ,construct_func_t(DoOpen)) + {} + + //!Destroys *this and indicates that the calling process is finished using + //!the resource. The destructor function will deallocate + //!any system resources allocated by the system for use by this process for + //!this resource. The resource can still be opened again calling + //!the open constructor overload. To erase the resource from the system + //!use remove(). + ~shm_named_condition_any() + {} + + //!If there is a thread waiting on *this, change that + //!thread's state to ready. Otherwise there is no effect.*/ + void notify_one() + { m_cond.notify_one(); } + + //!Change the state of all threads waiting on *this to ready. + //!If there are no waiting threads, notify_all() has no effect. + void notify_all() + { m_cond.notify_all(); } + + //!Releases the lock on the named_mutex object associated with lock, blocks + //!the current thread of execution until readied by a call to + //!this->notify_one() or this->notify_all(), and then reacquires the lock. + template + void wait(L& lock) + { m_cond.wait(lock); } + + //!The same as: + //!while (!pred()) wait(lock) + template + void wait(L& lock, Pr pred) + { m_cond.wait(lock, pred); } + + //!Releases the lock on the named_mutex object associated with lock, blocks + //!the current thread of execution until readied by a call to + //!this->notify_one() or this->notify_all(), or until time abs_time is reached, + //!and then reacquires the lock. + //!Returns: false if time abs_time is reached, otherwise true. + template + bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time) + { return m_cond.timed_wait(lock, abs_time); } + + //!The same as: while (!pred()) { + //! if (!timed_wait(lock, abs_time)) return pred(); + //! } return true; + template + bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred) + { return m_cond.timed_wait(lock, abs_time, pred); } + + //!Erases a named condition from the system. + //!Returns false on error. Never throws. + static bool remove(const char *name) + { return shared_memory_object::remove(name); } + + /// @cond + private: + + class internal_condition_members + { + public: + typedef interprocess_mutex mutex_type; + typedef interprocess_condition condvar_type; + + condvar_type& get_condvar() { return m_cond; } + mutex_type& get_mutex() { return m_mtx; } + + private: + mutex_type m_mtx; + condvar_type m_cond; + }; + + typedef ipcdetail::condition_any_wrapper internal_condition; + + internal_condition m_cond; + + friend class boost::interprocess::ipcdetail::interprocess_tester; + void dont_close_on_destruction() + { interprocess_tester::dont_close_on_destruction(m_shmem); } + + managed_open_or_create_impl m_shmem; + + template friend class boost::interprocess::ipcdetail::named_creation_functor; + typedef boost::interprocess::ipcdetail::named_creation_functor construct_func_t; + /// @endcond +}; + +} //namespace ipcdetail +} //namespace interprocess +} //namespace boost + +#include + +#endif // BOOST_INTERPROCESS_SHM_NAMED_CONDITION_ANY_HPP diff --git a/include/boost/interprocess/sync/shm/named_creation_functor.hpp b/include/boost/interprocess/sync/shm/named_creation_functor.hpp index 9d752c8..ec28c8e 100644 --- a/include/boost/interprocess/sync/shm/named_creation_functor.hpp +++ b/include/boost/interprocess/sync/shm/named_creation_functor.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2007-2012. 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) // @@ -38,7 +38,7 @@ class named_creation_functor { new(address)T(m_arg); } bool operator()(void *address, std::size_t, bool created) const - { + { switch(m_creation_type){ case DoOpen: return true; diff --git a/include/boost/interprocess/sync/shm/named_mutex.hpp b/include/boost/interprocess/sync/shm/named_mutex.hpp index f32fa70..ad4b215 100644 --- a/include/boost/interprocess/sync/shm/named_mutex.hpp +++ b/include/boost/interprocess/sync/shm/named_mutex.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -100,8 +100,9 @@ class shm_named_mutex static bool remove(const char *name); /// @cond - interprocess_mutex *mutex() const - { return static_cast(m_shmem.get_user_address()); } + typedef interprocess_mutex internal_mutex_type; + interprocess_mutex &internal_mutex() + { return *static_cast(m_shmem.get_user_address()); } private: friend class ipcdetail::interprocess_tester; @@ -153,13 +154,13 @@ inline shm_named_mutex::shm_named_mutex(open_only_t, const char *name) {} inline void shm_named_mutex::lock() -{ this->mutex()->lock(); } +{ this->internal_mutex().lock(); } inline void shm_named_mutex::unlock() -{ this->mutex()->unlock(); } +{ this->internal_mutex().unlock(); } inline bool shm_named_mutex::try_lock() -{ return this->mutex()->try_lock(); } +{ return this->internal_mutex().try_lock(); } inline bool shm_named_mutex::timed_lock(const boost::posix_time::ptime &abs_time) { @@ -167,7 +168,7 @@ inline bool shm_named_mutex::timed_lock(const boost::posix_time::ptime &abs_time this->lock(); return true; } - return this->mutex()->timed_lock(abs_time); + return this->internal_mutex().timed_lock(abs_time); } inline bool shm_named_mutex::remove(const char *name) diff --git a/include/boost/interprocess/sync/shm/named_recursive_mutex.hpp b/include/boost/interprocess/sync/shm/named_recursive_mutex.hpp index 7235571..28da749 100644 --- a/include/boost/interprocess/sync/shm/named_recursive_mutex.hpp +++ b/include/boost/interprocess/sync/shm/named_recursive_mutex.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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/include/boost/interprocess/sync/shm/named_semaphore.hpp b/include/boost/interprocess/sync/shm/named_semaphore.hpp index c6d3830..14034c2 100644 --- a/include/boost/interprocess/sync/shm/named_semaphore.hpp +++ b/include/boost/interprocess/sync/shm/named_semaphore.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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/include/boost/interprocess/sync/shm/named_upgradable_mutex.hpp b/include/boost/interprocess/sync/shm/named_upgradable_mutex.hpp index 0975a6e..191a6b6 100644 --- a/include/boost/interprocess/sync/shm/named_upgradable_mutex.hpp +++ b/include/boost/interprocess/sync/shm/named_upgradable_mutex.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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/include/boost/interprocess/sync/spin/condition.hpp b/include/boost/interprocess/sync/spin/condition.hpp index 55dd79b..7c3306d 100644 --- a/include/boost/interprocess/sync/spin/condition.hpp +++ b/include/boost/interprocess/sync/spin/condition.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -110,7 +110,7 @@ inline spin_condition::spin_condition() } inline spin_condition::~spin_condition() -{ +{ //Trivial destructor } @@ -171,7 +171,7 @@ inline bool spin_condition::do_timed_wait(bool tout_enabled, InterprocessMutex &mut) { boost::posix_time::ptime now = microsec_clock::universal_time(); - + if(tout_enabled){ if(now >= abs_time) return false; } @@ -205,7 +205,7 @@ inline bool spin_condition::do_timed_wait(bool tout_enabled, //By default, we suppose that no timeout has happened bool timed_out = false, unlock_enter_mut= false; - + //Loop until a notification indicates that the thread should //exit or timeout occurs while(1){ @@ -253,7 +253,7 @@ inline bool spin_condition::do_timed_wait(bool tout_enabled, continue; } else if(result == NOTIFY_ONE){ - //If it was a NOTIFY_ONE command, only this thread should + //If it was a NOTIFY_ONE command, only this thread should //exit. This thread has atomically marked command as sleep before //so no other thread will exit. //Decrement wait count. diff --git a/include/boost/interprocess/sync/spin/mutex.hpp b/include/boost/interprocess/sync/spin/mutex.hpp index 926f723..94c26a1 100644 --- a/include/boost/interprocess/sync/spin/mutex.hpp +++ b/include/boost/interprocess/sync/spin/mutex.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -73,7 +73,7 @@ inline void spin_mutex::lock(void) inline bool spin_mutex::try_lock(void) { - boost::uint32_t prev_s = ipcdetail::atomic_cas32(const_cast(&m_s), 1, 0); + boost::uint32_t prev_s = ipcdetail::atomic_cas32(const_cast(&m_s), 1, 0); return m_s == 1 && prev_s == 0; } diff --git a/include/boost/interprocess/sync/spin/recursive_mutex.hpp b/include/boost/interprocess/sync/spin/recursive_mutex.hpp index a763f9c..38e9dca 100644 --- a/include/boost/interprocess/sync/spin/recursive_mutex.hpp +++ b/include/boost/interprocess/sync/spin/recursive_mutex.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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/include/boost/interprocess/sync/spin/semaphore.hpp b/include/boost/interprocess/sync/spin/semaphore.hpp index 1b8cac3..a5ba3b1 100644 --- a/include/boost/interprocess/sync/spin/semaphore.hpp +++ b/include/boost/interprocess/sync/spin/semaphore.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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/include/boost/interprocess/sync/upgradable_lock.hpp b/include/boost/interprocess/sync/upgradable_lock.hpp index fb86374..6b766fd 100644 --- a/include/boost/interprocess/sync/upgradable_lock.hpp +++ b/include/boost/interprocess/sync/upgradable_lock.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -207,7 +207,7 @@ class upgradable_lock //!Notes: The sharable_lock changes from a state of not owning the mutex, //! to owning the mutex, blocking if necessary. void lock() - { + { if(!mp_mutex || m_locked) throw lock_exception(); mp_mutex->lock_upgradable(); @@ -223,7 +223,7 @@ class upgradable_lock //! mutex_type does not support try_lock_upgradable(), this function will //! fail at compile time if instantiated, but otherwise have no effect. bool try_lock() - { + { if(!mp_mutex || m_locked) throw lock_exception(); m_locked = mp_mutex->try_lock_upgradable(); @@ -240,7 +240,7 @@ class upgradable_lock //! timed_lock_upgradable(abs_time), this function will fail at compile //! time if instantiated, but otherwise have no effect. bool timed_lock(const boost::posix_time::ptime& abs_time) - { + { if(!mp_mutex || m_locked) throw lock_exception(); m_locked = mp_mutex->timed_lock_upgradable(abs_time); diff --git a/include/boost/interprocess/sync/windows/condition.hpp b/include/boost/interprocess/sync/windows/condition.hpp index 9695c21..6277951 100644 --- a/include/boost/interprocess/sync/windows/condition.hpp +++ b/include/boost/interprocess/sync/windows/condition.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -33,63 +33,34 @@ class windows_condition windows_condition &operator=(const windows_condition &); public: - windows_condition(); - ~windows_condition(); + windows_condition() + : m_condition_data() + {} - void notify_one(); - void notify_all(); + ~windows_condition() + {} + + void notify_one() + { m_condition_data.notify_one(); } + + void notify_all() + { m_condition_data.notify_all(); } template bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time) - { - if(abs_time == boost::posix_time::pos_infin){ - this->wait(lock); - return true; - } - if (!lock) - throw lock_exception(); - return this->do_timed_wait(abs_time, *lock.mutex()); - } + { return m_condition_data.timed_wait(lock, abs_time); } template bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred) - { - if(abs_time == boost::posix_time::pos_infin){ - this->wait(lock, pred); - return true; - } - if (!lock) - throw lock_exception(); - while (!pred()){ - if (!this->do_timed_wait(abs_time, *lock.mutex())) - return pred(); - } - return true; - } + { return m_condition_data.timed_wait(lock, abs_time, pred); } template void wait(L& lock) - { - if (!lock) - throw lock_exception(); - do_wait(*lock.mutex()); - } + { m_condition_data.wait(lock); } template void wait(L& lock, Pr pred) - { - if (!lock) - throw lock_exception(); - - while (!pred()) - do_wait(*lock.mutex()); - } - - template - void do_wait(InterprocessMutex &mut); - - template - bool do_timed_wait(const boost::posix_time::ptime &abs_time, InterprocessMutex &mut); + { m_condition_data.wait(lock, pred); } private: @@ -132,33 +103,11 @@ class windows_condition windows_semaphore m_sem_block_queue; windows_semaphore m_sem_block_lock; windows_mutex m_mtx_unblock_lock; - } m_condition_data; + }; - typedef condition_algorithm_8a algorithm_type; + ipcdetail::condition_8a_wrapper m_condition_data; }; -inline windows_condition::windows_condition() - : m_condition_data() -{} - -inline windows_condition::~windows_condition() -{} - -inline void windows_condition::notify_one() -{ algorithm_type::signal(m_condition_data, false); } - -inline void windows_condition::notify_all() -{ algorithm_type::signal(m_condition_data, true); } - -template -inline void windows_condition::do_wait(InterprocessMutex &mut) -{ algorithm_type::wait(m_condition_data, false, boost::posix_time::ptime(), mut); } - -template -inline bool windows_condition::do_timed_wait - (const boost::posix_time::ptime &abs_time, InterprocessMutex &mut) -{ return algorithm_type::wait(m_condition_data, true, abs_time, mut); } - } //namespace ipcdetail } //namespace interprocess } //namespace boost diff --git a/include/boost/interprocess/sync/windows/mutex.hpp b/include/boost/interprocess/sync/windows/mutex.hpp index 477acd3..7da70f4 100644 --- a/include/boost/interprocess/sync/windows/mutex.hpp +++ b/include/boost/interprocess/sync/windows/mutex.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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/include/boost/interprocess/sync/windows/named_condition.hpp b/include/boost/interprocess/sync/windows/named_condition.hpp index 403e826..4724482 100644 --- a/include/boost/interprocess/sync/windows/named_condition.hpp +++ b/include/boost/interprocess/sync/windows/named_condition.hpp @@ -17,313 +17,13 @@ #include #include -#include -#include -#include -#include -#include -#include -#include +#include namespace boost { namespace interprocess { namespace ipcdetail { -class windows_named_condition -{ - /// @cond - - //Non-copyable - windows_named_condition(); - windows_named_condition(const windows_named_condition &); - windows_named_condition &operator=(const windows_named_condition &); - /// @endcond - - public: - windows_named_condition(create_only_t, const char *name, const permissions &perm = permissions()); - - windows_named_condition(open_or_create_t, const char *name, const permissions &perm = permissions()); - - windows_named_condition(open_only_t, const char *name); - - ~windows_named_condition(); - - //!If there is a thread waiting on *this, change that - //!thread's state to ready. Otherwise there is no effect.*/ - void notify_one(); - - //!Change the state of all threads waiting on *this to ready. - //!If there are no waiting threads, notify_all() has no effect. - void notify_all(); - - //!Releases the lock on the named_mutex object associated with lock, blocks - //!the current thread of execution until readied by a call to - //!this->notify_one() or this->notify_all(), and then reacquires the lock. - template - void wait(L& lock); - - //!The same as: - //!while (!pred()) wait(lock) - template - void wait(L& lock, Pr pred); - - //!Releases the lock on the named_mutex object associated with lock, blocks - //!the current thread of execution until readied by a call to - //!this->notify_one() or this->notify_all(), or until time abs_time is reached, - //!and then reacquires the lock. - //!Returns: false if time abs_time is reached, otherwise true. - template - bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time); - - //!The same as: while (!pred()) { - //! if (!timed_wait(lock, abs_time)) return pred(); - //! } return true; - template - bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred); - - static bool remove(const char *name); - - /// @cond - private: - friend class interprocess_tester; - void dont_close_on_destruction(); - - template - void do_wait(InterprocessMutex& lock); - - template - bool do_timed_wait(const boost::posix_time::ptime &abs_time, InterprocessMutex& lock); - - struct condition_data - { - typedef boost::int32_t integer_type; - typedef winapi_semaphore_wrapper semaphore_type; - typedef winapi_mutex_wrapper mutex_type; - - integer_type &get_nwaiters_blocked() - { return m_nwaiters_blocked; } - - integer_type &get_nwaiters_gone() - { return m_nwaiters_gone; } - - integer_type &get_nwaiters_to_unblock() - { return m_nwaiters_to_unblock; } - - semaphore_type &get_sem_block_queue() - { return m_sem_block_queue; } - - semaphore_type &get_sem_block_lock() - { return m_sem_block_lock; } - - mutex_type &get_mtx_unblock_lock() - { return m_mtx_unblock_lock; } - - integer_type m_nwaiters_blocked; - integer_type m_nwaiters_gone; - integer_type m_nwaiters_to_unblock; - winapi_semaphore_wrapper m_sem_block_queue; - winapi_semaphore_wrapper m_sem_block_lock; - winapi_mutex_wrapper m_mtx_unblock_lock; - } m_condition_data; - - typedef condition_algorithm_8a algorithm_type; - - class named_cond_callbacks : public windows_named_sync_interface - { - typedef __int64 sem_count_t; - mutable sem_count_t sem_counts [2]; - - public: - named_cond_callbacks(condition_data &cond_data) - : m_condition_data(cond_data) - {} - - virtual std::size_t get_data_size() const - { return sizeof(sem_counts); } - - virtual const void *buffer_with_final_data_to_file() - { - sem_counts[0] = m_condition_data.m_sem_block_queue.value(); - sem_counts[1] = m_condition_data.m_sem_block_lock.value(); - return &sem_counts; - } - - virtual const void *buffer_with_init_data_to_file() - { - sem_counts[0] = 0; - sem_counts[1] = 1; - return &sem_counts; - } - - virtual void *buffer_to_store_init_data_from_file() - { return &sem_counts; } - - virtual bool open(create_enum_t, const char *id_name) - { - m_condition_data.m_nwaiters_blocked = 0; - m_condition_data.m_nwaiters_gone = 0; - m_condition_data.m_nwaiters_to_unblock = 0; - - //Now open semaphores and mutex. - //Use local variables + swap to guarantee consistent - //initialization and cleanup in case any opening fails - permissions perm; - perm.set_unrestricted(); - std::string aux_str = "Global\\bipc.cond."; - aux_str += id_name; - std::size_t pos = aux_str.size(); - - //sem_block_queue - aux_str += "_bq"; - winapi_semaphore_wrapper sem_block_queue; - bool created; - if(!sem_block_queue.open_or_create - (aux_str.c_str(), sem_counts[0], winapi_semaphore_wrapper::MaxCount, perm, created)) - return false; - aux_str.erase(pos); - - //sem_block_lock - aux_str += "_bl"; - winapi_semaphore_wrapper sem_block_lock; - if(!sem_block_lock.open_or_create - (aux_str.c_str(), sem_counts[1], winapi_semaphore_wrapper::MaxCount, perm, created)) - return false; - aux_str.erase(pos); - - //mtx_unblock_lock - aux_str += "_ul"; - winapi_mutex_wrapper mtx_unblock_lock; - if(!mtx_unblock_lock.open_or_create(aux_str.c_str(), perm)) - return false; - - //All ok, commit data - m_condition_data.m_sem_block_queue.swap(sem_block_queue); - m_condition_data.m_sem_block_lock.swap(sem_block_lock); - m_condition_data.m_mtx_unblock_lock.swap(mtx_unblock_lock); - return true; - } - - virtual void close() - { - m_condition_data.m_sem_block_queue.close(); - m_condition_data.m_sem_block_lock.close(); - m_condition_data.m_mtx_unblock_lock.close(); - m_condition_data.m_nwaiters_blocked = 0; - m_condition_data.m_nwaiters_gone = 0; - m_condition_data.m_nwaiters_to_unblock = 0; - } - - virtual ~named_cond_callbacks() - {} - - private: - condition_data &m_condition_data; - }; - - windows_named_sync m_named_sync; - /// @endcond -}; - -inline windows_named_condition::~windows_named_condition() -{ - named_cond_callbacks callbacks(m_condition_data); - m_named_sync.close(callbacks); -} - -inline void windows_named_condition::dont_close_on_destruction() -{} - -inline windows_named_condition::windows_named_condition - (create_only_t, const char *name, const permissions &perm) - : m_condition_data() -{ - named_cond_callbacks callbacks(m_condition_data); - m_named_sync.open_or_create(DoCreate, name, perm, callbacks); -} - -inline windows_named_condition::windows_named_condition - (open_or_create_t, const char *name, const permissions &perm) - : m_condition_data() -{ - named_cond_callbacks callbacks(m_condition_data); - m_named_sync.open_or_create(DoOpenOrCreate, name, perm, callbacks); -} - -inline windows_named_condition::windows_named_condition(open_only_t, const char *name) - : m_condition_data() -{ - named_cond_callbacks callbacks(m_condition_data); - m_named_sync.open_or_create(DoOpen, name, permissions(), callbacks); -} - -inline void windows_named_condition::notify_one() -{ algorithm_type::signal(m_condition_data, false); } - -inline void windows_named_condition::notify_all() -{ algorithm_type::signal(m_condition_data, true); } - -template -inline void windows_named_condition::do_wait(InterprocessMutex &mut) -{ algorithm_type::wait(m_condition_data, false, boost::posix_time::ptime(), mut); } - -template -inline bool windows_named_condition::do_timed_wait - (const boost::posix_time::ptime &abs_time, InterprocessMutex &mut) -{ return algorithm_type::wait(m_condition_data, true, abs_time, mut); } - -template -inline void windows_named_condition::wait(L& lock) -{ - if (!lock) - throw lock_exception(); - this->do_wait(*lock.mutex()); -} - -template -inline void windows_named_condition::wait(L& lock, Pr pred) -{ - if (!lock) - throw lock_exception(); - while (!pred()) - this->do_wait(*lock.mutex()); -} - -template -inline bool windows_named_condition::timed_wait - (L& lock, const boost::posix_time::ptime &abs_time) -{ - if(abs_time == boost::posix_time::pos_infin){ - this->wait(lock); - return true; - } - if (!lock) - throw lock_exception(); - return this->do_timed_wait(abs_time, *lock.mutex()); -} - -template -inline bool windows_named_condition::timed_wait - (L& lock, const boost::posix_time::ptime &abs_time, Pr pred) -{ - if(abs_time == boost::posix_time::pos_infin){ - this->wait(lock, pred); - return true; - } - if (!lock) - throw lock_exception(); - - while (!pred()){ - if(!this->do_timed_wait(abs_time, *lock.mutex())){ - return pred(); - } - } - return true; -} - -inline bool windows_named_condition::remove(const char *name) -{ - return windows_named_sync::remove(name); -} +typedef windows_named_condition_any windows_named_condition; } //namespace ipcdetail { } //namespace interprocess { diff --git a/include/boost/interprocess/sync/windows/named_condition_any.hpp b/include/boost/interprocess/sync/windows/named_condition_any.hpp new file mode 100644 index 0000000..0d3b915 --- /dev/null +++ b/include/boost/interprocess/sync/windows/named_condition_any.hpp @@ -0,0 +1,241 @@ + ////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2011-2012. 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_WINDOWS_NAMED_CONDITION_ANY_HPP +#define BOOST_INTERPROCESS_WINDOWS_NAMED_CONDITION_ANY_HPP + +#if (defined _MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace interprocess { +namespace ipcdetail { + +class windows_named_condition_any +{ + /// @cond + + //Non-copyable + windows_named_condition_any(); + windows_named_condition_any(const windows_named_condition_any &); + windows_named_condition_any &operator=(const windows_named_condition_any &); + /// @endcond + + public: + windows_named_condition_any + (create_only_t, const char *name, const permissions &perm) + : m_condition_data() + { + named_cond_callbacks callbacks(m_condition_data.get_members()); + m_named_sync.open_or_create(DoCreate, name, perm, callbacks); + } + + windows_named_condition_any + (open_or_create_t, const char *name, const permissions &perm) + : m_condition_data() + { + named_cond_callbacks callbacks(m_condition_data.get_members()); + m_named_sync.open_or_create(DoOpenOrCreate, name, perm, callbacks); + } + + windows_named_condition_any(open_only_t, const char *name) + : m_condition_data() + { + named_cond_callbacks callbacks(m_condition_data.get_members()); + m_named_sync.open_or_create(DoOpen, name, permissions(), callbacks); + } + + ~windows_named_condition_any() + { + named_cond_callbacks callbacks(m_condition_data.get_members()); + m_named_sync.close(callbacks); + } + + void notify_one() + { m_condition_data.notify_one(); } + + void notify_all() + { m_condition_data.notify_all(); } + + template + bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time) + { return m_condition_data.timed_wait(lock, abs_time); } + + template + bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred) + { return m_condition_data.timed_wait(lock, abs_time, pred); } + + template + void wait(L& lock) + { m_condition_data.wait(lock); } + + template + void wait(L& lock, Pr pred) + { m_condition_data.wait(lock, pred); } + + static bool remove(const char *name) + { return windows_named_sync::remove(name); } + + /// @cond + private: + + void windows_named_condition_any::dont_close_on_destruction() + {} + + friend class interprocess_tester; + + struct condition_data + { + typedef boost::int32_t integer_type; + typedef winapi_semaphore_wrapper semaphore_type; + typedef winapi_mutex_wrapper mutex_type; + + integer_type &get_nwaiters_blocked() + { return m_nwaiters_blocked; } + + integer_type &get_nwaiters_gone() + { return m_nwaiters_gone; } + + integer_type &get_nwaiters_to_unblock() + { return m_nwaiters_to_unblock; } + + semaphore_type &get_sem_block_queue() + { return m_sem_block_queue; } + + semaphore_type &get_sem_block_lock() + { return m_sem_block_lock; } + + mutex_type &get_mtx_unblock_lock() + { return m_mtx_unblock_lock; } + + integer_type m_nwaiters_blocked; + integer_type m_nwaiters_gone; + integer_type m_nwaiters_to_unblock; + winapi_semaphore_wrapper m_sem_block_queue; + winapi_semaphore_wrapper m_sem_block_lock; + winapi_mutex_wrapper m_mtx_unblock_lock; + }; + + ipcdetail::condition_8a_wrapper m_condition_data; + + class named_cond_callbacks : public windows_named_sync_interface + { + typedef __int64 sem_count_t; + mutable sem_count_t sem_counts [2]; + + public: + named_cond_callbacks(condition_data &cond_data) + : m_condition_data(cond_data) + {} + + virtual std::size_t get_data_size() const + { return sizeof(sem_counts); } + + virtual const void *buffer_with_final_data_to_file() + { + sem_counts[0] = m_condition_data.m_sem_block_queue.value(); + sem_counts[1] = m_condition_data.m_sem_block_lock.value(); + return &sem_counts; + } + + virtual const void *buffer_with_init_data_to_file() + { + sem_counts[0] = 0; + sem_counts[1] = 1; + return &sem_counts; + } + + virtual void *buffer_to_store_init_data_from_file() + { return &sem_counts; } + + virtual bool open(create_enum_t, const char *id_name) + { + m_condition_data.m_nwaiters_blocked = 0; + m_condition_data.m_nwaiters_gone = 0; + m_condition_data.m_nwaiters_to_unblock = 0; + + //Now open semaphores and mutex. + //Use local variables + swap to guarantee consistent + //initialization and cleanup in case any opening fails + permissions perm; + perm.set_unrestricted(); + std::string aux_str = "Global\\bipc.cond."; + aux_str += id_name; + std::size_t pos = aux_str.size(); + + //sem_block_queue + aux_str += "_bq"; + winapi_semaphore_wrapper sem_block_queue; + bool created; + if(!sem_block_queue.open_or_create + (aux_str.c_str(), sem_counts[0], winapi_semaphore_wrapper::MaxCount, perm, created)) + return false; + aux_str.erase(pos); + + //sem_block_lock + aux_str += "_bl"; + winapi_semaphore_wrapper sem_block_lock; + if(!sem_block_lock.open_or_create + (aux_str.c_str(), sem_counts[1], winapi_semaphore_wrapper::MaxCount, perm, created)) + return false; + aux_str.erase(pos); + + //mtx_unblock_lock + aux_str += "_ul"; + winapi_mutex_wrapper mtx_unblock_lock; + if(!mtx_unblock_lock.open_or_create(aux_str.c_str(), perm)) + return false; + + //All ok, commit data + m_condition_data.m_sem_block_queue.swap(sem_block_queue); + m_condition_data.m_sem_block_lock.swap(sem_block_lock); + m_condition_data.m_mtx_unblock_lock.swap(mtx_unblock_lock); + return true; + } + + virtual void close() + { + m_condition_data.m_sem_block_queue.close(); + m_condition_data.m_sem_block_lock.close(); + m_condition_data.m_mtx_unblock_lock.close(); + m_condition_data.m_nwaiters_blocked = 0; + m_condition_data.m_nwaiters_gone = 0; + m_condition_data.m_nwaiters_to_unblock = 0; + } + + virtual ~named_cond_callbacks() + {} + + private: + condition_data &m_condition_data; + }; + + windows_named_sync m_named_sync; + /// @endcond +}; + +} //namespace ipcdetail { +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_WINDOWS_NAMED_CONDITION_ANY_HPP diff --git a/include/boost/interprocess/sync/windows/recursive_mutex.hpp b/include/boost/interprocess/sync/windows/recursive_mutex.hpp index 9565cb6..2b4797e 100644 --- a/include/boost/interprocess/sync/windows/recursive_mutex.hpp +++ b/include/boost/interprocess/sync/windows/recursive_mutex.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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/include/boost/interprocess/sync/windows/semaphore.hpp b/include/boost/interprocess/sync/windows/semaphore.hpp index af336df..a8625a6 100644 --- a/include/boost/interprocess/sync/windows/semaphore.hpp +++ b/include/boost/interprocess/sync/windows/semaphore.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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/include/boost/interprocess/sync/windows/sync_utils.hpp b/include/boost/interprocess/sync/windows/sync_utils.hpp index 0281da1..10d0a55 100644 --- a/include/boost/interprocess/sync/windows/sync_utils.hpp +++ b/include/boost/interprocess/sync/windows/sync_utils.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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/include/boost/interprocess/sync/xsi/simple_xsi_semaphore.hpp b/include/boost/interprocess/sync/xsi/simple_xsi_semaphore.hpp index 266e7c5..deb429a 100644 --- a/include/boost/interprocess/sync/xsi/simple_xsi_semaphore.hpp +++ b/include/boost/interprocess/sync/xsi/simple_xsi_semaphore.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2011-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2011-2012. 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/include/boost/interprocess/sync/xsi/xsi_named_mutex.hpp b/include/boost/interprocess/sync/xsi/xsi_named_mutex.hpp index 485b1ac..f69f9cd 100644 --- a/include/boost/interprocess/sync/xsi/xsi_named_mutex.hpp +++ b/include/boost/interprocess/sync/xsi/xsi_named_mutex.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2009-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2009-2012. 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) // @@ -72,10 +72,10 @@ class xsi_named_mutex //!After the call, "moved" does not represent any named mutex. //!Does not throw xsi_named_mutex &operator=(BOOST_RV_REF(xsi_named_mutex) moved) - { + { xsi_named_mutex tmp(boost::move(moved)); this->swap(tmp); - return *this; + return *this; } //!Swaps two xsi_named_mutex. Does not throw @@ -142,7 +142,7 @@ inline void xsi_named_mutex::swap(xsi_named_mutex &other) std::swap(m_id, other.m_id); std::swap(m_semid, other.m_semid); std::swap(m_perm, other.m_perm); - m_path.swap(other.m_path); + m_path.swap(other.m_path); } inline mapping_handle_t xsi_named_mutex::get_mapping_handle() const diff --git a/include/boost/interprocess/windows_shared_memory.hpp b/include/boost/interprocess/windows_shared_memory.hpp index 76601bb..f2195ac 100644 --- a/include/boost/interprocess/windows_shared_memory.hpp +++ b/include/boost/interprocess/windows_shared_memory.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -88,10 +88,10 @@ class windows_shared_memory //!After the call, "moved" does not represent any shared memory. //!Does not throw windows_shared_memory &operator=(BOOST_RV_REF(windows_shared_memory) moved) - { + { windows_shared_memory tmp(boost::move(moved)); this->swap(tmp); - return *this; + return *this; } //!Swaps to shared_memory_objects. Does not throw @@ -140,10 +140,10 @@ inline const char *windows_shared_memory::get_name() const { return m_name.c_str(); } inline void windows_shared_memory::swap(windows_shared_memory &other) -{ +{ std::swap(m_handle, other.m_handle); std::swap(m_mode, other.m_mode); - m_name.swap(other.m_name); + m_name.swap(other.m_name); } inline mapping_handle_t windows_shared_memory::get_mapping_handle() const diff --git a/include/boost/interprocess/xsi_shared_memory.hpp b/include/boost/interprocess/xsi_shared_memory.hpp index e84d9b1..11cfe1d 100644 --- a/include/boost/interprocess/xsi_shared_memory.hpp +++ b/include/boost/interprocess/xsi_shared_memory.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2009. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2009-2012. 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) // @@ -89,10 +89,10 @@ class xsi_shared_memory //!After the call, "moved" does not represent any shared memory. //!Does not throw xsi_shared_memory &operator=(BOOST_RV_REF(xsi_shared_memory) moved) - { + { xsi_shared_memory tmp(boost::move(moved)); this->swap(tmp); - return *this; + return *this; } //!Swaps two xsi_shared_memorys. Does not throw diff --git a/proj/to-do.txt b/proj/to-do.txt index ec55fe2..658f4e0 100644 --- a/proj/to-do.txt +++ b/proj/to-do.txt @@ -249,3 +249,17 @@ MyRobustMutexLockFile() ipcdetail::intermodule_singleton::get(); +Add unsigned overflow checking with shortcut as explained here: + +https://github.com/ivmai/bdwgc/commit/83231d0ab5ed60015797c3d1ad9056295ac3b2bb + +# define GC_SIZE_MAX (~(size_t)0) + #endif ++#define GC_SQRT_SIZE_MAX ((1U << (WORDSZ / 2)) - 1) ++ +void * calloc(size_t n, size_t lb) +{ +- if (lb && n > GC_SIZE_MAX / lb) ++ if ((lb | n) > GC_SQRT_SIZE_MAX /* fast initial test */ ++ && lb && n > GC_SIZE_MAX / lb) + return NULL; diff --git a/proj/vc7ide/Interprocess.sln b/proj/vc7ide/Interprocess.sln index 029088d..0773ac8 100644 --- a/proj/vc7ide/Interprocess.sln +++ b/proj/vc7ide/Interprocess.sln @@ -463,6 +463,22 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "windows_shared_memory_test" ProjectSection(ProjectDependencies) = postProject EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sharable_mutex_test", "sharable_mutex.vcproj", "{4E88C1C2-0961-F7A4-F48E-A6A7D3B06004}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "condition_any_test", "condition_any_test.vcproj", "{5875E186-48F8-0992-26A7-D34F4A053798}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "named_sharable_mutex_test", "named_sharable_mutex.vcproj", "{4FB82CC8-9671-FA47-48FE-723BA0D91604}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "named_condition_any_test", "named_condition_any_test.vcproj", "{58CC2563-6092-48FE-FAF7-BA046A792658}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject Global GlobalSection(SolutionConfiguration) = preSolution Debug = Debug @@ -935,6 +951,22 @@ Global {E35C288C-F48E-6914-4FA7-5BA006383C10}.Debug.Build.0 = Debug|Win32 {E35C288C-F48E-6914-4FA7-5BA006383C10}.Release.ActiveCfg = Release|Win32 {E35C288C-F48E-6914-4FA7-5BA006383C10}.Release.Build.0 = Release|Win32 + {4E88C1C2-0961-F7A4-F48E-A6A7D3B06004}.Debug.ActiveCfg = Debug|Win32 + {4E88C1C2-0961-F7A4-F48E-A6A7D3B06004}.Debug.Build.0 = Debug|Win32 + {4E88C1C2-0961-F7A4-F48E-A6A7D3B06004}.Release.ActiveCfg = Release|Win32 + {4E88C1C2-0961-F7A4-F48E-A6A7D3B06004}.Release.Build.0 = Release|Win32 + {5875E186-48F8-0992-26A7-D34F4A053798}.Debug.ActiveCfg = Debug|Win32 + {5875E186-48F8-0992-26A7-D34F4A053798}.Debug.Build.0 = Debug|Win32 + {5875E186-48F8-0992-26A7-D34F4A053798}.Release.ActiveCfg = Release|Win32 + {5875E186-48F8-0992-26A7-D34F4A053798}.Release.Build.0 = Release|Win32 + {4FB82CC8-9671-FA47-48FE-723BA0D91604}.Debug.ActiveCfg = Debug|Win32 + {4FB82CC8-9671-FA47-48FE-723BA0D91604}.Debug.Build.0 = Debug|Win32 + {4FB82CC8-9671-FA47-48FE-723BA0D91604}.Release.ActiveCfg = Release|Win32 + {4FB82CC8-9671-FA47-48FE-723BA0D91604}.Release.Build.0 = Release|Win32 + {58CC2563-6092-48FE-FAF7-BA046A792658}.Debug.ActiveCfg = Debug|Win32 + {58CC2563-6092-48FE-FAF7-BA046A792658}.Debug.Build.0 = Debug|Win32 + {58CC2563-6092-48FE-FAF7-BA046A792658}.Release.ActiveCfg = Release|Win32 + {58CC2563-6092-48FE-FAF7-BA046A792658}.Release.Build.0 = Release|Win32 EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution EndGlobalSection diff --git a/proj/vc7ide/condition_any_test.vcproj b/proj/vc7ide/condition_any_test.vcproj new file mode 100644 index 0000000..3f6d4d7 --- /dev/null +++ b/proj/vc7ide/condition_any_test.vcproj @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/condition_test.vcproj b/proj/vc7ide/condition_test.vcproj index 5777e89..57eb01e 100644 --- a/proj/vc7ide/condition_test.vcproj +++ b/proj/vc7ide/condition_test.vcproj @@ -13,7 +13,7 @@ @@ -67,7 +67,7 @@ + + @@ -203,6 +206,9 @@ + + @@ -215,6 +221,9 @@ + + @@ -224,6 +233,9 @@ + + @@ -311,6 +323,9 @@ + + @@ -345,6 +360,9 @@ + + @@ -367,6 +385,12 @@ + + + + - - diff --git a/proj/vc7ide/message_queue.vcproj b/proj/vc7ide/message_queue.vcproj index 243a30e..46767f9 100644 --- a/proj/vc7ide/message_queue.vcproj +++ b/proj/vc7ide/message_queue.vcproj @@ -13,7 +13,7 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/named_sharable_mutex.vcproj b/proj/vc7ide/named_sharable_mutex.vcproj new file mode 100644 index 0000000..68a6433 --- /dev/null +++ b/proj/vc7ide/named_sharable_mutex.vcproj @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/proj/vc7ide/sharable_mutex.vcproj b/proj/vc7ide/sharable_mutex.vcproj new file mode 100644 index 0000000..adb58c5 --- /dev/null +++ b/proj/vc7ide/sharable_mutex.vcproj @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/adaptive_node_pool_test.cpp b/test/adaptive_node_pool_test.cpp index 365397d..66c0d83 100644 --- a/test/adaptive_node_pool_test.cpp +++ b/test/adaptive_node_pool_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2007-2012. 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/adaptive_pool_test.cpp b/test/adaptive_pool_test.cpp index 2b4443b..c642761 100644 --- a/test/adaptive_pool_test.cpp +++ b/test/adaptive_pool_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2004-2012. 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/allocator_v1.hpp b/test/allocator_v1.hpp index d833c26..6fb7dc2 100644 --- a/test/allocator_v1.hpp +++ b/test/allocator_v1.hpp @@ -1,6 +1,6 @@ /////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -29,6 +29,7 @@ #include #include #include +#include //!\file //!Describes an allocator_v1 that allocates portions of fixed size @@ -86,7 +87,7 @@ class allocator_v1 //!Obtains an allocator_v1 of other type template struct rebind - { + { typedef allocator_v1 other; }; @@ -118,7 +119,12 @@ class allocator_v1 //!Allocates memory for an array of count elements. //!Throws boost::interprocess::bad_alloc if there is no enough memory pointer allocate(size_type count, cvoid_ptr hint = 0) - { (void)hint; return pointer(static_cast(mp_mngr->allocate(count*sizeof(value_type)))); } + { + if(size_overflows(count)){ + throw bad_alloc(); + } + (void)hint; return pointer(static_cast(mp_mngr->allocate(count*sizeof(T)))); + } //!Deallocates memory previously allocated. Never throws void deallocate(const pointer &ptr, size_type) diff --git a/test/allocexcept_test.cpp b/test/allocexcept_test.cpp index 653ba94..2482f6f 100644 --- a/test/allocexcept_test.cpp +++ b/test/allocexcept_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2004-2012. 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) // @@ -59,7 +59,7 @@ int main () int i; for(i = 0; true; ++i){ myvec.push_back(InstanceCounter()); - } + } } catch(boost::interprocess::bad_alloc &){ if(InstanceCounter::counter != 0) @@ -74,7 +74,7 @@ int main () InstanceCounter ic; for(i = 0; true; ++i){ myvec.insert(myvec.begin(), i, ic); - } + } } catch(boost::interprocess::bad_alloc &){ if(InstanceCounter::counter != 0) diff --git a/test/anonymous_shared_memory_test.cpp b/test/anonymous_shared_memory_test.cpp index efe053d..cdff6e6 100644 --- a/test/anonymous_shared_memory_test.cpp +++ b/test/anonymous_shared_memory_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2004-2012. 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/boost_interprocess_check.hpp b/test/boost_interprocess_check.hpp index 5e79b8a..6107cf5 100644 --- a/test/boost_interprocess_check.hpp +++ b/test/boost_interprocess_check.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2004-2012. 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/bufferstream_test.cpp b/test/bufferstream_test.cpp index bcaaf9f..58d9d05 100644 --- a/test/bufferstream_test.cpp +++ b/test/bufferstream_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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) // @@ -60,10 +60,10 @@ static int bufferstream_test() bufstream >> str1 >> number1; std_stringstream >> str2 >> number2; if((str1 != str2) || (str1 != str3)){ - assert(0); return 1; + assert(0); return 1; } if((number1 != number2) || (number1 != i)){ - assert(0); return 1; + assert(0); return 1; } } //We shouldn't have reached the end of the buffer reading @@ -90,7 +90,7 @@ static int bufferstream_test() bufstream << "testline: " << i << std::endl; std_stringstream << "testline: " << i << std::endl; } - + //Contents should be different if(std::strcmp(buffer, std_stringstream.str().c_str()) == 0){ return 1; diff --git a/test/cached_adaptive_pool_test.cpp b/test/cached_adaptive_pool_test.cpp index 28a6e97..eb63ec0 100644 --- a/test/cached_adaptive_pool_test.cpp +++ b/test/cached_adaptive_pool_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2004-2012. 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/cached_node_allocator_test.cpp b/test/cached_node_allocator_test.cpp index 35c9de7..8ffa0f0 100644 --- a/test/cached_node_allocator_test.cpp +++ b/test/cached_node_allocator_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2004-2012. 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/check_equal_containers.hpp b/test/check_equal_containers.hpp index b59c0d7..48eb9c2 100644 --- a/test/check_equal_containers.hpp +++ b/test/check_equal_containers.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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) // @@ -15,11 +15,31 @@ #include #include #include +#include namespace boost{ namespace interprocess{ namespace test{ +template< class T1, class T2> +bool CheckEqual( const T1 &t1, const T2 &t2 + , typename boost::container::container_detail::enable_if_c + ::value && + !boost::container::container_detail::is_pair::value + >::type* = 0) +{ return t1 == t2; } + +template< class Pair1, class Pair2> +bool CheckEqual( const Pair1 &pair1, const Pair2 &pair2 + , typename boost::container::container_detail::enable_if_c + ::value && + boost::container::container_detail::is_pair::value + >::type* = 0) +{ + return CheckEqual(pair1.first, pair2.first) && CheckEqual(pair1.second, pair2.second); +} + + //Function to check if both containers are equal template @@ -38,9 +58,7 @@ bool CheckEqualContainers(MyShmCont *shmcont, MyStdCont *stdcont) } std::size_t i = 0; for(; itshm != itshmend; ++itshm, ++itstd, ++i){ - value_type val(*itstd); - const value_type &v = *itshm; - if(v != val) + if(!CheckEqual(*itstd, *itshm)) return false; } return true; diff --git a/test/condition_any_test.cpp b/test/condition_any_test.cpp new file mode 100644 index 0000000..8349fed --- /dev/null +++ b/test/condition_any_test.cpp @@ -0,0 +1,34 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2006-2012. 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 "condition_test_template.hpp" + +using namespace boost::interprocess; + +int main () +{ + if(!test::do_test_condition()) + return 1; + if(!test::do_test_condition()) + return 1; + if(!test::do_test_condition()) + return 1; + + return 0; +} + +#include diff --git a/test/condition_test.cpp b/test/condition_test.cpp index 72ccaf5..089c0a6 100644 --- a/test/condition_test.cpp +++ b/test/condition_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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/condition_test_template.hpp b/test/condition_test_template.hpp index 830ba6f..7f3ac77 100644 --- a/test/condition_test_template.hpp +++ b/test/condition_test_template.hpp @@ -10,7 +10,7 @@ // It is provided "as is" without express or implied warranty. ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -48,7 +48,7 @@ inline boost::xtime delay(int secs, int msecs=0, int nsecs=0) const int NANOSECONDS_PER_MILLISECOND = 1000000; boost::xtime xt; - + #if BOOST_VERSION >= 105100 //TIME_UTC is a macro in C11, breaking change in Boost.Thread int ret = boost::xtime_get(&xt, boost::TIME_UTC_); BOOST_INTERPROCES_CHECK(ret == static_cast(boost::TIME_UTC_));(void)ret; @@ -168,6 +168,8 @@ void do_test_condition_notify_one() condition_test_data data; boost::thread thread(bind_function(&condition_test_thread, &data)); + //Make sure thread is blocked + boost::thread::sleep(delay(1)); { boost::interprocess::scoped_lock lock(data.mutex); @@ -187,16 +189,18 @@ void do_test_condition_notify_all() boost::thread_group threads; condition_test_data data; - for (int i = 0; i < NUMTHREADS; ++i) + for (int i = 0; i < NUMTHREADS; ++i){ threads.create_thread(bind_function(&condition_test_thread, &data)); - + } + //Make sure all threads are blocked + boost::thread::sleep(delay(1)); { boost::interprocess::scoped_lock lock(data.mutex); BOOST_INTERPROCES_CHECK(lock ? true : false); data.notified++; - data.condition.notify_all(); } + data.condition.notify_all(); threads.join_all(); BOOST_INTERPROCES_CHECK(data.awoken == NUMTHREADS); @@ -396,16 +400,16 @@ void do_test_condition_queue_notify_all(void) template bool do_test_condition() { - std::cout << "do_test_condition_notify_one<" << typeid(Condition).name() << "," << typeid(Mutex).name() << std::endl; + std::cout << "do_test_condition_notify_one<" << typeid(Condition).name() << "," << typeid(Mutex).name() << '\n' << std::endl; do_test_condition_notify_one(); - std::cout << "do_test_condition_notify_all<" << typeid(Condition).name() << "," << typeid(Mutex).name() << std::endl; + std::cout << "do_test_condition_notify_all<" << typeid(Condition).name() << "," << typeid(Mutex).name() << '\n' << std::endl; do_test_condition_notify_all(); - std::cout << "do_test_condition_waits<" << typeid(Condition).name() << "," << typeid(Mutex).name() << std::endl; + std::cout << "do_test_condition_waits<" << typeid(Condition).name() << "," << typeid(Mutex).name() << '\n' << std::endl; do_test_condition_waits(); - //std::cout << "do_test_condition_queue_notify_one<" << typeid(Condition).name() << "," << typeid(Mutex).name() << std::endl; - //do_test_condition_queue_notify_one(); - //std::cout << "do_test_condition_queue_notify_all<" << typeid(Condition).name() << "," << typeid(Mutex).name() << std::endl; - //do_test_condition_queue_notify_all(); + std::cout << "do_test_condition_queue_notify_one<" << typeid(Condition).name() << "," << typeid(Mutex).name() << '\n' << std::endl; + do_test_condition_queue_notify_one(); + std::cout << "do_test_condition_queue_notify_all<" << typeid(Condition).name() << "," << typeid(Mutex).name() << '\n' << std::endl; + do_test_condition_queue_notify_all(); return true; } diff --git a/test/data_test.cpp b/test/data_test.cpp index fee925f..717c84c 100644 --- a/test/data_test.cpp +++ b/test/data_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2004-2012. 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/deque_test.cpp b/test/deque_test.cpp index 87da1fd..4f5173a 100644 --- a/test/deque_test.cpp +++ b/test/deque_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2004-2012. 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) // @@ -57,7 +57,7 @@ bool copyable_only(V1 *shmdeque, V2 *stddeque, ipcdetail::true_type) typedef typename V1::value_type IntType; std::size_t size = shmdeque->size(); stddeque->insert(stddeque->end(), 50, 1); - shmdeque->insert(shmdeque->end(), 50, 1); + shmdeque->insert(shmdeque->end(), 50, IntType(1)); if(!test::CheckEqualContainers(shmdeque, stddeque)) return false; { IntType move_me(1); @@ -261,11 +261,11 @@ bool do_test() shmdeque->resize(100); stddeque->resize(100); - if(!test::CheckEqualContainers(shmdeque, stddeque)) return 1; + if(!test::CheckEqualContainers(shmdeque, stddeque)) return 1; shmdeque->resize(200); stddeque->resize(200); - if(!test::CheckEqualContainers(shmdeque, stddeque)) return 1; + if(!test::CheckEqualContainers(shmdeque, stddeque)) return 1; segment.template destroy("MyShmDeque"); delete stddeque; @@ -278,7 +278,7 @@ bool do_test() std::cout << ex.what() << std::endl; return false; }*/ - + std::cout << std::endl << "Test OK!" << std::endl; }/* catch(...){ diff --git a/test/dummy_test_allocator.hpp b/test/dummy_test_allocator.hpp index f195938..5672ff2 100644 --- a/test/dummy_test_allocator.hpp +++ b/test/dummy_test_allocator.hpp @@ -1,6 +1,6 @@ /////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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/emplace_test.hpp b/test/emplace_test.hpp index 93408ce..1ba168a 100644 --- a/test/emplace_test.hpp +++ b/test/emplace_test.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2008. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2008-2012. 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/enable_shared_from_this_test.cpp b/test/enable_shared_from_this_test.cpp index 81734b0..2b90adc 100644 --- a/test/enable_shared_from_this_test.cpp +++ b/test/enable_shared_from_this_test.cpp @@ -3,7 +3,7 @@ // // This file is the adaptation of shared_from_this_test.cpp from smart_ptr library // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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 5d53959..c48f07a 100644 --- a/test/expand_bwd_test_allocator.hpp +++ b/test/expand_bwd_test_allocator.hpp @@ -1,6 +1,6 @@ /////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -109,7 +109,7 @@ class expand_bwd_test_allocator { return m_size; } friend void swap(self_t &alloc1, self_t &alloc2) - { + { ipcdetail::do_swap(alloc1.mp_buffer, alloc2.mp_buffer); ipcdetail::do_swap(alloc1.m_size, alloc2.m_size); ipcdetail::do_swap(alloc1.m_offset, alloc2.m_offset); @@ -126,7 +126,7 @@ class expand_bwd_test_allocator (void)preferred_size; (void)reuse; (void)command; //This allocator only expands backwards! assert(m_allocations == 0 || (command & boost::interprocess::expand_bwd)); - + received_size = limit_size; if(m_allocations == 0){ diff --git a/test/expand_bwd_test_template.hpp b/test/expand_bwd_test_template.hpp index 05b79a6..68b7de6 100644 --- a/test/expand_bwd_test_template.hpp +++ b/test/expand_bwd_test_template.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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/file_lock_test.cpp b/test/file_lock_test.cpp index f9ed7e5..d8c48ab 100644 --- a/test/file_lock_test.cpp +++ b/test/file_lock_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2004-2012. 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/file_mapping_test.cpp b/test/file_mapping_test.cpp index 3099a87..c9dcf07 100644 --- a/test/file_mapping_test.cpp +++ b/test/file_mapping_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2004-2012. 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) // @@ -62,7 +62,7 @@ int main () ,FileSize - FileSize/2 ); - //Fill two regions with a pattern + //Fill two regions with a pattern unsigned char *filler = static_cast(region.get_address()); for(std::size_t i = 0 ;i < FileSize/2 @@ -92,7 +92,7 @@ int main () //Create a memory buffer std::auto_ptr memory (new unsigned char [FileSize/2 +1]); - + //Fill buffer file.read(static_cast(static_cast(memory.get())) , FileSize/2); diff --git a/test/flat_map_index_allocation_test.cpp b/test/flat_map_index_allocation_test.cpp index a021455..41476ab 100644 --- a/test/flat_map_index_allocation_test.cpp +++ b/test/flat_map_index_allocation_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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/flat_tree_test.cpp b/test/flat_tree_test.cpp index 5c6a066..f61fb56 100644 --- a/test/flat_tree_test.cpp +++ b/test/flat_tree_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2004-2012. 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) // @@ -23,11 +23,11 @@ #include "emplace_test.hpp" ///////////////////////////////////////////////////////////////// -// -// This example repeats the same operations with std::set and -// shmem_set using the node allocator -// and compares the values of both containers -// +// +// This example repeats the same operations with std::set and +// shmem_set using the node allocator +// and compares the values of both containers +// ///////////////////////////////////////////////////////////////// using namespace boost::interprocess; diff --git a/test/get_process_id_name.hpp b/test/get_process_id_name.hpp index 4e49525..f79384a 100644 --- a/test/get_process_id_name.hpp +++ b/test/get_process_id_name.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2004-2012. 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/heap_allocator_v1.hpp b/test/heap_allocator_v1.hpp index d5b8bac..9ec82bb 100644 --- a/test/heap_allocator_v1.hpp +++ b/test/heap_allocator_v1.hpp @@ -1,6 +1,6 @@ /////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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) // @@ -83,7 +83,7 @@ class heap_allocator_v1 //!Obtains an heap_allocator_v1 of other type template struct rebind - { + { typedef heap_allocator_v1 other; }; diff --git a/test/intermodule_singleton_test.cpp b/test/intermodule_singleton_test.cpp index b15df84..15d6105 100644 --- a/test/intermodule_singleton_test.cpp +++ b/test/intermodule_singleton_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2004-2012. 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) // @@ -87,7 +87,7 @@ int intermodule_singleton_test() return 1; } - return 0; + return 0; } //A class simulating a logger @@ -249,7 +249,7 @@ int phoenix_singleton_test() //LoggerSingleton. //After that LoggerSingleton will be destroyed and //lastly LogPhoenixTester will be destroyed checking - //LoggerSingleton was correctly destroyed. + //LoggerSingleton was correctly destroyed. return 0; } diff --git a/test/intersegment_ptr_test.cpp b/test/intersegment_ptr_test.cpp index 709acd4..d3a91ca 100644 --- a/test/intersegment_ptr_test.cpp +++ b/test/intersegment_ptr_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2007-2012. 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) // @@ -48,7 +48,7 @@ bool test_types_and_convertions() pcint_t pcint(0); pvint_t pvint(0); pcvint_t pcvint(0); - + pint = &dummy_int; pcint = &dummy_int; pvint = &dummy_int; @@ -75,7 +75,7 @@ bool test_arithmetic() typedef intersegment_ptr pint_t; const int NumValues = 5; int values[NumValues]; - + //Initialize p pint_t p = values; if(p.get() != values) @@ -376,7 +376,7 @@ bool test_multi_segment_shared_memory() shared_memory_object::remove("kk0"); managed_multi_shared_memory mshm(create_only, "kk", 4096); } - + shared_memory_object::remove("kk0"); return true; } diff --git a/test/intrusive_ptr_test.cpp b/test/intrusive_ptr_test.cpp index fc8db0e..d3fb0a1 100644 --- a/test/intrusive_ptr_test.cpp +++ b/test/intrusive_ptr_test.cpp @@ -1,7 +1,7 @@ ////////////////////////////////////////////////////////////////////////////// // // (C) Copyright Peter Dimov 2002-2005. -// (C) Copyright Ion Gaztanaga 2006. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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/iset_index_allocation_test.cpp b/test/iset_index_allocation_test.cpp index 9e25313..42d03ff 100644 --- a/test/iset_index_allocation_test.cpp +++ b/test/iset_index_allocation_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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/iunordered_set_index_allocation_test.cpp b/test/iunordered_set_index_allocation_test.cpp index 98ab47d..5e8e966 100644 --- a/test/iunordered_set_index_allocation_test.cpp +++ b/test/iunordered_set_index_allocation_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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/list_test.cpp b/test/list_test.cpp index 434f1c7..4ecf55a 100644 --- a/test/list_test.cpp +++ b/test/list_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2004-2012. 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/list_test.hpp b/test/list_test.hpp index 4a9f44b..2e54783 100644 --- a/test/list_test.hpp +++ b/test/list_test.hpp @@ -1,6 +1,6 @@ //////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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) // @@ -219,7 +219,7 @@ int list_test (bool copied_allocators_equal = true) shmlist->splice(shmlist->begin(), othershmlist); stdlist->splice(stdlist->begin(), otherstdlist); if(!CheckEqualContainers(shmlist, stdlist)) - return 1; + return 1; } listsize = (int)shmlist->size(); diff --git a/test/managed_mapped_file_test.cpp b/test/managed_mapped_file_test.cpp index 0936995..90f0f00 100644 --- a/test/managed_mapped_file_test.cpp +++ b/test/managed_mapped_file_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2004-2012. 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) // @@ -83,7 +83,7 @@ int main () //Construct a vector in the memory-mapped file mfile_vect = mfile.construct ("MyVector") (myallocator); - + //Flush cached data from memory-mapped file to disk mfile.flush(); } diff --git a/test/managed_shared_memory_test.cpp b/test/managed_shared_memory_test.cpp index e589d93..df85082 100644 --- a/test/managed_shared_memory_test.cpp +++ b/test/managed_shared_memory_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2004-2012. 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/managed_windows_shared_memory_test.cpp b/test/managed_windows_shared_memory_test.cpp index e5cefcb..aa01119 100644 --- a/test/managed_windows_shared_memory_test.cpp +++ b/test/managed_windows_shared_memory_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2004-2012. 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) // @@ -123,7 +123,7 @@ int main () if(!shmem_vect) 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) diff --git a/test/managed_xsi_shared_memory_test.cpp b/test/managed_xsi_shared_memory_test.cpp index 03e695e..1492596 100644 --- a/test/managed_xsi_shared_memory_test.cpp +++ b/test/managed_xsi_shared_memory_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2008-2012. 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/map_index_allocation_test.cpp b/test/map_index_allocation_test.cpp index bedb6ad..5202a24 100644 --- a/test/map_index_allocation_test.cpp +++ b/test/map_index_allocation_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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/map_test.hpp b/test/map_test.hpp index cebe940..d116667 100644 --- a/test/map_test.hpp +++ b/test/map_test.hpp @@ -1,6 +1,6 @@ //////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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) // @@ -67,7 +67,7 @@ int map_test () MyStdMultiMap *stdmultimap = new MyStdMultiMap; - //Test construction from a range + //Test construction from a range { //This is really nasty, but we have no other simple choice IntPairType aux_vect[50]; @@ -555,7 +555,7 @@ int map_test_copyable () stdmapcopy = *stdmap; shmmmapcopy = *shmmultimap; stdmmapcopy = *stdmultimap; - + if(!CheckEqualContainers(&shmmapcopy, &stdmapcopy)) return 1; if(!CheckEqualContainers(&shmmmapcopy, &stdmmapcopy)) diff --git a/test/mapped_file_test.cpp b/test/mapped_file_test.cpp index 1c89e69..ae19b4f 100644 --- a/test/mapped_file_test.cpp +++ b/test/mapped_file_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2004-2012. 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) // @@ -37,7 +37,7 @@ struct file_destroyer ~file_destroyer() { //The last destructor will destroy the file - file_mapping::remove(get_filename().c_str()); + file_mapping::remove(get_filename().c_str()); } }; @@ -72,7 +72,7 @@ int main () test::test_named_creation(); //Create and get name, size and address - { + { mapped_file file1(create_only, get_filename().c_str(), FileSize, read_write, 0, permissions()); //Overwrite all memory diff --git a/test/memory_algorithm_test.cpp b/test/memory_algorithm_test.cpp index 05db1e4..8ed6dec 100644 --- a/test/memory_algorithm_test.cpp +++ b/test/memory_algorithm_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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/memory_algorithm_test_template.hpp b/test/memory_algorithm_test_template.hpp index 2350053..5892e00 100644 --- a/test/memory_algorithm_test_template.hpp +++ b/test/memory_algorithm_test_template.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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) // @@ -118,7 +118,7 @@ bool test_allocation_shrink(Allocator &a) std::memset(buffers[i], 0, a.size(buffers[i])); } } - + //Deallocate it in non sequential order for(int j = 0, max = (int)buffers.size() ;j < max @@ -170,7 +170,7 @@ bool test_allocation_expand(Allocator &a) preferred_size = min_size*2; } } - + //Deallocate it in non sequential order for(int j = 0, max = (int)buffers.size() ;j < max @@ -243,7 +243,7 @@ bool test_allocation_shrink_and_expand(Allocator &a) return false; } } - + //Deallocate it in non sequential order for(int j = 0, max = (int)buffers.size() ;j < max @@ -310,7 +310,7 @@ bool test_allocation_deallocation_expand(Allocator &a) } } } - + //Now erase null values from the vector buffers.erase( std::remove(buffers.begin(), buffers.end(), static_cast(0)) , buffers.end()); @@ -349,7 +349,7 @@ bool test_allocation_with_reuse(Allocator &a) std::memset(ptr, 0, size); buffers.push_back(ptr); } - + //Now deallocate all except the latest //Now try to expand to the double of the sizeof_object for(int i = 0, max = (int)buffers.size() - 1 @@ -381,7 +381,7 @@ bool test_allocation_with_reuse(Allocator &a) } //There is only a single block so deallocate it a.deallocate(ptr); - + if(!a.all_memory_deallocated() || !a.check_sanity()) return false; } @@ -405,7 +405,7 @@ bool test_aligned_allocation(Allocator &a) continue_loop = false; break; } - + if(((std::size_t)ptr & (j - 1)) != 0) return false; a.deallocate(ptr); @@ -441,7 +441,7 @@ bool test_continuous_aligned_allocation(Allocator &a) else{ any_allocated = true; } - + if(((std::size_t)ptr & (j - 1)) != 0) return false; } @@ -679,8 +679,7 @@ bool test_many_equal_allocation(Allocator &a) typename multiallocation_chain::size_type n = chain.size(); while(!chain.empty()){ - buffers.push_back(ipcdetail::to_raw_pointer(chain.front())); - chain.pop_front(); + buffers.push_back(ipcdetail::to_raw_pointer(chain.pop_front())); } if(n != std::size_t((i+1)*2)) return false; @@ -788,8 +787,7 @@ bool test_many_different_allocation(Allocator &a) break; typename multiallocation_chain::size_type n = chain.size(); while(!chain.empty()){ - buffers.push_back(ipcdetail::to_raw_pointer(chain.front())); - chain.pop_front(); + buffers.push_back(ipcdetail::to_raw_pointer(chain.pop_front())); } if(n != ArraySize) return false; diff --git a/test/message_queue_test.cpp b/test/message_queue_test.cpp index 9368f58..f9e7b79 100644 --- a/test/message_queue_test.cpp +++ b/test/message_queue_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2004-2012. 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) // @@ -48,6 +48,8 @@ bool test_priority_order() message_queue::size_type recvd = 0; unsigned int priority = 0; std::size_t tstamp; + unsigned int priority_prev; + std::size_t tstamp_prev; //We will send 100 message with priority 0-9 //The message will contain the timestamp of the message @@ -56,8 +58,31 @@ bool test_priority_order() mq1.send(&tstamp, sizeof(tstamp), (unsigned int)(i%10)); } - unsigned int priority_prev = (std::numeric_limits::max)(); - std::size_t tstamp_prev = 0; + priority_prev = (std::numeric_limits::max)(); + 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; + } + + //Now retry it with different priority order + for(std::size_t i = 0; i < 100; ++i){ + tstamp = i; + mq1.send(&tstamp, sizeof(tstamp), (unsigned int)(9 - i%10)); + } + + priority_prev = (std::numeric_limits::max)(); + tstamp_prev = 0; //Receive all messages and test those are ordered //by priority and by FIFO in the same priority @@ -83,7 +108,7 @@ bool test_priority_order() //another buffer and checks it against the original data-base bool test_serialize_db() { - //Typedef data to create a Interprocess map + //Typedef data to create a Interprocess map typedef std::pair MyPair; typedef std::less MyLess; typedef node_allocator @@ -157,7 +182,7 @@ bool test_serialize_db() 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); @@ -188,7 +213,7 @@ bool test_serialize_db() return false; } } - + //Destroy maps from db-s db_origin.destroy_ptr(map1); db_destiny.destroy_ptr(map2); diff --git a/test/movable_int.hpp b/test/movable_int.hpp index 528600e..3f26787 100644 --- a/test/movable_int.hpp +++ b/test/movable_int.hpp @@ -1,6 +1,6 @@ /////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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) // @@ -19,12 +19,21 @@ namespace boost { namespace interprocess { namespace test { +template +struct is_copyable; + +template<> +struct is_copyable +{ + static const bool value = true; +}; + + class movable_int { BOOST_MOVABLE_BUT_NOT_COPYABLE(movable_int) public: - movable_int() : m_int(0) {} @@ -64,6 +73,12 @@ class movable_int int get_int() const { return m_int; } + friend bool operator==(const movable_int &l, int r) + { return l.get_int() == r; } + + friend bool operator==(int l, const movable_int &r) + { return l == r.get_int(); } + private: int m_int; }; @@ -77,11 +92,18 @@ std::basic_ostream & operator<< return os; } + +template<> +struct is_copyable +{ + static const bool value = false; +}; + class movable_and_copyable_int { BOOST_COPYABLE_AND_MOVABLE(movable_and_copyable_int) - public: + public: movable_and_copyable_int() : m_int(0) {} @@ -94,13 +116,13 @@ class movable_and_copyable_int : m_int(mmi.m_int) {} - movable_and_copyable_int &operator= (BOOST_COPY_ASSIGN_REF(movable_and_copyable_int) mi) - { this->m_int = mi.m_int; return *this; } - movable_and_copyable_int(BOOST_RV_REF(movable_and_copyable_int) mmi) : m_int(mmi.m_int) { mmi.m_int = 0; } + movable_and_copyable_int &operator= (BOOST_COPY_ASSIGN_REF(movable_and_copyable_int) mi) + { this->m_int = mi.m_int; return *this; } + movable_and_copyable_int & operator= (BOOST_RV_REF(movable_and_copyable_int) mmi) { this->m_int = mmi.m_int; mmi.m_int = 0; return *this; } @@ -128,6 +150,12 @@ class movable_and_copyable_int int get_int() const { return m_int; } + friend bool operator==(const movable_and_copyable_int &l, int r) + { return l.get_int() == r; } + + friend bool operator==(int l, const movable_and_copyable_int &r) + { return l == r.get_int(); } + private: int m_int; }; @@ -141,6 +169,12 @@ std::basic_ostream & operator<< return os; } +template<> +struct is_copyable +{ + static const bool value = true; +}; + class copyable_int { public: @@ -156,9 +190,6 @@ class copyable_int : m_int(mmi.m_int) {} - copyable_int & operator= (const copyable_int &mi) - { this->m_int = mi.m_int; return *this; } - copyable_int & operator= (int i) { this->m_int = i; return *this; } @@ -183,10 +214,31 @@ class copyable_int int get_int() const { return m_int; } + friend bool operator==(const copyable_int &l, int r) + { return l.get_int() == r; } + + friend bool operator==(int l, const copyable_int &r) + { return l == r.get_int(); } + private: int m_int; }; +template +std::basic_ostream & operator<< + (std::basic_ostream & os, copyable_int const & p) + +{ + os << p.get_int(); + return os; +} + +template<> +struct is_copyable +{ + static const bool value = true; +}; + class non_copymovable_int { non_copymovable_int(const non_copymovable_int& mmi); @@ -222,21 +274,16 @@ class non_copymovable_int int get_int() const { return m_int; } + friend bool operator==(const non_copymovable_int &l, int r) + { return l.get_int() == r; } + + friend bool operator==(int l, const non_copymovable_int &r) + { return l == r.get_int(); } + private: int m_int; }; -template -std::basic_ostream & operator<< - (std::basic_ostream & os, copyable_int const & p) - -{ - os << p.get_int(); - return os; -} - - - } //namespace test { } //namespace interprocess { } //namespace boost { diff --git a/test/multi_index_test.cpp b/test/multi_index_test.cpp index cebdc78..7c77154 100644 --- a/test/multi_index_test.cpp +++ b/test/multi_index_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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/mutex_test.cpp b/test/mutex_test.cpp index 185a094..e3bd482 100644 --- a/test/mutex_test.cpp +++ b/test/mutex_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2004-2012. 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/mutex_test_template.hpp b/test/mutex_test_template.hpp index 6bba872..c41abe3 100644 --- a/test/mutex_test_template.hpp +++ b/test/mutex_test_template.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2004-2012. 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) // @@ -232,7 +232,7 @@ template void test_mutex_lock() { shared_val = 0; - + M mtx; data d1(1); @@ -260,7 +260,7 @@ template void test_mutex_lock_timeout() { shared_val = 0; - + M mtx; int wait_time_s = BOOST_INTERPROCESS_TIMEOUT_WHEN_LOCKING_DURATION_MS / 1000; diff --git a/test/mutex_timeout_test.cpp b/test/mutex_timeout_test.cpp index ea03f35..7dc4df5 100644 --- a/test/mutex_timeout_test.cpp +++ b/test/mutex_timeout_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2004-2012. 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/named_allocation_test_template.hpp b/test/named_allocation_test_template.hpp index a821b1a..439e787 100644 --- a/test/named_allocation_test_template.hpp +++ b/test/named_allocation_test_template.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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/named_condition_any_test.cpp b/test/named_condition_any_test.cpp new file mode 100644 index 0000000..500cb18 --- /dev/null +++ b/test/named_condition_any_test.cpp @@ -0,0 +1,189 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2004-2012. 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 "condition_test_template.hpp" +#include "named_creation_template.hpp" +#include +#include +#include "get_process_id_name.hpp" + +using namespace boost::interprocess; + +struct condition_deleter +{ + std::string name; + + ~condition_deleter() + { + if(name.empty()) + named_condition_any::remove(test::add_to_process_id_name("named_condition_any")); + else + named_condition_any::remove(name.c_str()); + } +}; + +inline std::string num_to_string(int n) +{ std::stringstream s; s << n; return s.str(); } + +//This wrapper is necessary to have a default constructor +//in generic mutex_test_template functions +class named_condition_any_test_wrapper + : public condition_deleter, public named_condition_any +{ + public: + + named_condition_any_test_wrapper() + : named_condition_any(open_or_create, + (test::add_to_process_id_name("test_cond") + num_to_string(count)).c_str()) + { + condition_deleter::name += test::add_to_process_id_name("test_cond"); + condition_deleter::name += num_to_string(count); + ++count; + } + + ~named_condition_any_test_wrapper() + { --count; } + + + template + void wait(L& lock) + { + ipcdetail::internal_mutex_lock internal_lock(lock); + named_condition_any::wait(internal_lock); + } + + template + void wait(L& lock, Pr pred) + { + ipcdetail::internal_mutex_lock internal_lock(lock); + named_condition_any::wait(internal_lock, pred); + } + + template + bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time) + { + ipcdetail::internal_mutex_lock internal_lock(lock); + return named_condition_any::timed_wait(internal_lock, abs_time); + } + + template + bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred) + { + ipcdetail::internal_mutex_lock internal_lock(lock); + return named_condition_any::timed_wait(internal_lock, abs_time, pred); + } + + static int count; +}; + +int named_condition_any_test_wrapper::count = 0; + +//This wrapper is necessary to have a common constructor +//in generic named_creation_template functions +class named_condition_any_creation_test_wrapper + : public condition_deleter, public named_condition_any +{ + public: + named_condition_any_creation_test_wrapper(create_only_t) + : named_condition_any(create_only, test::add_to_process_id_name("named_condition_any")) + { ++count_; } + + named_condition_any_creation_test_wrapper(open_only_t) + : named_condition_any(open_only, test::add_to_process_id_name("named_condition_any")) + { ++count_; } + + named_condition_any_creation_test_wrapper(open_or_create_t) + : named_condition_any(open_or_create, test::add_to_process_id_name("named_condition_any")) + { ++count_; } + + ~named_condition_any_creation_test_wrapper() { + if(--count_){ + ipcdetail::interprocess_tester:: + dont_close_on_destruction(static_cast(*this)); + } + } + static int count_; +}; + +int named_condition_any_creation_test_wrapper::count_ = 0; + +struct mutex_deleter +{ + std::string name; + + ~mutex_deleter() + { + if(name.empty()) + named_mutex::remove(test::add_to_process_id_name("named_mutex")); + else + named_mutex::remove(name.c_str()); + } +}; + +//This wrapper is necessary to have a default constructor +//in generic mutex_test_template functions +class named_mutex_test_wrapper + : public mutex_deleter, public named_mutex +{ + public: + named_mutex_test_wrapper() + : named_mutex(open_or_create, + (test::add_to_process_id_name("test_mutex") + num_to_string(count)).c_str()) + { + mutex_deleter::name += test::add_to_process_id_name("test_mutex"); + mutex_deleter::name += num_to_string(count); + ++count; + } + + typedef named_mutex internal_mutex_type; + + internal_mutex_type &internal_mutex() + { return *this; } + + ~named_mutex_test_wrapper() + { --count; } + + static int count; +}; + +int named_mutex_test_wrapper::count = 0; + +int main () +{ + try{ + //Remove previous mutexes and conditions + named_mutex::remove(test::add_to_process_id_name("test_mutex0")); + named_condition_any::remove(test::add_to_process_id_name("test_cond0")); + named_condition_any::remove(test::add_to_process_id_name("test_cond1")); + named_condition_any::remove(test::add_to_process_id_name("named_condition_any")); + named_mutex::remove(test::add_to_process_id_name("named_mutex")); + + test::test_named_creation(); + test::do_test_condition(); + } + catch(std::exception &ex){ + std::cout << ex.what() << std::endl; + return 1; + } + named_mutex::remove(test::add_to_process_id_name("test_mutex0")); + named_condition_any::remove(test::add_to_process_id_name("test_cond0")); + named_condition_any::remove(test::add_to_process_id_name("test_cond1")); + named_condition_any::remove(test::add_to_process_id_name("named_condition_any")); + named_mutex::remove(test::add_to_process_id_name("named_mutex")); + return 0; +} + +#include diff --git a/test/named_condition_test.cpp b/test/named_condition_test.cpp index b7b23b2..6aa9c78 100644 --- a/test/named_condition_test.cpp +++ b/test/named_condition_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2004-2012. 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) // @@ -12,6 +12,7 @@ #include #include #include +#include #include "condition_test_template.hpp" #include "named_creation_template.hpp" #include @@ -25,7 +26,7 @@ struct condition_deleter std::string name; ~condition_deleter() - { + { if(name.empty()) named_condition::remove(test::add_to_process_id_name("named_condition")); else @@ -56,76 +57,32 @@ class named_condition_test_wrapper { --count; } - template - class lock_wrapper - { - typedef void (lock_wrapper::*unspecified_bool_type)(); - public: - - typedef named_mutex mutex_type; - - lock_wrapper(Lock &l) - : l_(l) - {} - - mutex_type* mutex() const - { return l_.mutex(); } - - void lock() { l_.lock(); } - - void unlock() { l_.unlock(); } - - operator unspecified_bool_type() const - { return l_ ? &lock_wrapper::lock : 0; } - - private: - Lock &l_; - }; -/* - template - class lock_wrapper - { - public: - - typedef named_mutex mutex_type; - - lock_wrapper(Lock &l) - : l_(l) - {} - - mutex_type* mutex() const - { return l_.mutex(); } - - private: - Lock &l_; - }; -*/ template void wait(L& lock) { - lock_wrapper newlock(lock); - named_condition::wait(newlock); + ipcdetail::internal_mutex_lock internal_lock(lock); + named_condition::wait(internal_lock); } template void wait(L& lock, Pr pred) { - lock_wrapper newlock(lock); - named_condition::wait(newlock, pred); + ipcdetail::internal_mutex_lock internal_lock(lock); + named_condition::wait(internal_lock, pred); } template bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time) { - lock_wrapper newlock(lock); - return named_condition::timed_wait(newlock, abs_time); + ipcdetail::internal_mutex_lock internal_lock(lock); + return named_condition::timed_wait(internal_lock, abs_time); } template bool timed_wait(L& lock, const boost::posix_time::ptime &abs_time, Pr pred) { - lock_wrapper newlock(lock); - return named_condition::timed_wait(newlock, abs_time, pred); + ipcdetail::internal_mutex_lock internal_lock(lock); + return named_condition::timed_wait(internal_lock, abs_time, pred); } static int count; @@ -167,7 +124,7 @@ struct mutex_deleter std::string name; ~mutex_deleter() - { + { if(name.empty()) named_mutex::remove(test::add_to_process_id_name("named_mutex")); else @@ -190,6 +147,11 @@ class named_mutex_test_wrapper ++count; } + typedef named_mutex internal_mutex_type; + + internal_mutex_type &internal_mutex() + { return *this; } + ~named_mutex_test_wrapper() { --count; } diff --git a/test/named_construct_test.cpp b/test/named_construct_test.cpp index 81a0a6a..acdd9b7 100644 --- a/test/named_construct_test.cpp +++ b/test/named_construct_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2008-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2008-2012. 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/named_creation_template.hpp b/test/named_creation_template.hpp index e24cda9..ee34aa6 100644 --- a/test/named_creation_template.hpp +++ b/test/named_creation_template.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2004-2012. 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) // @@ -23,7 +23,7 @@ namespace boost { namespace interprocess { namespace test { template inline void create_then_open_then_open_or_create() -{ +{ try{ //Create it and open it twice NamedResource nresource1(create_only); @@ -38,7 +38,7 @@ inline void create_then_open_then_open_or_create() template inline void open_or_create_then_create() -{ +{ //Create it with open_or_create and try to create it twice NamedResource nresource1(open_or_create); try{ @@ -51,7 +51,7 @@ inline void open_or_create_then_create() template inline void dont_create_and_open() -{ +{ //Try to open it without creating try{ NamedResource nresource1(open_only); diff --git a/test/named_mutex_test.cpp b/test/named_mutex_test.cpp index f818c31..11c7f1c 100644 --- a/test/named_mutex_test.cpp +++ b/test/named_mutex_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2004-2012. 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/named_recursive_mutex_test.cpp b/test/named_recursive_mutex_test.cpp index 345b3cb..376c1e3 100644 --- a/test/named_recursive_mutex_test.cpp +++ b/test/named_recursive_mutex_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2004-2012. 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/named_semaphore_test.cpp b/test/named_semaphore_test.cpp index 4f6cd5a..c5dc02b 100644 --- a/test/named_semaphore_test.cpp +++ b/test/named_semaphore_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2004-2012. 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/named_sharable_mutex_test.cpp b/test/named_sharable_mutex_test.cpp new file mode 100644 index 0000000..9721ab0 --- /dev/null +++ b/test/named_sharable_mutex_test.cpp @@ -0,0 +1,103 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2004-2012. 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 "mutex_test_template.hpp" +#include "sharable_mutex_test_template.hpp" +#include "named_creation_template.hpp" +#include +#include +#include "get_process_id_name.hpp" + +using namespace boost::interprocess; + +struct mutex_deleter +{ + ~mutex_deleter() + { named_sharable_mutex::remove(test::get_process_id_name()); } +}; + +//This wrapper is necessary to have a default constructor +//in generic mutex_test_template functions +class named_sharable_mutex_lock_test_wrapper + : public named_sharable_mutex +{ + public: + named_sharable_mutex_lock_test_wrapper() + : named_sharable_mutex(open_or_create, test::get_process_id_name()) + { ++count_; } + + ~named_sharable_mutex_lock_test_wrapper() + { + if(--count_){ + ipcdetail::interprocess_tester:: + dont_close_on_destruction(static_cast(*this)); + } + } + + static int count_; +}; + +int named_sharable_mutex_lock_test_wrapper::count_ = 0; + + +//This wrapper is necessary to have a common constructor +//in generic named_creation_template functions +class named_sharable_mutex_creation_test_wrapper + : public mutex_deleter, public named_sharable_mutex +{ + public: + named_sharable_mutex_creation_test_wrapper + (create_only_t) + : named_sharable_mutex(create_only, test::get_process_id_name()) + { ++count_; } + + named_sharable_mutex_creation_test_wrapper + (open_only_t) + : named_sharable_mutex(open_only, test::get_process_id_name()) + { ++count_; } + + named_sharable_mutex_creation_test_wrapper + (open_or_create_t) + : named_sharable_mutex(open_or_create, test::get_process_id_name()) + { ++count_; } + + ~named_sharable_mutex_creation_test_wrapper() + { + if(--count_){ + ipcdetail::interprocess_tester:: + dont_close_on_destruction(static_cast(*this)); + } + } + + static int count_; +}; + +int named_sharable_mutex_creation_test_wrapper::count_ = 0; + +int main () +{ + try{ + named_sharable_mutex::remove(test::get_process_id_name()); + test::test_named_creation< test::named_sync_creation_test_wrapper >(); + test::test_all_lock< test::named_sync_wrapper >(); + test::test_all_mutex >(); + test::test_all_sharable_mutex >(); + } + catch(std::exception &ex){ + named_sharable_mutex::remove(test::get_process_id_name()); + std::cout << ex.what() << std::endl; + return 1; + } + named_sharable_mutex::remove(test::get_process_id_name()); + return 0; +} + +#include diff --git a/test/named_upgradable_mutex_test.cpp b/test/named_upgradable_mutex_test.cpp index 564294b..c0d2bcd 100644 --- a/test/named_upgradable_mutex_test.cpp +++ b/test/named_upgradable_mutex_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2004-2012. 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/node_allocator_test.cpp b/test/node_allocator_test.cpp index ba6052f..4ff7097 100644 --- a/test/node_allocator_test.cpp +++ b/test/node_allocator_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2004-2012. 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/node_pool_test.cpp b/test/node_pool_test.cpp index 71c8142..149bd7f 100644 --- a/test/node_pool_test.cpp +++ b/test/node_pool_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2007-2012. 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/node_pool_test.hpp b/test/node_pool_test.hpp index ec4cae7..76a87d3 100644 --- a/test/node_pool_test.hpp +++ b/test/node_pool_test.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2007-2012. 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) // @@ -49,7 +49,7 @@ bool test_node_pool::allocate_then_deallocate(NodePool &pool) if((pool.get_real_num_node() - 1) != pool.num_free_nodes()){ return false; } - + //Now deallocate all and check again for(std::size_t i = 0; i < num_alloc; ++i){ pool.deallocate_node(nodes[i]); @@ -59,7 +59,7 @@ bool test_node_pool::allocate_then_deallocate(NodePool &pool) if(4*pool.get_real_num_node() != pool.num_free_nodes()){ return false; } - + pool.deallocate_free_blocks(); if(0 != pool.num_free_nodes()){ @@ -92,7 +92,7 @@ bool test_node_pool::deallocate_free_blocks(NodePool &pool) if(0 != pool.num_free_nodes()){ return false; } - + //Now deallocate one of each block per iteration for(std::size_t node_i = 0; node_i < nodes_per_block; ++node_i){ //Deallocate a node per block @@ -104,7 +104,7 @@ bool test_node_pool::deallocate_free_blocks(NodePool &pool) if(max_blocks*(node_i+1) != pool.num_free_nodes()){ return false; } - + //Now try to deallocate free blocks pool.deallocate_free_blocks(); diff --git a/test/null_index_test.cpp b/test/null_index_test.cpp index 7da718e..e0f2340 100644 --- a/test/null_index_test.cpp +++ b/test/null_index_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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/offset_ptr_test.cpp b/test/offset_ptr_test.cpp index 929dead..3ec3e65 100644 --- a/test/offset_ptr_test.cpp +++ b/test/offset_ptr_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2007-2012. 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) // @@ -60,7 +60,7 @@ bool test_types_and_conversions() pcint_t pcint(0); pvint_t pvint(0); pcvint_t pcvint(0); - + pint = &dummy_int; pcint = &dummy_int; pvint = &dummy_int; @@ -153,7 +153,7 @@ bool test_arithmetic() typedef offset_ptr pint_t; const int NumValues = 5; int values[NumValues]; - + //Initialize p pint_t p = values; if(p.get() != values) diff --git a/test/print_container.hpp b/test/print_container.hpp index 0aaffe9..eefc6ba 100644 --- a/test/print_container.hpp +++ b/test/print_container.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2004-2012. 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) // @@ -49,7 +49,7 @@ void PrintContainers(MyShmCont *shmcont, MyStdCont *stdcont) std::cout << *itshm << std::endl; } std::cout << "MyStdCont" << std::endl; - + for(; itstd != itstdend; ++itstd){ std::cout << *itstd << std::endl; } diff --git a/test/private_adaptive_pool_test.cpp b/test/private_adaptive_pool_test.cpp index c93ddfb..55868a0 100644 --- a/test/private_adaptive_pool_test.cpp +++ b/test/private_adaptive_pool_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2004-2012. 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/private_node_allocator_test.cpp b/test/private_node_allocator_test.cpp index 5abd662..4690f83 100644 --- a/test/private_node_allocator_test.cpp +++ b/test/private_node_allocator_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2004-2012. 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/recursive_mutex_test.cpp b/test/recursive_mutex_test.cpp index eb58f3e..8bec034 100644 --- a/test/recursive_mutex_test.cpp +++ b/test/recursive_mutex_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2004-2012. 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/robust_emulation_test.cpp b/test/robust_emulation_test.cpp index 3e2d9e9..98a64e0 100644 --- a/test/robust_emulation_test.cpp +++ b/test/robust_emulation_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2010-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2010-2012. 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/robust_mutex_test.hpp b/test/robust_mutex_test.hpp index e189984..513dba9 100644 --- a/test/robust_mutex_test.hpp +++ b/test/robust_mutex_test.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2010-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2010-2012. 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) // @@ -69,7 +69,7 @@ int robust_mutex_test(int argc, char *argv[]) while(!*go_ahead){ ipcdetail::thread_yield(); } - + std::cout << "... recovering mutex[0]" << std::endl; //First try to recover lock[0], put into consistent //state and relock it again diff --git a/test/robust_recursive_emulation_test.cpp b/test/robust_recursive_emulation_test.cpp index bfda4cc..bc14076 100644 --- a/test/robust_recursive_emulation_test.cpp +++ b/test/robust_recursive_emulation_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2010-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2010-2012. 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/semaphore_test.cpp b/test/semaphore_test.cpp index ed71ba6..54913ce 100644 --- a/test/semaphore_test.cpp +++ b/test/semaphore_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2004-2012. 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/set_test.hpp b/test/set_test.hpp index cdec125..9aec856 100644 --- a/test/set_test.hpp +++ b/test/set_test.hpp @@ -1,6 +1,6 @@ //////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2004-2012. 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) // @@ -58,7 +58,7 @@ int set_test () MyStdMultiSet *stdmultiset = new MyStdMultiSet; - //Test construction from a range + //Test construction from a range { IntType aux_vect[50]; for(int i = 0; i < 50; ++i){ @@ -567,7 +567,7 @@ int set_test_copyable () shmmsetcopy = *shmmultiset; stdmsetcopy = *stdmultiset; - + if(!CheckEqualContainers(&shmmsetcopy, &stdmsetcopy)) return 1; } diff --git a/test/sharable_mutex_test.cpp b/test/sharable_mutex_test.cpp new file mode 100644 index 0000000..b273154 --- /dev/null +++ b/test/sharable_mutex_test.cpp @@ -0,0 +1,31 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2004-2012. 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 "mutex_test_template.hpp" +#include "sharable_mutex_test_template.hpp" +#include +#include +#include +#include +#include "util.hpp" + +int main () +{ + using namespace boost::interprocess; + + test::test_all_lock(); + test::test_all_mutex(); + test::test_all_sharable_mutex(); + + return 0; +} + +#include diff --git a/test/sharable_mutex_test_template.hpp b/test/sharable_mutex_test_template.hpp index 66ab056..3fc5e98 100644 --- a/test/sharable_mutex_test_template.hpp +++ b/test/sharable_mutex_test_template.hpp @@ -10,7 +10,7 @@ // It is provided "as is" without express or implied warranty. ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2005-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2005-2012. 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/shared_memory_mapping_test.cpp b/test/shared_memory_mapping_test.cpp index 52d615e..a3b0f10 100644 --- a/test/shared_memory_mapping_test.cpp +++ b/test/shared_memory_mapping_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2004-2012. 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) // @@ -31,7 +31,7 @@ int main () std::string process_id2(process_id); process_id2 += "_2"; try{ - const std::size_t FileSize = 99999*2; + const std::size_t FileSize = 99999*4; { //Remove shared memory shared_memory_object::remove(process_id.c_str()); @@ -59,7 +59,7 @@ int main () ,FileSize - FileSize/2 ,0); - //Fill two regions with a pattern + //Fill two regions with a pattern unsigned char *filler = static_cast(region.get_address()); for(std::size_t i = 0 ;i < FileSize/2 @@ -129,6 +129,52 @@ int main () return 1; } } + //Now shrink + const std::size_t original_region_size = region.get_size(); + if(!region.shrink_by(region.get_size()/2, false) || region.get_size() != original_region_size/2){ + return 1; + } + const std::size_t shrunk_region_size = region.get_size(); + if(!region.shrink_by(region.get_size()/2, true) || region.get_size() != shrunk_region_size/2){ + return 1; + } + + //Now advise + #if defined(POSIX_MADV_NORMAL) || defined(MADV_NORMAL) + std::cout << "Advice normal" << std::endl; + if(!region.advise(mapped_region::advice_normal)){ + return 1; + } + #endif + + #if defined(POSIX_MADV_SEQUENTIAL) || defined(MADV_SEQUENTIAL) + std::cout << "Advice sequential" << std::endl; + if(!region.advise(mapped_region::advice_sequential)){ + return 1; + } + #endif + + #if defined(POSIX_MADV_RANDOM) || defined(MADV_RANDOM) + std::cout << "Advice random" << std::endl; + if(!region.advise(mapped_region::advice_random)){ + return 1; + } + #endif + + #if defined(POSIX_MADV_WILLNEED) || defined(MADV_WILLNEED) + std::cout << "Advice 'will need'" << std::endl; + if(!region.advise(mapped_region::advice_willneed)){ + return 1; + } + #endif + + #if defined(POSIX_MADV_DONTNEED) || (defined(MADV_DONTNEED) && defined(BOOST_INTERPROCESS_MADV_DONTNEED_HAS_NONDESTRUCTIVE_SEMANTICS)) + std::cout << "Advice 'dont't need'" << std::endl; + if(!region.advise(mapped_region::advice_dontneed)){ + return 1; + } + #endif + } { //Check for busy address space diff --git a/test/shared_memory_test.cpp b/test/shared_memory_test.cpp index de51516..347ab47 100644 --- a/test/shared_memory_test.cpp +++ b/test/shared_memory_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2004-2012. 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) // @@ -62,7 +62,7 @@ int main () test::test_named_creation(); //Create and get name, size and address - { + { shared_memory_object::remove(ShmName); shared_memory shm1(create_only, ShmName, ShmSize, read_write, 0, permissions()); diff --git a/test/shared_ptr_test.cpp b/test/shared_ptr_test.cpp index ff7f215..7ca0942 100644 --- a/test/shared_ptr_test.cpp +++ b/test/shared_ptr_test.cpp @@ -1,7 +1,7 @@ ////////////////////////////////////////////////////////////////////////////// // // (C) Copyright Peter Dimov 2002-2005, 2007. -// (C) Copyright Ion Gaztanaga 2006-2011. +// (C) Copyright Ion Gaztanaga 2006-2012. // 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) @@ -144,7 +144,7 @@ int string_shared_ptr_vector_insertion_test() { managed_shared_memory shmem(create_only, process_name.c_str(), 20000); - { + { const int NumElements = 100; //Construct the allocator of strings string_allocator_t string_allocator(shmem.get_segment_manager()); @@ -202,7 +202,7 @@ int string_shared_ptr_vector_insertion_test() } //Now fill a vector of weak_ptr-s string_weak_ptr_vector_t my_weakptr_vector(string_weak_ptr_allocator); - my_weakptr_vector.insert(my_weakptr_vector.begin(), NumElements, string_weak_ptr); + my_weakptr_vector.insert(my_weakptr_vector.begin(), NumElements, string_weak_ptr); //The shared count should remain the same if(string_shared_ptr.use_count() != static_cast(my_sharedptr_vector.size()+1)){ return 1; diff --git a/test/slist_test.cpp b/test/slist_test.cpp index db271b3..2f20748 100644 --- a/test/slist_test.cpp +++ b/test/slist_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2004-2012. 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/stable_vector_test.cpp b/test/stable_vector_test.cpp index 5af9a1c..cb2a1bb 100644 --- a/test/stable_vector_test.cpp +++ b/test/stable_vector_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2004-2012. 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/string_test.cpp b/test/string_test.cpp index 7713329..150caa5 100644 --- a/test/string_test.cpp +++ b/test/string_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2004-2012. 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) // @@ -82,7 +82,7 @@ int string_test() (create_only, process_name.c_str(),//segment name 65536); //segment size in bytes - + ShmemAllocatorChar shmallocator (segment.get_segment_manager()); //Initialize vector with a range or iterators and allocator @@ -166,16 +166,16 @@ int string_test() shm_swapper.swap(auxShmString); std_swapper.swap(auxStdString); if(!StringEqual()(auxShmString, auxStdString)) - return 1; + return 1; if(!StringEqual()(shm_swapper, std_swapper)) - return 1; + return 1; shm_swapper.swap(auxShmString); std_swapper.swap(auxStdString); if(!StringEqual()(auxShmString, auxStdString)) - return 1; + return 1; if(!StringEqual()(shm_swapper, std_swapper)) - return 1; + return 1; auxShmString = "LongLongLongLongLongLongLongLongLongLongLongLongLongString"; auxStdString = "LongLongLongLongLongLongLongLongLongLongLongLongLongString"; @@ -184,16 +184,16 @@ int string_test() shm_swapper.swap(auxShmString); std_swapper.swap(auxStdString); if(!StringEqual()(auxShmString, auxStdString)) - return 1; + return 1; if(!StringEqual()(shm_swapper, std_swapper)) - return 1; + return 1; shm_swapper.swap(auxShmString); std_swapper.swap(auxStdString); if(!StringEqual()(auxShmString, auxStdString)) - return 1; + return 1; if(!StringEqual()(shm_swapper, std_swapper)) - return 1; + return 1; //No sort std::sort(shmStringVect->begin(), shmStringVect->end()); diff --git a/test/tree_test.cpp b/test/tree_test.cpp index f11ce78..4619052 100644 --- a/test/tree_test.cpp +++ b/test/tree_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2004-2012. 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) // @@ -42,19 +42,19 @@ typedef basic_managed_shared_memory //We will work with narrow characters for shared memory objects //Alias an integer node allocator type -typedef allocator +typedef allocator shmem_allocator_t; -typedef allocator, my_managed_shared_memory::segment_manager> +typedef allocator, my_managed_shared_memory::segment_manager> shmem_node_pair_allocator_t; -typedef allocator +typedef allocator shmem_movable_allocator_t; -typedef allocator, my_managed_shared_memory::segment_manager> +typedef allocator, my_managed_shared_memory::segment_manager> shmem_movable_node_pair_allocator_t; -typedef allocator +typedef allocator shmem_move_copy_allocator_t; -typedef allocator +typedef allocator shmem_copy_allocator_t; -typedef allocator, my_managed_shared_memory::segment_manager> +typedef allocator, my_managed_shared_memory::segment_manager> shmem_move_copy_node_pair_allocator_t; //Alias standard types diff --git a/test/unique_ptr_test.cpp b/test/unique_ptr_test.cpp index 9e57313..b9e24dd 100644 --- a/test/unique_ptr_test.cpp +++ b/test/unique_ptr_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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) // @@ -56,7 +56,7 @@ int main() shared_memory_object::remove(process_name.c_str()); { managed_shared_memory segment(create_only, process_name.c_str(), 10000); - + //Create unique_ptr using dynamic allocation my_unique_ptr_class my_ptr (segment.construct(anonymous_instance)() ,segment.get_deleter()); @@ -83,7 +83,7 @@ int main() assert(my_ptr2.get() == 0); assert(list.begin()->get() == ptr1); assert(list.rbegin()->get() == ptr2); - + //Construct a set and fill typedef std::less set_less_t; MySet set(set_less_t(), segment.get_segment_manager()); diff --git a/test/unordered_test.cpp b/test/unordered_test.cpp index 37343ea..54673d5 100644 --- a/test/unordered_test.cpp +++ b/test/unordered_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2007-2012. 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/upgradable_mutex_test.cpp b/test/upgradable_mutex_test.cpp index ef0b708..94bc315 100644 --- a/test/upgradable_mutex_test.cpp +++ b/test/upgradable_mutex_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2004-2012. 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/user_buffer_test.cpp b/test/user_buffer_test.cpp index daf63e9..d48be22 100644 --- a/test/user_buffer_test.cpp +++ b/test/user_buffer_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2004-2012. 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) // @@ -201,7 +201,7 @@ int main () heaplist->merge(otherheaplist, std::greater()); stdlist->merge(otherstdlist, std::greater()); if(!CheckEqual(userlist, stdlist, heaplist)) return 1; - + user_buffer.destroy(L"MyUserList"); delete stdlist; @@ -212,7 +212,7 @@ int main () } } catch(boost::interprocess::bad_alloc &){} - + MyHeapList::size_type heap_list_size = heaplist->size(); //Copy heap buffer to another @@ -246,7 +246,7 @@ int main () } catch(boost::interprocess::bad_alloc &){} - MyUserList::size_type user_list_size = userlist->size(); + MyUserList::size_type user_list_size = userlist->size(); if(user_list_size <= heap_list_size){ return 1; diff --git a/test/util.hpp b/test/util.hpp index ddd13d4..1580c9f 100644 --- a/test/util.hpp +++ b/test/util.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2004-2012. 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/vector_test.cpp b/test/vector_test.cpp index 0111b32..ed3aed5 100644 --- a/test/vector_test.cpp +++ b/test/vector_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2004-2012. 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/vector_test.hpp b/test/vector_test.hpp index 51f1a29..04642c1 100644 --- a/test/vector_test.hpp +++ b/test/vector_test.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2004-2012. 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) // @@ -102,15 +102,15 @@ int vector_test() shmvector->resize(100); stdvector->resize(100); - if(!test::CheckEqualContainers(shmvector, stdvector)) return 1; + if(!test::CheckEqualContainers(shmvector, stdvector)) return 1; shmvector->resize(200); stdvector->resize(200); - if(!test::CheckEqualContainers(shmvector, stdvector)) return 1; + if(!test::CheckEqualContainers(shmvector, stdvector)) return 1; shmvector->resize(0); stdvector->resize(0); - if(!test::CheckEqualContainers(shmvector, stdvector)) return 1; + if(!test::CheckEqualContainers(shmvector, stdvector)) return 1; for(int i = 0; i < max; ++i){ IntType new_int(i); diff --git a/test/vectorstream_test.cpp b/test/vectorstream_test.cpp index 9404ba9..e072ecd 100644 --- a/test/vectorstream_test.cpp +++ b/test/vectorstream_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2006. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2006-2012. 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) // @@ -37,7 +37,7 @@ using namespace boost::interprocess; static int vectorstream_test() { - { //Test high watermarking initialization + { //Test high watermarking initialization my_stringstream_t my_stringstream; int a (0); my_stringstream << 11; @@ -45,7 +45,7 @@ static int vectorstream_test() if(a != 11) return 1; } - { //Test high watermarking initialization + { //Test high watermarking initialization my_vectorstream_t my_stringstream; int a (0); my_stringstream << 13; @@ -66,7 +66,7 @@ static int vectorstream_test() my_stringstream << "testline: " << i << std::endl; std_stringstream << "testline: " << i << std::endl; } - + if(std::strcmp(my_stringstream.vector().c_str(), std_stringstream.str().c_str()) != 0){ return 1; } @@ -75,10 +75,10 @@ static int vectorstream_test() my_stringstream >> str1 >> number1; std_stringstream >> str2 >> number2; if((str1 != str2) || (str1 != str3)){ - assert(0); return 1; + assert(0); return 1; } if((number1 != number2) || (number1 != i)){ - assert(0); return 1; + assert(0); return 1; } } } @@ -105,10 +105,10 @@ static int vectorstream_test() my_vectorstream >> str1 >> number1; std_stringstream >> str2 >> number2; if((str1 != str2) || (str1 != str3)){ - assert(0); return 1; + assert(0); return 1; } if((number1 != number2) || (number1 != i)){ - assert(0); return 1; + assert(0); return 1; } } } @@ -131,10 +131,10 @@ static int vectorstream_test() my_stringstream >> str1 >> number1; std_stringstream >> str2 >> number2; if((str1 != str2) || (str1 != str3)){ - assert(0); return 1; + assert(0); return 1; } if((number1 != number2) || (number1 != i)){ - assert(0); return 1; + assert(0); return 1; } } } diff --git a/test/windows_shared_memory_mapping_test.cpp b/test/windows_shared_memory_mapping_test.cpp index 0a8cdaa..115dc7f 100644 --- a/test/windows_shared_memory_mapping_test.cpp +++ b/test/windows_shared_memory_mapping_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2004-2012. 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) // @@ -48,7 +48,7 @@ int main () ,FileSize - FileSize/2 ,0); - //Fill two regions with a pattern + //Fill two regions with a pattern unsigned char *filler = static_cast(region.get_address()); for(std::size_t i = 0 ;i < FileSize/2 diff --git a/test/windows_shared_memory_test.cpp b/test/windows_shared_memory_test.cpp index 84bae98..f21999d 100644 --- a/test/windows_shared_memory_test.cpp +++ b/test/windows_shared_memory_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2004-2012. 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/xsi_shared_memory_mapping_test.cpp b/test/xsi_shared_memory_mapping_test.cpp index 4326d77..e82de82 100644 --- a/test/xsi_shared_memory_mapping_test.cpp +++ b/test/xsi_shared_memory_mapping_test.cpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2004-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2004-2012. 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) // @@ -93,7 +93,7 @@ int main (int argc, char *argv[]) //Create a mapped region mapped_region region (mapping, read_write, 0, FileSize, 0); - //Fill two regions with a pattern + //Fill two regions with a pattern unsigned char *filler = static_cast(region.get_address()); for(std::size_t i = 0; i < FileSize; ++i){ *filler++ = static_cast(i);