diff options
Diffstat (limited to 'boost/interprocess/detail')
42 files changed, 2433 insertions, 1192 deletions
diff --git a/boost/interprocess/detail/atomic.hpp b/boost/interprocess/detail/atomic.hpp index aab1533985..96b7729d7e 100644 --- a/boost/interprocess/detail/atomic.hpp +++ b/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 // @@ -15,6 +15,10 @@ #ifndef BOOST_INTERPROCESS_DETAIL_ATOMIC_HPP #define BOOST_INTERPROCESS_DETAIL_ATOMIC_HPP +#if defined(_MSC_VER) +# pragma once +#endif + #include <boost/interprocess/detail/config_begin.hpp> #include <boost/interprocess/detail/workaround.hpp> #include <boost/cstdint.hpp> @@ -49,10 +53,22 @@ inline boost::uint32_t atomic_cas32 } //namespace interprocess{ } //namespace boost{ -#if (defined BOOST_INTERPROCESS_WINDOWS) +#if defined (BOOST_INTERPROCESS_WINDOWS) #include <boost/interprocess/detail/win32_api.hpp> +#if defined( _MSC_VER ) + extern "C" void _ReadWriteBarrier(void); + #pragma intrinsic(_ReadWriteBarrier) + #define BOOST_INTERPROCESS_READ_WRITE_BARRIER _ReadWriteBarrier() +#elif defined(__GNUC__) + #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100 + #define BOOST_INTERPROCESS_READ_WRITE_BARRIER __sync_synchronize() + #else + #define BOOST_INTERPROCESS_READ_WRITE_BARRIER __asm__ __volatile__("" : : : "memory") + #endif +#endif + namespace boost{ namespace interprocess{ namespace ipcdetail{ @@ -71,7 +87,11 @@ inline boost::uint32_t atomic_inc32(volatile boost::uint32_t *mem) //! Atomically read an boost::uint32_t from memory inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem) -{ return *mem; } +{ + const boost::uint32_t val = *mem; + BOOST_INTERPROCESS_READ_WRITE_BARRIER; + return val; +} //! Atomically set an boost::uint32_t in memory //! "mem": pointer to the object @@ -93,7 +113,7 @@ inline boost::uint32_t atomic_cas32 } //namespace interprocess{ } //namespace boost{ -#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) +#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) && !defined(_CRAYC) namespace boost { namespace interprocess { @@ -157,13 +177,24 @@ inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem) //! Atomically read an boost::uint32_t from memory inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem) -{ return *mem; } +{ + const boost::uint32_t val = *mem; + __asm__ __volatile__ ( "" ::: "memory" ); + return 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; } +{ + __asm__ __volatile__ + ( + "xchgl %0, %1" + : "+r" (val), "+m" (*mem) + :: "memory" + ); +} } //namespace ipcdetail{ } //namespace interprocess{ @@ -213,7 +244,7 @@ inline boost::uint32_t atomic_cas32 "bne- 1b\n\t" "2:" : "=&r"(prev) - : "b" (mem), "r"(cmp), "r" (with) + : "b" (mem), "r" (with), "r" (cmp) : "cc", "memory"); return prev; } @@ -232,7 +263,11 @@ inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem) //! Atomically read an boost::uint32_t from memory inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem) -{ return *mem; } +{ + const boost::uint32_t val = *mem; + __asm__ __volatile__ ( "" ::: "memory" ); + return val; +} //! Atomically set an boost::uint32_t in memory //! "mem": pointer to the object @@ -390,96 +425,96 @@ inline boost::uint32_t atomic_cas32( } //namespace interprocess{ } //namespace boost{ -#elif defined(__IBMCPP__) && (__IBMCPP__ >= 800) && defined(_AIX) - -#include <builtins.h> - -namespace boost { -namespace interprocess { -namespace ipcdetail{ - -//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<boost::uint32_t>(__lwarx(reinterpret_cast<volatile int*>(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<volatile int*>(mem), static_cast<int>(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; -} - -//! 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 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)); - - 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; } - -} //namespace ipcdetail -} //namespace interprocess +#elif defined(__IBMCPP__) && (__IBMCPP__ >= 800) && defined(_AIX) + +#include <builtins.h> + +namespace boost { +namespace interprocess { +namespace ipcdetail{ + +//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<boost::uint32_t>(__lwarx(reinterpret_cast<volatile int*>(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<volatile int*>(mem), static_cast<int>(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; +} + +//! 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 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)); + + 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; } + +} //namespace ipcdetail +} //namespace interprocess } //namespace boost #elif defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) @@ -510,7 +545,7 @@ inline boost::uint32_t atomic_dec32(volatile boost::uint32_t *mem) //! Atomically read an boost::uint32_t from memory inline boost::uint32_t atomic_read32(volatile boost::uint32_t *mem) -{ return *mem; } +{ boost::uint32_t old_val = *mem; __sync_synchronize(); return old_val; } //! Compare an boost::uint32_t's value with "cmp". //! If they are the same swap the value with "with" @@ -526,7 +561,7 @@ inline boost::uint32_t atomic_cas32 //! "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; } +{ __sync_synchronize(); *mem = val; } } //namespace ipcdetail{ } //namespace interprocess{ @@ -552,9 +587,9 @@ inline bool atomic_add_unless32 return c != unless_this; } -} //namespace ipcdetail -} //namespace interprocess -} //namespace boost +} //namespace ipcdetail +} //namespace interprocess +} //namespace boost #include <boost/interprocess/detail/config_end.hpp> diff --git a/boost/interprocess/detail/cast_tags.hpp b/boost/interprocess/detail/cast_tags.hpp index bd91d1b6bb..0019af7933 100644 --- a/boost/interprocess/detail/cast_tags.hpp +++ b/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) // @@ -11,6 +11,10 @@ #ifndef BOOST_INTERPROCESS_CAST_TAGS_HPP #define BOOST_INTERPROCESS_CAST_TAGS_HPP +#if defined(_MSC_VER) +# pragma once +#endif + #include <boost/interprocess/detail/config_begin.hpp> #include <boost/interprocess/detail/workaround.hpp> diff --git a/boost/interprocess/detail/config_begin.hpp b/boost/interprocess/detail/config_begin.hpp index a72f6df1fe..8bcdcac587 100644 --- a/boost/interprocess/detail/config_begin.hpp +++ b/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) // @@ -13,10 +13,6 @@ #endif #ifdef BOOST_MSVC - #ifndef _CRT_SECURE_NO_DEPRECATE - #define BOOST_INTERPROCESS_CRT_SECURE_NO_DEPRECATE - #define _CRT_SECURE_NO_DEPRECATE - #endif #pragma warning (push) #pragma warning (disable : 4702) // unreachable code #pragma warning (disable : 4706) // assignment within conditional expression diff --git a/boost/interprocess/detail/config_end.hpp b/boost/interprocess/detail/config_end.hpp index 422458e855..28ec407312 100644 --- a/boost/interprocess/detail/config_end.hpp +++ b/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) // @@ -9,9 +9,5 @@ ////////////////////////////////////////////////////////////////////////////// #if defined BOOST_MSVC #pragma warning (pop) - #ifdef BOOST_INTERPROCESS_CRT_SECURE_NO_DEPRECATE - #undef BOOST_INTERPROCESS_CRT_SECURE_NO_DEPRECATE - #undef _CRT_SECURE_NO_DEPRECATE - #endif #endif diff --git a/boost/interprocess/detail/config_external_begin.hpp b/boost/interprocess/detail/config_external_begin.hpp new file mode 100644 index 0000000000..fb578ef013 --- /dev/null +++ b/boost/interprocess/detail/config_external_begin.hpp @@ -0,0 +1,18 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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_EXTERNAL_CONFIG_INCLUDED +#define BOOST_INTERPROCESS_EXTERNAL_CONFIG_INCLUDED +#include <boost/config.hpp> +#endif + +#if defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 406) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wshadow" +#endif diff --git a/boost/interprocess/detail/config_external_end.hpp b/boost/interprocess/detail/config_external_end.hpp new file mode 100644 index 0000000000..214558f58c --- /dev/null +++ b/boost/interprocess/detail/config_external_end.hpp @@ -0,0 +1,12 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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. +// +////////////////////////////////////////////////////////////////////////////// +#if defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 406) +# pragma GCC diagnostic pop +#endif diff --git a/boost/interprocess/detail/file_locking_helpers.hpp b/boost/interprocess/detail/file_locking_helpers.hpp index 2b96e2b6d5..6a7ce8ef3b 100644 --- a/boost/interprocess/detail/file_locking_helpers.hpp +++ b/boost/interprocess/detail/file_locking_helpers.hpp @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_FILE_LOCKING_HELPERS_HPP #define BOOST_INTERPROCESS_FILE_LOCKING_HELPERS_HPP -#if defined(_MSC_VER)&&(_MSC_VER>=1200) +#if defined(_MSC_VER) #pragma once #endif @@ -26,7 +26,7 @@ #include <cstddef> #include <boost/interprocess/detail/os_file_functions.hpp> -#include <boost/interprocess/detail/tmp_dir_helpers.hpp> +#include <boost/interprocess/detail/shared_dir_helpers.hpp> #if defined(BOOST_INTERPROCESS_WINDOWS) @@ -287,7 +287,7 @@ inline bool compare_file_serial(int fd, const locking_file_serial_id &id) id.st_ino == info.st_ino; } -#endif +#endif } //namespace ipcdetail{ } //namespace interprocess{ diff --git a/boost/interprocess/detail/file_wrapper.hpp b/boost/interprocess/detail/file_wrapper.hpp index 586e20db4d..507ec478dc 100644 --- a/boost/interprocess/detail/file_wrapper.hpp +++ b/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) // @@ -11,11 +11,15 @@ #ifndef BOOST_INTERPROCESS_DETAIL_FILE_WRAPPER_HPP #define BOOST_INTERPROCESS_DETAIL_FILE_WRAPPER_HPP +#if defined(_MSC_VER) +# pragma once +#endif + #include <boost/interprocess/detail/config_begin.hpp> #include <boost/interprocess/detail/workaround.hpp> #include <boost/interprocess/detail/os_file_functions.hpp> #include <boost/interprocess/creation_tags.hpp> -#include <boost/move/move.hpp> +#include <boost/move/utility_core.hpp> #include <boost/interprocess/creation_tags.hpp> namespace boost { @@ -24,9 +28,9 @@ namespace ipcdetail{ class file_wrapper { - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) BOOST_MOVABLE_BUT_NOT_COPYABLE(file_wrapper) - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: //!Default constructor. @@ -60,10 +64,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 +77,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 +126,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 @@ -167,7 +171,8 @@ inline bool file_wrapper::priv_open_or_create //Check for error if(m_handle == invalid_file()){ - throw interprocess_exception(error_info(system_error_code())); + error_info err = system_error_code(); + throw interprocess_exception(err); } m_mode = mode; diff --git a/boost/interprocess/detail/in_place_interface.hpp b/boost/interprocess/detail/in_place_interface.hpp index b43b2ce165..5af5a0d2df 100644 --- a/boost/interprocess/detail/in_place_interface.hpp +++ b/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) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_IN_PLACE_INTERFACE_HPP #define BOOST_INTERPROCESS_IN_PLACE_INTERFACE_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -47,7 +47,7 @@ template<class T> struct placement_destroy : public in_place_interface { placement_destroy() - : in_place_interface(::boost::alignment_of<T>::value, sizeof(T), typeid(T).name()) + : in_place_interface(::boost::alignment_of<T>::value, sizeof(T), typeid(T).name()) {} virtual void destroy_n(void *mem, std::size_t num, std::size_t &destroyed) diff --git a/boost/interprocess/detail/intermodule_singleton.hpp b/boost/interprocess/detail/intermodule_singleton.hpp index 054322699d..a99934893d 100644 --- a/boost/interprocess/detail/intermodule_singleton.hpp +++ b/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) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_INTERMODULE_SINGLETON_HPP #define BOOST_INTERPROCESS_INTERMODULE_SINGLETON_HPP -#if defined(_MSC_VER)&&(_MSC_VER>=1200) +#if defined(_MSC_VER) #pragma once #endif @@ -20,8 +20,9 @@ #ifdef BOOST_INTERPROCESS_WINDOWS #include <boost/interprocess/detail/windows_intermodule_singleton.hpp> +#else + #include <boost/interprocess/detail/portable_intermodule_singleton.hpp> #endif -#include <boost/interprocess/detail/portable_intermodule_singleton.hpp> namespace boost{ namespace interprocess{ @@ -30,7 +31,7 @@ namespace ipcdetail{ //Now this class is a singleton, initializing the singleton in //the first get() function call if LazyInit is false. If true //then the singleton will be initialized when loading the module. -template<typename C, bool LazyInit = true, bool Phoenix = true> +template<typename C, bool LazyInit = true, bool Phoenix = false> class intermodule_singleton #ifdef BOOST_INTERPROCESS_WINDOWS : public windows_intermodule_singleton<C, LazyInit, Phoenix> diff --git a/boost/interprocess/detail/intermodule_singleton_common.hpp b/boost/interprocess/detail/intermodule_singleton_common.hpp index 0710c0bbc1..10c9eceabb 100644 --- a/boost/interprocess/detail/intermodule_singleton_common.hpp +++ b/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) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_INTERMODULE_SINGLETON_COMMON_HPP #define BOOST_INTERPROCESS_INTERMODULE_SINGLETON_COMMON_HPP -#if defined(_MSC_VER)&&(_MSC_VER>=1200) +#if defined(_MSC_VER) #pragma once #endif @@ -20,8 +20,10 @@ #include <boost/interprocess/detail/atomic.hpp> #include <boost/interprocess/detail/os_thread_functions.hpp> +#include <boost/interprocess/exceptions.hpp> #include <boost/type_traits/type_with_alignment.hpp> #include <boost/interprocess/detail/mpl.hpp> +#include <boost/interprocess/sync/spin/wait.hpp> #include <boost/assert.hpp> #include <cstddef> #include <cstdio> @@ -121,7 +123,8 @@ class intermodule_singleton_common //Now try to create the singleton in global map. //This function solves concurrency issues //between threads of several modules - void *tmp = constructor(get_map()); + ThreadSafeGlobalMap *const pmap = get_map_ptr(); + void *tmp = constructor(*pmap); //Increment the module reference count that reflects how many //singletons this module holds, so that we can safely destroy //module global map object when no singleton is left @@ -144,6 +147,7 @@ class intermodule_singleton_common //If previous state was initializing, this means that another winner thread is //trying to initialize the singleton. Just wait until completes its work. else if(previous_module_singleton_initialized == Initializing){ + spin_wait swait; while(1){ previous_module_singleton_initialized = atomic_read32(&this_module_singleton_initialized); if(previous_module_singleton_initialized >= Initialized){ @@ -151,7 +155,7 @@ class intermodule_singleton_common break; } else if(previous_module_singleton_initialized == Initializing){ - thread_yield(); + swait.yield(); } else{ //This can't be happening! @@ -178,7 +182,8 @@ class intermodule_singleton_common //Note: this destructor might provoke a Phoenix singleton //resurrection. This means that this_module_singleton_count //might change after this call. - destructor(ptr, get_map()); + ThreadSafeGlobalMap * const pmap = get_map_ptr(); + destructor(ptr, *pmap); ptr = 0; //Memory barrier to make sure pointer is nulled. @@ -197,14 +202,15 @@ class intermodule_singleton_common } private: - static ThreadSafeGlobalMap &get_map() + static ThreadSafeGlobalMap *get_map_ptr() { - return *static_cast<ThreadSafeGlobalMap *>(static_cast<void *>(&mem_holder.map_mem)); + return static_cast<ThreadSafeGlobalMap *>(static_cast<void*>(mem_holder.map_mem)); } static void initialize_global_map_handle() { //Obtain unique map name and size + spin_wait swait; while(1){ //Try to pass map state to initializing ::boost::uint32_t tmp = atomic_cas32(&this_module_map_initialized, Initializing, Uninitialized); @@ -217,7 +223,7 @@ class intermodule_singleton_common } //If some other thread is doing the work wait else if(tmp == Initializing){ - thread_yield(); + swait.yield(); } else{ //(tmp == Uninitialized) //If not initialized try it again? @@ -225,16 +231,17 @@ class intermodule_singleton_common //Remove old global map from the system intermodule_singleton_helpers::thread_safe_global_map_dependant<ThreadSafeGlobalMap>::remove_old_gmem(); //in-place construction of the global map class + ThreadSafeGlobalMap * const pmap = get_map_ptr(); intermodule_singleton_helpers::thread_safe_global_map_dependant - <ThreadSafeGlobalMap>::construct_map(static_cast<void*>(&get_map())); + <ThreadSafeGlobalMap>::construct_map(static_cast<void*>(pmap)); //Use global map's internal lock to initialize the lock file //that will mark this gmem as "in use". typename intermodule_singleton_helpers::thread_safe_global_map_dependant<ThreadSafeGlobalMap>:: - lock_file_logic f(get_map()); + lock_file_logic f(*pmap); //If function failed (maybe a competing process has erased the shared //memory between creation and file locking), retry with a new instance. if(f.retry()){ - get_map().~ThreadSafeGlobalMap(); + pmap->~ThreadSafeGlobalMap(); atomic_write32(&this_module_map_initialized, Destroyed); } else{ @@ -257,9 +264,10 @@ class intermodule_singleton_common //This module is being unloaded, so destroy //the global map object of this module //and unlink the global map if it's the last + ThreadSafeGlobalMap * const pmap = get_map_ptr(); typename intermodule_singleton_helpers::thread_safe_global_map_dependant<ThreadSafeGlobalMap>:: - unlink_map_logic f(get_map()); - (get_map()).~ThreadSafeGlobalMap(); + unlink_map_logic f(*pmap); + pmap->~ThreadSafeGlobalMap(); atomic_write32(&this_module_map_initialized, Destroyed); //Do some cleanup for other processes old gmem instances intermodule_singleton_helpers::thread_safe_global_map_dependant<ThreadSafeGlobalMap>::remove_old_gmem(); @@ -274,11 +282,11 @@ 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 - static struct mem_holder_t + //Raw memory to construct the global map manager + static union mem_holder_t { + unsigned char map_mem [sizeof(ThreadSafeGlobalMap)]; ::boost::detail::max_align aligner; - char map_mem [sizeof(ThreadSafeGlobalMap)]; } mem_holder; }; @@ -308,7 +316,7 @@ struct ref_count_ptr //Now this class is a singleton, initializing the singleton in -//the first get() function call if LazyInit is false. If true +//the first get() function call if LazyInit is true. If false //then the singleton will be initialized when loading the module. template<typename C, bool LazyInit, bool Phoenix, class ThreadSafeGlobalMap> class intermodule_singleton_impl @@ -356,9 +364,9 @@ class intermodule_singleton_impl ~lifetime_type_lazy() { - if(!Phoenix){ - atexit_work(); - } + //if(!Phoenix){ + //atexit_work(); + //} } //Dummy volatile so that the compiler can't resolve its value at compile-time @@ -384,7 +392,7 @@ class intermodule_singleton_impl struct init_atomic_func { init_atomic_func(ThreadSafeGlobalMap &m) - : m_map(m) + : m_map(m), ret_ptr() {} void operator()() @@ -405,13 +413,13 @@ class intermodule_singleton_impl throw; } } - if(Phoenix){ + //if(Phoenix){ std::atexit(&atexit_work); - } + //} atomic_inc32(&rcount->singleton_ref_count); ret_ptr = rcount->ptr; } - void *data() const + void *data() const { return ret_ptr; } private: @@ -446,12 +454,9 @@ class intermodule_singleton_impl delete pc; } } - void *data() const - { return ret_ptr; } - + private: ThreadSafeGlobalMap &m_map; - void *ret_ptr; }; //A wrapper to execute init_atomic_func diff --git a/boost/interprocess/detail/interprocess_tester.hpp b/boost/interprocess/detail/interprocess_tester.hpp index 2581776745..8c00c4c0c4 100644 --- a/boost/interprocess/detail/interprocess_tester.hpp +++ b/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) // @@ -11,6 +11,10 @@ #ifndef BOOST_INTERPROCESS_DETAIL_INTERPROCESS_TESTER_HPP #define BOOST_INTERPROCESS_DETAIL_INTERPROCESS_TESTER_HPP +#if defined(_MSC_VER) +# pragma once +#endif + namespace boost{ namespace interprocess{ namespace ipcdetail{ diff --git a/boost/interprocess/detail/intersegment_ptr.hpp b/boost/interprocess/detail/intersegment_ptr.hpp index 16d3505883..fa1b277ef4 100644 --- a/boost/interprocess/detail/intersegment_ptr.hpp +++ b/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) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_INTERSEGMENT_PTR_HPP #define BOOST_INTERPROCESS_INTERSEGMENT_PTR_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -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<void*>(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<segment_data> 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<char*>(reinterpret_cast<const char*>(it->first)); std::size_t segment_size = it->second.size; - + if(segment_base <= reinterpret_cast<const char*>(ptr) && (segment_base + segment_size) >= reinterpret_cast<const char*>(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<interprocess_mutex> //!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<interprocess_mutex> //!are assignable, intersegment_ptrs will be assignable. Never throws. template <class T2> intersegment_ptr& operator= (const intersegment_ptr<T2> & 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<interprocess_mutex> //!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<interprocess_mutex> //!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<interprocess_mutex> template <class T1, class T2> inline bool operator ==(const intersegment_ptr<T1> &left, const intersegment_ptr<T2> &right) -{ +{ //Make sure both pointers can be compared bool e = typename intersegment_ptr<T1>::pointer(0) == typename intersegment_ptr<T2>::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<T1> &left, template <class T1, class T2> inline bool operator <(const intersegment_ptr<T1> &left, const intersegment_ptr<T2> &right) -{ +{ //Make sure both pointers can be compared bool e = typename intersegment_ptr<T1>::pointer(0) < typename intersegment_ptr<T2>::pointer(0); (void)e; - return left._less(right); + return left._less(right); } template<class T1, class T2> inline diff --git a/boost/interprocess/detail/managed_global_memory.hpp b/boost/interprocess/detail/managed_global_memory.hpp index 39dd0b1e6d..baa6361e69 100644 --- a/boost/interprocess/detail/managed_global_memory.hpp +++ b/boost/interprocess/detail/managed_global_memory.hpp @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_BASIC_GLOBAL_MEMORY_HPP #define BOOST_INTERPROCESS_BASIC_GLOBAL_MEMORY_HPP -#if defined(_MSC_VER)&&(_MSC_VER>=1200) +#if defined(_MSC_VER) #pragma once #endif @@ -23,7 +23,7 @@ #include <boost/interprocess/sync/spin/recursive_mutex.hpp> #include <boost/interprocess/detail/managed_memory_impl.hpp> #include <boost/interprocess/detail/managed_open_or_create_impl.hpp> -#include <boost/interprocess/mem_algo/rbtree_best_fit.hpp> +#include <boost/interprocess/mem_algo/rbtree_best_fit.hpp> #include <boost/interprocess/indexes/iset_index.hpp> #include <boost/interprocess/creation_tags.hpp> #include <boost/interprocess/permissions.hpp> @@ -47,7 +47,7 @@ struct intermodule_types struct open_or_create { typedef managed_open_or_create_impl - <Device, mem_algo::Alignment, FileBased> type; + <Device, mem_algo::Alignment, FileBased, false> type; }; }; @@ -62,7 +62,7 @@ class basic_managed_global_memory > , private intermodule_types::open_or_create<Device, FileBased>::type { - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) typedef typename intermodule_types::template open_or_create<Device, FileBased>::type base2_t; typedef basic_managed_memory_impl @@ -83,7 +83,7 @@ class basic_managed_global_memory private: typedef typename base_t::char_ptr_holder_t char_ptr_holder_t; BOOST_MOVABLE_BUT_NOT_COPYABLE(basic_managed_global_memory) - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: //functions diff --git a/boost/interprocess/detail/managed_memory_impl.hpp b/boost/interprocess/detail/managed_memory_impl.hpp index f9ecb8a860..b77c53274d 100644 --- a/boost/interprocess/detail/managed_memory_impl.hpp +++ b/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) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_DETAIL_MANAGED_MEMORY_IMPL_HPP #define BOOST_INTERPROCESS_DETAIL_MANAGED_MEMORY_IMPL_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -90,7 +90,7 @@ class basic_managed_memory_impl typedef typename segment_manager:: const_unique_iterator const_unique_iterator; - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) typedef typename segment_manager::char_ptr_holder_t char_ptr_holder_t; @@ -98,7 +98,7 @@ class basic_managed_memory_impl typedef typename segment_manager::multiallocation_chain multiallocation_chain; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED static const size_type PayloadPerAllocation = segment_manager::PayloadPerAllocation; @@ -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<const char*>(ptr) - - reinterpret_cast<const char*>(this->get_address())); + reinterpret_cast<const char*>(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<const char*>(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); } @@ -303,31 +303,37 @@ class basic_managed_memory_impl void * allocate_aligned(size_type nbytes, size_type alignment) { return mp_header->allocate_aligned(nbytes, alignment); } - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) //Experimental. Don't use. - //!Allocates n_elements of elem_size bytes. - multiallocation_chain allocate_many(size_type elem_bytes, size_type num_elements) - { return mp_header->allocate_many(elem_bytes, num_elements); } + //!Allocates n_elements of elem_bytes bytes. + //!Throws bad_alloc on failure. chain.size() is not increased on failure. + void allocate_many(size_type elem_bytes, size_type n_elements, multiallocation_chain &chain) + { mp_header->allocate_many(elem_bytes, n_elements, chain); } - //!Allocates n_elements, each one of elem_sizes[i] bytes. - multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements) - { return mp_header->allocate_many(elem_sizes, n_elements); } + //!Allocates n_elements, each one of element_lengths[i]*sizeof_element bytes. + //!Throws bad_alloc on failure. chain.size() is not increased on failure. + void allocate_many(const size_type *element_lengths, size_type n_elements, size_type sizeof_element, multiallocation_chain &chain) + { mp_header->allocate_many(element_lengths, n_elements, sizeof_element, chain); } - //!Allocates n_elements of elem_size bytes. - multiallocation_chain allocate_many(size_type elem_bytes, size_type num_elements, std::nothrow_t nothrow) - { return mp_header->allocate_many(elem_bytes, num_elements, nothrow); } + //!Allocates n_elements of elem_bytes bytes. + //!Non-throwing version. chain.size() is not increased on failure. + void allocate_many(std::nothrow_t, size_type elem_bytes, size_type n_elements, multiallocation_chain &chain) + { mp_header->allocate_many(std::nothrow_t(), elem_bytes, n_elements, chain); } - //!Allocates n_elements, each one of elem_sizes[i] bytes. - multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements, std::nothrow_t nothrow) - { return mp_header->allocate_many(elem_sizes, n_elements, nothrow); } + //!Allocates n_elements, each one of + //!element_lengths[i]*sizeof_element bytes. + //!Non-throwing version. chain.size() is not increased on failure. + void allocate_many(std::nothrow_t, const size_type *elem_sizes, size_type n_elements, size_type sizeof_element, multiallocation_chain &chain) + { mp_header->allocate_many(std::nothrow_t(), elem_sizes, n_elements, sizeof_element, chain); } - //!Allocates n_elements, each one of elem_sizes[i] bytes. - void deallocate_many(multiallocation_chain chain) - { return mp_header->deallocate_many(boost::move(chain)); } + //!Deallocates all elements contained in chain. + //!Never throws. + void deallocate_many(multiallocation_chain &chain) + { mp_header->deallocate_many(chain); } - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED //!Marks previously allocated memory as free. Never throws. void deallocate (void *addr) @@ -603,7 +609,7 @@ class basic_managed_memory_impl { mp_header->template destroy_ptr<T>(ptr); } //!Returns the name of an object created with construct/find_or_construct - //!functions. Does not throw + //!functions. If ptr points to an unique instance typeid(T).name() is returned. template<class T> static const char_type *get_instance_name(const T *ptr) { return segment_manager::get_instance_name(ptr); } @@ -697,14 +703,14 @@ class basic_managed_memory_impl get_deleter() { return mp_header->template get_deleter<T>(); } - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) //!Tries to find a previous named allocation address. Returns a memory //!buffer and the object count. If not found returned pointer is 0. //!Never throws. template <class T> std::pair<T*, size_type> find_no_lock (char_ptr_holder_t name) { return mp_header->template find_no_lock<T>(name); } - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED protected: //!Swaps the segment manager's managed by this managed memory segment. @@ -719,20 +725,40 @@ class basic_managed_memory_impl template<class BasicManagedMemoryImpl> class create_open_func { + typedef typename BasicManagedMemoryImpl::size_type size_type; + public: + create_open_func(BasicManagedMemoryImpl * const frontend, create_enum_t type) : 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)) + bool operator()(void *addr, std::size_t size, bool created) const + { + if( ((m_type == DoOpen) && created) || + ((m_type == DoCreate) && !created) || + //Check for overflow + size_type(-1) < size ){ return false; + } + else if(created){ + return m_frontend->create_impl(addr, static_cast<size_type>(size)); + } + else{ + return m_frontend->open_impl (addr, static_cast<size_type>(size)); + } + } - if(created) - return m_frontend->create_impl(addr, size); - else - return m_frontend->open_impl (addr, size); + std::size_t get_min_size() const + { + const size_type sz = m_frontend->get_segment_manager()->get_min_size(); + if(sz > std::size_t(-1)){ + //The minimum size is not representable by std::size_t + BOOST_ASSERT(false); + return std::size_t(-1); + } + else{ + return static_cast<std::size_t>(sz); + } } private: diff --git a/boost/interprocess/detail/managed_multi_shared_memory.hpp b/boost/interprocess/detail/managed_multi_shared_memory.hpp index 654c8bb9f3..4c2ef14dcc 100644 --- a/boost/interprocess/detail/managed_multi_shared_memory.hpp +++ b/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) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_MANAGED_MULTI_SHARED_MEMORY_HPP #define BOOST_INTERPROCESS_MANAGED_MULTI_SHARED_MEMORY_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -36,7 +36,7 @@ #include <boost/assert.hpp> //These includes needed to fulfill default template parameters of //predeclarations in interprocess_fwd.hpp -#include <boost/interprocess/mem_algo/rbtree_best_fit.hpp> +#include <boost/interprocess/mem_algo/rbtree_best_fit.hpp> #include <boost/interprocess/sync/mutex_family.hpp> //!\file @@ -69,10 +69,10 @@ class basic_managed_multi_shared_memory <CharType, MemoryAlgorithm, IndexType> self_t; typedef ipcdetail::basic_managed_memory_impl <CharType, MemoryAlgorithm, IndexType> base_t; - + typedef typename MemoryAlgorithm::void_pointer void_pointer; typedef typename ipcdetail:: - managed_open_or_create_impl<shared_memory_object, MemoryAlgorithm::Alignment> managed_impl; + managed_open_or_create_impl<shared_memory_object, MemoryAlgorithm::Alignment, true, false> managed_impl; typedef typename void_pointer::segment_group_id segment_group_id; typedef typename base_t::size_type size_type; @@ -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<void *>(0), 0); + return result_type(static_cast<void *>(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; @@ -211,9 +211,23 @@ class basic_managed_multi_shared_memory } return false; } + + std::size_t get_min_size() const + { + const size_type sz = mp_frontend->get_segment_manager()->get_min_size(); + if(sz > std::size_t(-1)){ + //The minimum size is not representable by std::size_t + BOOST_ASSERT(false); + return std::size_t(-1); + } + else{ + return static_cast<std::size_t>(sz); + } + } + self_t * const mp_frontend; type_t m_type; - size_type m_segment_number; + size_type m_segment_number; }; //!Functor to execute atomically when closing a shared memory segment. @@ -226,7 +240,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 +265,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 +315,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 +382,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 +399,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/boost/interprocess/detail/managed_open_or_create_impl.hpp b/boost/interprocess/detail/managed_open_or_create_impl.hpp index a4f1f15817..bd08be56d3 100644 --- a/boost/interprocess/detail/managed_open_or_create_impl.hpp +++ b/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) // @@ -11,6 +11,10 @@ #ifndef BOOST_INTERPROCESS_MANAGED_OPEN_OR_CREATE_IMPL #define BOOST_INTERPROCESS_MANAGED_OPEN_OR_CREATE_IMPL +#if defined(_MSC_VER) +# pragma once +#endif + #include <boost/interprocess/detail/config_begin.hpp> #include <boost/interprocess/detail/os_thread_functions.hpp> #include <boost/interprocess/detail/os_file_functions.hpp> @@ -25,13 +29,14 @@ #include <boost/interprocess/permissions.hpp> #include <boost/type_traits/alignment_of.hpp> #include <boost/type_traits/type_with_alignment.hpp> +#include <boost/interprocess/sync/spin/wait.hpp> #include <boost/move/move.hpp> #include <boost/cstdint.hpp> namespace boost { namespace interprocess { -/// @cond +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) namespace ipcdetail{ class interprocess_tester; } @@ -48,13 +53,13 @@ class xsi_key; template<> struct managed_open_or_create_impl_device_id_t<xsi_shared_memory_file_wrapper> -{ +{ typedef xsi_key type; }; #endif //BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS - -/// @endcond + +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED namespace ipcdetail { @@ -79,12 +84,12 @@ class managed_open_or_create_impl_device_holder<true, DeviceAbstraction> const DeviceAbstraction &get_device() const { return dev; } - + private: DeviceAbstraction dev; }; -template<class DeviceAbstraction, std::size_t MemAlignment = 0, bool FileBased = true, bool StoreDevice = true> +template<class DeviceAbstraction, std::size_t MemAlignment, bool FileBased, bool StoreDevice> class managed_open_or_create_impl : public managed_open_or_create_impl_device_holder<StoreDevice, DeviceAbstraction> { @@ -94,9 +99,9 @@ class managed_open_or_create_impl typedef typename managed_open_or_create_impl_device_id_t<DeviceAbstraction>::type device_id_t; typedef managed_open_or_create_impl_device_holder<StoreDevice, DeviceAbstraction> DevHolder; enum - { - UninitializedSegment, - InitializingSegment, + { + UninitializedSegment, + InitializingSegment, InitializedSegment, CorruptedSegment }; @@ -222,10 +227,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() @@ -309,14 +314,18 @@ class managed_open_or_create_impl { typedef bool_<FileBased> file_like_t; (void)mode; - error_info err; bool created = false; bool ronly = false; bool cow = false; DeviceAbstraction dev; - if(type != DoOpen && size < ManagedOpenOrCreateUserOffset){ - throw interprocess_exception(error_info(size_error)); + if(type != DoOpen){ + //Check if the requested size is enough to build the managed metadata + const std::size_t func_min_size = construct_func.get_min_size(); + if( (std::size_t(-1) - ManagedOpenOrCreateUserOffset) < func_min_size || + size < (func_min_size + ManagedOpenOrCreateUserOffset) ){ + throw interprocess_exception(error_info(size_error)); + } } //Check size can be represented by offset_t (used by truncate) if(type != DoOpen && !check_offset_t_size<FileBased>(size, file_like_t())){ @@ -349,6 +358,7 @@ class managed_open_or_create_impl //file and know if we have really created it or just open it //drop me a e-mail! bool completed = false; + spin_wait swait; while(!completed){ try{ create_device<FileBased>(dev, id, size, perm, file_like_t()); @@ -366,8 +376,8 @@ class managed_open_or_create_impl created = false; completed = true; } - catch(interprocess_exception &ex){ - if(ex.get_error_code() != not_found_error){ + catch(interprocess_exception &e){ + if(e.get_error_code() != not_found_error){ throw; } } @@ -379,7 +389,7 @@ class managed_open_or_create_impl catch(...){ throw; } - thread_yield(); + swait.yield(); } } @@ -426,11 +436,13 @@ class managed_open_or_create_impl else{ if(FileBased){ offset_t filesize = 0; + spin_wait swait; while(filesize == 0){ if(!get_file_size(file_handle_from_mapping_handle(dev.get_mapping_handle()), filesize)){ - throw interprocess_exception(error_info(system_error_code())); + error_info err = system_error_code(); + throw interprocess_exception(err); } - thread_yield(); + swait.yield(); } if(filesize == 1){ throw interprocess_exception(error_info(corrupted_error)); @@ -442,8 +454,9 @@ class managed_open_or_create_impl boost::uint32_t *patomic_word = static_cast<boost::uint32_t*>(region.get_address()); boost::uint32_t value = atomic_read32(patomic_word); + spin_wait swait; while(value == InitializingSegment || value == UninitializedSegment){ - thread_yield(); + swait.yield(); value = atomic_read32(patomic_word); } @@ -461,6 +474,11 @@ class managed_open_or_create_impl } } + friend void swap(managed_open_or_create_impl &left, managed_open_or_create_impl &right) + { + left.swap(right); + } + private: friend class interprocess_tester; void dont_close_on_destruction() @@ -469,11 +487,6 @@ class managed_open_or_create_impl mapped_region m_mapped_region; }; -template<class DeviceAbstraction> -inline void swap(managed_open_or_create_impl<DeviceAbstraction> &x - ,managed_open_or_create_impl<DeviceAbstraction> &y) -{ x.swap(y); } - } //namespace ipcdetail { } //namespace interprocess { diff --git a/boost/interprocess/detail/math_functions.hpp b/boost/interprocess/detail/math_functions.hpp index 2fc457c683..3826f161e2 100644 --- a/boost/interprocess/detail/math_functions.hpp +++ b/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 @@ -16,6 +16,10 @@ #ifndef BOOST_INTERPROCESS_DETAIL_MATH_FUNCTIONS_HPP #define BOOST_INTERPROCESS_DETAIL_MATH_FUNCTIONS_HPP +#if defined(_MSC_VER) +# pragma once +#endif + #include <climits> #include <boost/static_assert.hpp> @@ -93,7 +97,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/boost/interprocess/detail/min_max.hpp b/boost/interprocess/detail/min_max.hpp index 1f4ebdfc33..a5d01f404b 100644 --- a/boost/interprocess/detail/min_max.hpp +++ b/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 @@ -13,7 +13,7 @@ #ifndef BOOST_INTERPROCESS_DETAIL_MIN_MAX_HPP #define BOOST_INTERPROCESS_DETAIL_MIN_MAX_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/boost/interprocess/detail/move.hpp b/boost/interprocess/detail/move.hpp index 1ec43b211b..22df7bd771 100644 --- a/boost/interprocess/detail/move.hpp +++ b/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) @@ -14,7 +14,11 @@ #ifndef BOOST_INTERPROCESS_DETAIL_MOVE_HPP #define BOOST_INTERPROCESS_DETAIL_MOVE_HPP -#include <boost/move/move.hpp> +#if defined(_MSC_VER) +# pragma once +#endif + +#include <boost/move/utility_core.hpp> namespace boost { namespace interprocess { diff --git a/boost/interprocess/detail/mpl.hpp b/boost/interprocess/detail/mpl.hpp index e2c7f52d24..29f3893038 100644 --- a/boost/interprocess/detail/mpl.hpp +++ b/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 @@ -13,7 +13,7 @@ #ifndef BOOST_INTERPROCESS_DETAIL_MPL_HPP #define BOOST_INTERPROCESS_DETAIL_MPL_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/boost/interprocess/detail/multi_segment_services.hpp b/boost/interprocess/detail/multi_segment_services.hpp index d1451d3379..dd9d5f82fd 100644 --- a/boost/interprocess/detail/multi_segment_services.hpp +++ b/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) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_MULTI_SEGMENT_SERVICES_HPP #define BOOST_INTERPROCESS_MULTI_SEGMENT_SERVICES_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/boost/interprocess/detail/named_proxy.hpp b/boost/interprocess/detail/named_proxy.hpp index c2aafed9ac..ee6668c2d5 100644 --- a/boost/interprocess/detail/named_proxy.hpp +++ b/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) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_NAMED_PROXY_HPP #define BOOST_INTERPROCESS_NAMED_PROXY_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -26,7 +26,7 @@ #ifndef BOOST_INTERPROCESS_PERFECT_FORWARDING #include <boost/interprocess/detail/preprocessor.hpp> #else -#include <boost/move/move.hpp> +#include <boost/move/utility_core.hpp> #include <boost/interprocess/detail/variadic_templates_tools.hpp> #endif //#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING @@ -93,7 +93,7 @@ struct CtorNArg : public placement_destroy<T> {} tuple<Args&...> args_; -}; +}; //!Describes a proxy class that implements named //!allocation syntax. @@ -119,7 +119,7 @@ class named_proxy template<class ...Args> T *operator()(Args &&...args) const - { + { CtorNArg<T, is_iterator, Args...> &&ctor_obj = CtorNArg<T, is_iterator, Args...> (boost::forward<Args>(args)...); return mp_mngr->template @@ -199,7 +199,7 @@ struct Ctor0Arg : public placement_destroy<T> // 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<T> ctor_obj; return mp_mngr->template generic_construct<T>(mp_name, m_num, m_find, m_dothrow, ctor_obj); diff --git a/boost/interprocess/detail/os_file_functions.hpp b/boost/interprocess/detail/os_file_functions.hpp index 08decd9bc4..1b54807ab1 100644 --- a/boost/interprocess/detail/os_file_functions.hpp +++ b/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) // @@ -11,6 +11,10 @@ #ifndef BOOST_INTERPROCESS_DETAIL_OS_FILE_FUNCTIONS_HPP #define BOOST_INTERPROCESS_DETAIL_OS_FILE_FUNCTIONS_HPP +#if defined(_MSC_VER) +# pragma once +#endif + #include <boost/interprocess/detail/config_begin.hpp> #include <boost/interprocess/detail/workaround.hpp> #include <boost/interprocess/errors.hpp> @@ -19,8 +23,9 @@ #include <string> #include <limits> #include <climits> +#include <boost/type_traits/make_unsigned.hpp> -#if (defined BOOST_INTERPROCESS_WINDOWS) +#if defined (BOOST_INTERPROCESS_WINDOWS) # include <boost/interprocess/detail/win32_api.hpp> #else # ifdef BOOST_HAS_UNISTD_H @@ -45,7 +50,7 @@ namespace boost { namespace interprocess { -#if (defined BOOST_INTERPROCESS_WINDOWS) +#if defined (BOOST_INTERPROCESS_WINDOWS) typedef void * file_handle_t; typedef long long offset_t; @@ -66,6 +71,9 @@ typedef enum { file_begin = winapi::file_begin , file_current = winapi::file_current } file_pos_t; +typedef unsigned long map_options_t; +static const map_options_t default_map_options = map_options_t(-1); + namespace ipcdetail{ inline mapping_handle_t mapping_handle_from_file_handle(file_handle_t hnd) @@ -90,34 +98,47 @@ inline file_handle_t file_handle_from_mapping_handle(mapping_handle_t hnd) inline bool create_directory(const char *path) { return winapi::create_directory(path); } -inline const char *get_temporary_path() -{ return std::getenv("TMP"); } - +inline bool get_temporary_path(char *buffer, std::size_t buf_len, std::size_t &required_len) +{ + required_len = 0; + //std::size_t is always bigger or equal than unsigned long in Windows systems + //In case std::size_t is bigger than unsigned long + unsigned long buf = buf_len; + if(buf_len != buf){ //maybe overflowed + return false; + } + required_len = winapi::get_temp_path(buf_len, buffer); + const bool ret = !(buf_len < required_len); + if(ret && buffer[required_len-1] == '\\'){ + buffer[required_len-1] = 0; + } + return ret; +} 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) @@ -129,10 +150,10 @@ inline bool truncate_file (file_handle_t hnd, std::size_t size) if(!winapi::get_file_size(hnd, filesize)) return false; - const offset_t max_filesize = (std::numeric_limits<offset_t>::max)(); + typedef boost::make_unsigned<offset_t>::type uoffset_t; + const uoffset_t max_filesize = uoffset_t((std::numeric_limits<offset_t>::max)()); //Avoid unused variable warnings in 32 bit systems - (void)max_filesize; - if( sizeof(std::size_t) >= sizeof(offset_t) && size > std::size_t(max_filesize) ){ + if(uoffset_t(size) > max_filesize){ winapi::set_last_error(winapi::error_file_too_large); return false; } @@ -177,7 +198,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 +210,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 +220,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 +229,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 @@ -253,7 +274,7 @@ inline bool delete_subdirectories_recursive void * hFile; // Handle to directory std::string strFilePath; // Filepath std::string strPattern; // Pattern - winapi::win32_find_data_t FileInformation; // File information + winapi::win32_find_data FileInformation; // File information //Find all files and directories strPattern = refcstrRootDirectory + "\\*.*"; @@ -269,8 +290,10 @@ inline bool delete_subdirectories_recursive //If it's a directory, go recursive if(FileInformation.dwFileAttributes & winapi::file_attribute_directory){ // Delete subdirectory - if(!delete_subdirectories_recursive(strFilePath, dont_delete_this, count+1)) + if(!delete_subdirectories_recursive(strFilePath, dont_delete_this, count+1)){ + winapi::find_close(hFile); return false; + } } //If it's a file, just delete it else{ @@ -278,7 +301,7 @@ inline bool delete_subdirectories_recursive //if(::SetFileAttributes(strFilePath.c_str(), winapi::file_attribute_normal) == 0) //return winapi::get_last_error(); // Delete file - winapi::delete_file(strFilePath.c_str()); + winapi::unlink_file(strFilePath.c_str()); } } //Go to the next file @@ -319,7 +342,7 @@ template<class Function> inline bool for_each_file_in_dir(const char *dir, Function f) { void * hFile; // Handle to directory - winapi::win32_find_data_t FileInformation; // File information + winapi::win32_find_data FileInformation; // File information //Get base directory std::string str(dir); @@ -352,7 +375,7 @@ inline bool for_each_file_in_dir(const char *dir, Function f) } -#else //#if (defined BOOST_INTERPROCESS_WINDOWS) +#else //#if defined (BOOST_INTERPROCESS_WINDOWS) typedef int file_handle_t; typedef off_t offset_t; @@ -375,6 +398,9 @@ typedef enum { file_begin = SEEK_SET , file_current = SEEK_CUR } file_pos_t; +typedef int map_options_t; +static const map_options_t default_map_options = map_options_t(-1); + namespace ipcdetail{ inline mapping_handle_t mapping_handle_from_file_handle(file_handle_t hnd) @@ -391,22 +417,20 @@ inline file_handle_t file_handle_from_mapping_handle(mapping_handle_t hnd) inline bool create_directory(const char *path) { return ::mkdir(path, 0777) == 0 && ::chmod(path, 0777) == 0; } -inline const char *get_temporary_path() +inline bool get_temporary_path(char *buffer, std::size_t buf_len, std::size_t &required_len) { - const char *names[] = {"/tmp", "TMPDIR", "TMP", "TEMP" }; - const int names_size = sizeof(names)/sizeof(names[0]); - struct stat data; - for(int i = 0; i != names_size; ++i){ - if(::stat(names[i], &data) == 0){ - return names[i]; - } + required_len = 5u; + if(buf_len < required_len) + return false; + else{ + std::strcpy(buffer, "/tmp"); } - return "/tmp"; + return true; } 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){ @@ -433,13 +457,16 @@ inline file_handle_t create_or_open_file break; } } + else{ + break; + } } return ret; } inline file_handle_t open_existing_file (const char *name, mode_t mode, bool temporary = false) -{ +{ (void)temporary; return ::open(name, (int)mode); } @@ -449,17 +476,16 @@ inline bool delete_file(const char *name) inline bool truncate_file (file_handle_t hnd, std::size_t size) { - if(sizeof(off_t) == sizeof(std::size_t)){ - if(size > ((~std::size_t(0)) >> 1)){ - errno = EINVAL; - return false; - } + typedef boost::make_unsigned<off_t>::type uoff_t; + if(uoff_t((std::numeric_limits<off_t>::max)()) < size){ + errno = EINVAL; + return false; } return 0 == ::ftruncate(hnd, off_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 +498,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 +548,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 +558,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 +627,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; @@ -672,7 +698,7 @@ inline bool delete_subdirectories(const std::string &refcstrRootDirectory, const return delete_subdirectories_recursive(refcstrRootDirectory, dont_delete_this ); } -#endif //#if (defined BOOST_INTERPROCESS_WINDOWS) +#endif //#if defined (BOOST_INTERPROCESS_WINDOWS) inline bool open_or_create_directory(const char *dir_name) { @@ -686,6 +712,18 @@ inline bool open_or_create_directory(const char *dir_name) return true; } +inline std::string get_temporary_path() +{ + std::size_t required_len = 0; + get_temporary_path(0, 0, required_len); + std::string ret_str(required_len, char(0)); + get_temporary_path(&ret_str[0], ret_str.size(), required_len); + while(!ret_str.empty() && !ret_str[ret_str.size()-1]){ + ret_str.erase(ret_str.size()-1); + } + + return ret_str; +} } //namespace ipcdetail{ } //namespace interprocess { diff --git a/boost/interprocess/detail/os_thread_functions.hpp b/boost/interprocess/detail/os_thread_functions.hpp index 8d769fc4e9..4604683645 100644 --- a/boost/interprocess/detail/os_thread_functions.hpp +++ b/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-2013. Distributed under the 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,24 +8,60 @@ // ////////////////////////////////////////////////////////////////////////////// +//Thread launching functions are adapted from boost/detail/lightweight_thread.hpp +// +// boost/detail/lightweight_thread.hpp +// +// Copyright (c) 2002 Peter Dimov and Multi Media Ltd. +// Copyright (c) 2008 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + #ifndef BOOST_INTERPROCESS_DETAIL_OS_THREAD_FUNCTIONS_HPP #define BOOST_INTERPROCESS_DETAIL_OS_THREAD_FUNCTIONS_HPP +#if defined(_MSC_VER) +# pragma once +#endif + #include <boost/interprocess/detail/config_begin.hpp> #include <boost/interprocess/detail/workaround.hpp> #include <boost/interprocess/streams/bufferstream.hpp> #include <boost/interprocess/detail/posix_time_types_wrk.hpp> +#include <cstddef> +#include <memory> -#if (defined BOOST_INTERPROCESS_WINDOWS) +#if defined(BOOST_INTERPROCESS_WINDOWS) # include <boost/interprocess/detail/win32_api.hpp> +# include <process.h> #else -# ifdef BOOST_HAS_UNISTD_H -# include <pthread.h> -# include <unistd.h> -# include <sched.h> -# include <time.h> +# include <pthread.h> +# include <unistd.h> +# include <sched.h> +# include <time.h> +# ifdef BOOST_INTERPROCESS_BSD_DERIVATIVE + //Some *BSD systems (OpenBSD & NetBSD) need sys/param.h before sys/sysctl.h, whereas + //others (FreeBSD & Darwin) need sys/types.h +# include <sys/types.h> +# include <sys/param.h> +# include <sys/sysctl.h> +# endif +//According to the article "C/C++ tip: How to measure elapsed real time for benchmarking" +# if defined(CLOCK_MONOTONIC_PRECISE) //BSD +# define BOOST_INTERPROCESS_CLOCK_MONOTONIC CLOCK_MONOTONIC_PRECISE +# elif defined(CLOCK_MONOTONIC_RAW) //Linux +# define BOOST_INTERPROCESS_CLOCK_MONOTONIC CLOCK_MONOTONIC_RAW +# elif defined(CLOCK_HIGHRES) //Solaris +# define BOOST_INTERPROCESS_CLOCK_MONOTONIC CLOCK_HIGHRES +# elif defined(CLOCK_MONOTONIC) //POSIX (AIX, BSD, Linux, Solaris) +# define BOOST_INTERPROCESS_CLOCK_MONOTONIC CLOCK_MONOTONIC +# elif !defined(CLOCK_MONOTONIC) && (defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)) +# include <mach/mach_time.h> // mach_absolute_time, mach_timebase_info_data_t +# define BOOST_INTERPROCESS_MATCH_ABSOLUTE_TIME # else -# error Unknown platform +# error "No high resolution steady clock in your system, please provide a patch" # endif #endif @@ -33,10 +69,11 @@ namespace boost { namespace interprocess { namespace ipcdetail{ -#if (defined BOOST_INTERPROCESS_WINDOWS) +#if defined (BOOST_INTERPROCESS_WINDOWS) typedef unsigned long OS_process_id_t; typedef unsigned long OS_thread_id_t; +typedef void* OS_thread_t; typedef OS_thread_id_t OS_systemwide_thread_id_t; //process @@ -56,11 +93,83 @@ inline OS_thread_id_t get_invalid_thread_id() inline bool equal_thread_id(OS_thread_id_t id1, OS_thread_id_t id2) { return id1 == id2; } +//return the system tick in ns +inline unsigned long get_system_tick_ns() +{ + unsigned long curres; + winapi::set_timer_resolution(10000, 0, &curres); + //Windows API returns the value in hundreds of ns + return (curres - 1ul)*100ul; +} + +//return the system tick in us +inline unsigned long get_system_tick_us() +{ + unsigned long curres; + winapi::set_timer_resolution(10000, 0, &curres); + //Windows API returns the value in hundreds of ns + return (curres - 1ul)/10ul + 1ul; +} + +typedef unsigned __int64 OS_highres_count_t; + +inline unsigned long get_system_tick_in_highres_counts() +{ + __int64 freq; + unsigned long curres; + winapi::set_timer_resolution(10000, 0, &curres); + //Frequency in counts per second + if(!winapi::query_performance_frequency(&freq)){ + //Tick resolution in ms + return (curres-1ul)/10000ul + 1ul; + } + else{ + //In femtoseconds + __int64 count_fs = (1000000000000000LL - 1LL)/freq + 1LL; + __int64 tick_counts = (static_cast<__int64>(curres)*100000000LL - 1LL)/count_fs + 1LL; + return static_cast<unsigned long>(tick_counts); + } +} + +inline OS_highres_count_t get_current_system_highres_count() +{ + __int64 count; + if(!winapi::query_performance_counter(&count)){ + count = winapi::get_tick_count(); + } + return count; +} + +inline void zero_highres_count(OS_highres_count_t &count) +{ count = 0; } + +inline bool is_highres_count_zero(const OS_highres_count_t &count) +{ return count == 0; } + +template <class Ostream> +inline Ostream &ostream_highres_count(Ostream &ostream, const OS_highres_count_t &count) +{ + ostream << count; + return ostream; +} + +inline OS_highres_count_t system_highres_count_subtract(const OS_highres_count_t &l, const OS_highres_count_t &r) +{ return l - r; } + +inline bool system_highres_count_less(const OS_highres_count_t &l, const OS_highres_count_t &r) +{ return l < r; } + +inline bool system_highres_count_less_ul(const OS_highres_count_t &l, unsigned long r) +{ return l < static_cast<OS_highres_count_t>(r); } + +inline void thread_sleep_tick() +{ winapi::sleep_tick(); } + inline void thread_yield() { winapi::sched_yield(); } inline void thread_sleep(unsigned int ms) -{ winapi::Sleep(ms); } +{ winapi::sleep(ms); } //systemwide thread inline OS_systemwide_thread_id_t get_current_systemwide_thread_id() @@ -88,7 +197,7 @@ inline long double get_current_process_creation_time() { winapi::interprocess_filetime CreationTime, ExitTime, KernelTime, UserTime; - get_process_times + winapi::get_process_times ( winapi::get_current_process(), &CreationTime, &ExitTime, &KernelTime, &UserTime); typedef long double ldouble_t; @@ -97,14 +206,22 @@ inline long double get_current_process_creation_time() CreationTime.dwLowDateTime*resolution; } +inline unsigned int get_num_cores() +{ + winapi::system_info sysinfo; + winapi::get_system_info( &sysinfo ); + //in Windows dw is long which is equal in bits to int + return static_cast<unsigned>(sysinfo.dwNumberOfProcessors); +} -#else //#if (defined BOOST_INTERPROCESS_WINDOWS) +#else //#if defined (BOOST_INTERPROCESS_WINDOWS) +typedef pthread_t OS_thread_t; 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() {} @@ -164,9 +281,135 @@ inline bool equal_thread_id(OS_thread_id_t id1, OS_thread_id_t id2) inline void thread_yield() { ::sched_yield(); } +#ifndef BOOST_INTERPROCESS_MATCH_ABSOLUTE_TIME +typedef struct timespec OS_highres_count_t; +#else +typedef unsigned long long OS_highres_count_t; +#endif + +inline unsigned long get_system_tick_ns() +{ + #ifdef _SC_CLK_TCK + long ticks_per_second =::sysconf(_SC_CLK_TCK); // ticks per sec + if(ticks_per_second <= 0){ //Try a typical value on error + ticks_per_second = 100; + } + return 999999999ul/static_cast<unsigned long>(ticks_per_second)+1ul; + #else + #error "Can't obtain system tick value for your system, please provide a patch" + #endif +} + +inline unsigned long get_system_tick_in_highres_counts() +{ + #ifndef BOOST_INTERPROCESS_MATCH_ABSOLUTE_TIME + return get_system_tick_ns(); + #else + mach_timebase_info_data_t info; + mach_timebase_info(&info); + //ns + return static_cast<unsigned long> + ( + static_cast<double>(get_system_tick_ns()) + / (static_cast<double>(info.numer) / info.denom) + ); + #endif +} + +//return system ticks in us +inline unsigned long get_system_tick_us() +{ + return (get_system_tick_ns()-1)/1000ul + 1ul; +} + +inline OS_highres_count_t get_current_system_highres_count() +{ + #if defined(BOOST_INTERPROCESS_CLOCK_MONOTONIC) + struct timespec count; + ::clock_gettime(BOOST_INTERPROCESS_CLOCK_MONOTONIC, &count); + return count; + #elif defined(BOOST_INTERPROCESS_MATCH_ABSOLUTE_TIME) + return ::mach_absolute_time(); + #endif +} + +#ifndef BOOST_INTERPROCESS_MATCH_ABSOLUTE_TIME + +inline void zero_highres_count(OS_highres_count_t &count) +{ count.tv_sec = 0; count.tv_nsec = 0; } + +inline bool is_highres_count_zero(const OS_highres_count_t &count) +{ return count.tv_sec == 0 && count.tv_nsec == 0; } + +template <class Ostream> +inline Ostream &ostream_highres_count(Ostream &ostream, const OS_highres_count_t &count) +{ + ostream << count.tv_sec << "s:" << count.tv_nsec << "ns"; + return ostream; +} + +inline OS_highres_count_t system_highres_count_subtract(const OS_highres_count_t &l, const OS_highres_count_t &r) +{ + OS_highres_count_t res; + + if (l.tv_nsec < r.tv_nsec){ + res.tv_nsec = 1000000000 + l.tv_nsec - r.tv_nsec; + res.tv_sec = l.tv_sec - 1 - r.tv_sec; + } + else{ + res.tv_nsec = l.tv_nsec - r.tv_nsec; + res.tv_sec = l.tv_sec - r.tv_sec; + } + + return res; +} + +inline bool system_highres_count_less(const OS_highres_count_t &l, const OS_highres_count_t &r) +{ return l.tv_sec < r.tv_sec || (l.tv_sec == r.tv_sec && l.tv_nsec < r.tv_nsec); } + +inline bool system_highres_count_less_ul(const OS_highres_count_t &l, unsigned long r) +{ return !l.tv_sec && (static_cast<unsigned long>(l.tv_nsec) < r); } + +#else + +inline void zero_highres_count(OS_highres_count_t &count) +{ count = 0; } + +inline bool is_highres_count_zero(const OS_highres_count_t &count) +{ return count == 0; } + +template <class Ostream> +inline Ostream &ostream_highres_count(Ostream &ostream, const OS_highres_count_t &count) +{ + ostream << count ; + return ostream; +} + +inline OS_highres_count_t system_highres_count_subtract(const OS_highres_count_t &l, const OS_highres_count_t &r) +{ return l - r; } + +inline bool system_highres_count_less(const OS_highres_count_t &l, const OS_highres_count_t &r) +{ return l < r; } + +inline bool system_highres_count_less_ul(const OS_highres_count_t &l, unsigned long r) +{ return l < static_cast<OS_highres_count_t>(r); } + +#endif + +inline void thread_sleep_tick() +{ + struct timespec rqt; + //Sleep for the half of the tick time + rqt.tv_sec = 0; + rqt.tv_nsec = get_system_tick_ns()/2; + ::nanosleep(&rqt, 0); +} + inline void thread_sleep(unsigned int ms) { - const struct timespec rqt = { ms/1000u, (ms%1000u)*1000000u }; + struct timespec rqt; + rqt.tv_sec = ms/1000u; + rqt.tv_nsec = (ms%1000u)*1000000u; ::nanosleep(&rqt, 0); } @@ -189,7 +432,46 @@ inline OS_systemwide_thread_id_t get_invalid_systemwide_thread_id() inline long double get_current_process_creation_time() { return 0.0L; } -#endif //#if (defined BOOST_INTERPROCESS_WINDOWS) +inline unsigned int get_num_cores() +{ + #ifdef _SC_NPROCESSORS_ONLN + long cores = ::sysconf(_SC_NPROCESSORS_ONLN); + // sysconf returns -1 if the name is invalid, the option does not exist or + // does not have a definite limit. + // if sysconf returns some other negative number, we have no idea + // what is going on. Default to something safe. + if(cores <= 0){ + return 1; + } + //Check for overflow (unlikely) + else if(static_cast<unsigned long>(cores) >= + static_cast<unsigned long>(static_cast<unsigned int>(-1))){ + return static_cast<unsigned int>(-1); + } + else{ + return static_cast<unsigned int>(cores); + } + #elif defined(BOOST_INTERPROCESS_BSD_DERIVATIVE) && defined(HW_NCPU) + int request[2] = { CTL_HW, HW_NCPU }; + int num_cores; + std::size_t result_len = sizeof(num_cores); + if ( (::sysctl (request, 2, &num_cores, &result_len, 0, 0) < 0) || (num_cores <= 0) ){ + //Return a safe value + return 1; + } + else{ + return static_cast<unsigned int>(num_cores); + } + #endif +} + +inline int thread_create(OS_thread_t * thread, void *(*start_routine)(void*), void* arg) +{ return pthread_create(thread, 0, start_routine, arg); } + +inline void thread_join(OS_thread_t thread) +{ (void)pthread_join(thread, 0); } + +#endif //#if defined (BOOST_INTERPROCESS_WINDOWS) typedef char pid_str_t[sizeof(OS_process_id_t)*3+1]; @@ -202,6 +484,111 @@ inline void get_pid_str(pid_str_t &pid_str, OS_process_id_t pid) inline void get_pid_str(pid_str_t &pid_str) { get_pid_str(pid_str, get_current_process_id()); } +#if defined(BOOST_INTERPROCESS_WINDOWS) + +inline int thread_create( OS_thread_t * thread, unsigned (__stdcall * start_routine) (void*), void* arg ) +{ + void* h = (void*)_beginthreadex( 0, 0, start_routine, arg, 0, 0 ); + + if( h != 0 ){ + *thread = h; + return 0; + } + else{ + return 1; + } +} + +inline void thread_join( OS_thread_t thread) +{ + winapi::wait_for_single_object( thread, winapi::infinite_time ); + winapi::close_handle( thread ); +} + +#endif + +class abstract_thread +{ + public: + virtual ~abstract_thread() {} + virtual void run() = 0; +}; + +template<class T> +class os_thread_func_ptr_deleter +{ + public: + explicit os_thread_func_ptr_deleter(T* p) + : m_p(p) + {} + + T *release() + { T *p = m_p; m_p = 0; return p; } + + T *get() const + { return m_p; } + + T *operator ->() const + { return m_p; } + + ~os_thread_func_ptr_deleter() + { delete m_p; } + + private: + T *m_p; +}; + +#if defined(BOOST_INTERPROCESS_WINDOWS) + +inline unsigned __stdcall launch_thread_routine( void * pv ) +{ + os_thread_func_ptr_deleter<abstract_thread> pt( static_cast<abstract_thread *>( pv ) ); + pt->run(); + return 0; +} + +#else + +extern "C" void * launch_thread_routine( void * pv ); + +inline void * launch_thread_routine( void * pv ) +{ + os_thread_func_ptr_deleter<abstract_thread> pt( static_cast<abstract_thread *>( pv ) ); + pt->run(); + return 0; +} + +#endif + +template<class F> +class launch_thread_impl + : public abstract_thread +{ + public: + explicit launch_thread_impl( F f ) + : f_( f ) + {} + + void run() + { f_(); } + + private: + F f_; +}; + +template<class F> +inline int thread_launch( OS_thread_t & pt, F f ) +{ + os_thread_func_ptr_deleter<abstract_thread> p( new launch_thread_impl<F>( f ) ); + + int r = thread_create(&pt, launch_thread_routine, p.get()); + if( r == 0 ){ + p.release(); + } + + return r; +} + } //namespace ipcdetail{ } //namespace interprocess { } //namespace boost { diff --git a/boost/interprocess/detail/pointer_type.hpp b/boost/interprocess/detail/pointer_type.hpp index 549b23fa6c..28b053c2ae 100644 --- a/boost/interprocess/detail/pointer_type.hpp +++ b/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. @@ -14,7 +14,7 @@ #ifndef BOOST_INTERPROCESS_DETAIL_POINTER_TYPE_HPP #define BOOST_INTERPROCESS_DETAIL_POINTER_TYPE_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/boost/interprocess/detail/portable_intermodule_singleton.hpp b/boost/interprocess/detail/portable_intermodule_singleton.hpp index eb2a13e104..80897f2721 100644 --- a/boost/interprocess/detail/portable_intermodule_singleton.hpp +++ b/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) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_PORTABLE_INTERMODULE_SINGLETON_HPP #define BOOST_INTERPROCESS_PORTABLE_INTERMODULE_SINGLETON_HPP -#if defined(_MSC_VER)&&(_MSC_VER>=1200) +#if defined(_MSC_VER) #pragma once #endif @@ -23,7 +23,7 @@ #include <boost/interprocess/shared_memory_object.hpp> #include <boost/interprocess/detail/atomic.hpp> #include <boost/interprocess/detail/os_thread_functions.hpp> -#include <boost/interprocess/detail/tmp_dir_helpers.hpp> +#include <boost/interprocess/detail/shared_dir_helpers.hpp> #include <boost/interprocess/detail/os_file_functions.hpp> #include <boost/interprocess/detail/file_locking_helpers.hpp> #include <boost/assert.hpp> @@ -45,16 +45,17 @@ static void create_tmp_subdir_and_get_pid_based_filepath { //Let's create a lock file for each process gmem that will mark if //the process is alive or not - create_tmp_and_clean_old(s); + create_shared_dir_and_clean_old(s); s += "/"; s += subdir_name; if(!open_or_create_directory(s.c_str())){ - throw interprocess_exception(error_info(system_error_code())); + error_info err = system_error_code(); + throw interprocess_exception(err); } s += "/"; s += file_prefix; if(creation_time){ - std::string sstamp; + std::string sstamp; get_pid_creation_time_str(sstamp); s += sstamp; } @@ -137,7 +138,7 @@ struct thread_safe_global_map_dependant<managed_global_memory> 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_; @@ -187,7 +188,7 @@ struct thread_safe_global_map_dependant<managed_global_memory> static bool remove_old_gmem() { std::string refcstrRootDirectory; - tmp_folder(refcstrRootDirectory); + get_shared_dir(refcstrRootDirectory); refcstrRootDirectory += "/"; refcstrRootDirectory += get_lock_file_subdir_name(); return for_each_file_in_dir(refcstrRootDirectory.c_str(), apply_gmem_erase_logic); @@ -222,11 +223,11 @@ struct thread_safe_global_map_dependant<managed_global_memory> //Create a unique current pid based lock file path create_and_get_singleton_lock_file_path(lck_str); //Open or create and lock file - int fd = open_or_create_and_lock_file(lck_str.c_str()); + int fd_lockfile = open_or_create_and_lock_file(lck_str.c_str()); //If failed, write a bad file descriptor to notify other modules that //something was wrong and unlink shared memory. Mark the function object //to tell caller to retry with another shared memory - if(fd < 0){ + if(fd_lockfile < 0){ this->register_lock_file(GMemMarkToBeRemoved); std::string s; get_map_name(s); @@ -235,7 +236,7 @@ struct thread_safe_global_map_dependant<managed_global_memory> } //If successful, register the file descriptor else{ - this->register_lock_file(fd); + this->register_lock_file(fd_lockfile); } } //If the fd was invalid (maybe a previous try failed) notify caller that @@ -342,7 +343,7 @@ struct thread_safe_global_map_dependant<managed_global_memory> } //namespace intermodule_singleton_helpers { -template<typename C, bool LazyInit = true, bool Phoenix = true> +template<typename C, bool LazyInit = true, bool Phoenix = false> class portable_intermodule_singleton : public intermodule_singleton_impl<C, LazyInit, Phoenix, managed_global_memory> {}; diff --git a/boost/interprocess/detail/posix_time_types_wrk.hpp b/boost/interprocess/detail/posix_time_types_wrk.hpp index e4df85a572..dbde3d1771 100644 --- a/boost/interprocess/detail/posix_time_types_wrk.hpp +++ b/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) // @@ -11,6 +11,10 @@ #ifndef BOOST_INTERPROCESS_POSIX_TIMES_WRK_HPP #define BOOST_INTERPROCESS_POSIX_TIMES_WRK_HPP +#if defined(_MSC_VER) +# pragma once +#endif + //workaround to avoid winsock redefines when using date-time #ifdef _WIN32 diff --git a/boost/interprocess/detail/preprocessor.hpp b/boost/interprocess/detail/preprocessor.hpp index 47b591c901..06d1354ee1 100644 --- a/boost/interprocess/detail/preprocessor.hpp +++ b/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) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_DETAIL_PREPROCESSOR_HPP #define BOOST_INTERPROCESS_DETAIL_PREPROCESSOR_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -35,7 +35,7 @@ //This cast is ugly but it is necessary until "perfect forwarding" //is achieved in C++0x. Meanwhile, if we want to be able to //bind rvalues with non-const references, we have to be ugly -#ifndef BOOST_NO_RVALUE_REFERENCES +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES #define BOOST_INTERPROCESS_PP_PARAM_LIST(z, n, data) \ BOOST_PP_CAT(P, n) && BOOST_PP_CAT(p, n) \ //! @@ -45,7 +45,7 @@ //! #endif -#ifndef BOOST_NO_RVALUE_REFERENCES +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES #define BOOST_INTERPROCESS_PP_PARAM(U, u) \ U && u \ //! @@ -55,80 +55,144 @@ //! #endif -#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) +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES #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 +#else //#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES #define BOOST_INTERPROCESS_PP_PARAM_INIT(z, n, data) \ BOOST_PP_CAT(m_p, n) (const_cast<BOOST_PP_CAT(P, n) &>(BOOST_PP_CAT(p, n))) \ //! #endif -#define BOOST_INTERPROCESS_PP_PARAM_INC(z, n, data) \ - BOOST_PP_CAT(++m_p, n) \ -//! - -#ifndef BOOST_NO_RVALUE_REFERENCES +#ifndef BOOST_NO_CXX11_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<class T> + struct ref_holder; + + template<class T> + struct ref_holder<T &> + { + ref_holder(T &t) + : t_(t) + {} + T &t_; + T & get() { return t_; } + T & get_lvalue() { return t_; } + }; + + template<class T> + struct ref_holder<const T> + { + ref_holder(const T &t) + : t_(t) + {} + const T &t_; + const T & get() { return t_; } + const T & get_lvalue() { return t_; } + }; + + template<class T> + struct ref_holder<const T &&> + { + ref_holder(const T &t) + : t_(t) + {} + const T &t_; + const T & get() { return t_; } + const T & get_lvalue() { return t_; } + }; + + template<class T> + struct ref_holder + { + ref_holder(T &&t) + : t_(t) + {} + T &t_; + T && get() { return ::boost::move(t_); } + T & get_lvalue() { return t_; } + }; + + template<class T> + struct ref_holder<T &&> + { + 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(P, n)> 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); \ -//! - -#endif //defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG) - + #define BOOST_INTERPROCESS_PP_PARAM_INC(z, n, data) \ + BOOST_PP_CAT(++m_p, n) \ + //! -#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) \ ::boost::forward< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(p, n) ) \ //! -#if !defined(BOOST_NO_RVALUE_REFERENCES) && defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG) +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG) -#include <boost/container/detail/stored_ref.hpp> + #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) ) \ + //! -#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) \ + //! -#define BOOST_INTERPROCESS_PP_MEMBER_IT_FORWARD(z, n, data) \ -BOOST_PP_CAT(*m_p, n) \ -//! + +#endif //!defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG) #include <boost/interprocess/detail/config_end.hpp> diff --git a/boost/interprocess/detail/ptime_wrk.hpp b/boost/interprocess/detail/ptime_wrk.hpp index 8cda3a445d..87f05e25c2 100644 --- a/boost/interprocess/detail/ptime_wrk.hpp +++ b/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) // @@ -11,6 +11,10 @@ #ifndef BOOST_INTERPROCESS_PTIME_WRK_HPP #define BOOST_INTERPROCESS_PTIME_WRK_HPP +#if defined(_MSC_VER) +# pragma once +#endif + //workaround to avoid winsock redefines when using date-time #ifdef _WIN32 diff --git a/boost/interprocess/detail/robust_emulation.hpp b/boost/interprocess/detail/robust_emulation.hpp index 1feb42dc35..d586db5071 100644 --- a/boost/interprocess/detail/robust_emulation.hpp +++ b/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) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_ROBUST_EMULATION_HPP #define BOOST_INTERPROCESS_ROBUST_EMULATION_HPP -#if defined(_MSC_VER)&&(_MSC_VER>=1200) +#if defined(_MSC_VER) #pragma once #endif @@ -21,9 +21,12 @@ #include <boost/interprocess/sync/interprocess_recursive_mutex.hpp> #include <boost/interprocess/detail/atomic.hpp> #include <boost/interprocess/detail/os_file_functions.hpp> -#include <boost/interprocess/detail/tmp_dir_helpers.hpp> +#include <boost/interprocess/detail/shared_dir_helpers.hpp> #include <boost/interprocess/detail/intermodule_singleton.hpp> +#include <boost/interprocess/detail/portable_intermodule_singleton.hpp> #include <boost/interprocess/exceptions.hpp> +#include <boost/interprocess/sync/spin/wait.hpp> +#include <boost/interprocess/sync/detail/common_algorithms.hpp> #include <string> namespace boost{ @@ -61,7 +64,7 @@ inline const char *robust_lock_prefix() inline void robust_lock_path(std::string &s) { - tmp_folder(s); + get_shared_dir(s); s += "/"; s += robust_lock_subdir_path(); } @@ -132,7 +135,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() { @@ -197,8 +200,8 @@ class robust_spin_mutex bool lock_own_unique_file(); bool robust_check(); bool check_if_owner_dead_and_take_ownership_atomically(); - bool is_owner_dead(boost::uint32_t owner); - void owner_to_filename(boost::uint32_t owner, std::string &s); + bool is_owner_dead(boost::uint32_t own); + void owner_to_filename(boost::uint32_t own, std::string &s); //The real mutex Mutex mtx; //The pid of the owner @@ -214,42 +217,7 @@ inline robust_spin_mutex<Mutex>::robust_spin_mutex() template<class Mutex> inline void robust_spin_mutex<Mutex>::lock() -{ - //If the mutex is broken (recovery didn't call consistent()), - //then throw an exception - if(atomic_read32(&this->state) == broken_state){ - throw interprocess_exception(lock_error, "Broken id"); - } - - //This function provokes intermodule_singleton instantiation - if(!this->lock_own_unique_file()){ - throw interprocess_exception(lock_error, "Broken id"); - } - - //Now the logic. Try to lock, if successful mark the owner - //if it fails, start recovery logic - unsigned int spin_count = 0; - while(1){ - if (mtx.try_lock()){ - atomic_write32(&this->owner, get_current_process_id()); - break; - } - else{ - //Do the dead owner checking each spin_threshold lock tries - ipcdetail::thread_yield(); - ++spin_count; - if(spin_count > spin_threshold){ - //Check if owner dead and take ownership if possible - if(!this->robust_check()){ - spin_count = 0; - } - else{ - break; - } - } - } - } -} +{ try_based_lock(*this); } template<class Mutex> inline bool robust_spin_mutex<Mutex>::try_lock() @@ -280,38 +248,12 @@ inline bool robust_spin_mutex<Mutex>::try_lock() template<class Mutex> inline bool robust_spin_mutex<Mutex>::timed_lock (const boost::posix_time::ptime &abs_time) -{ - //Same as lock() but with an additional timeout - if(abs_time == boost::posix_time::pos_infin){ - this->lock(); - return true; - } - //Obtain current count and target time - boost::posix_time::ptime now = microsec_clock::universal_time(); - - if(now >= abs_time) - return this->try_lock(); - - do{ - if(this->try_lock()){ - break; - } - now = microsec_clock::universal_time(); - - if(now >= abs_time){ - return this->try_lock(); - } - // relinquish current time slice - ipcdetail::thread_yield(); - }while (true); - - return true; -} +{ return try_based_timed_lock(*this, abs_time); } template<class Mutex> -inline void robust_spin_mutex<Mutex>::owner_to_filename(boost::uint32_t owner, std::string &s) +inline void robust_spin_mutex<Mutex>::owner_to_filename(boost::uint32_t own, std::string &s) { - robust_emulation_helpers::create_and_get_robust_lock_file_path(s, owner); + robust_emulation_helpers::create_and_get_robust_lock_file_path(s, own); } template<class Mutex> @@ -324,7 +266,7 @@ inline bool robust_spin_mutex<Mutex>::robust_check() return false; } atomic_write32(&this->state, fixing_state); - return true; + return true; } template<class Mutex> @@ -349,16 +291,16 @@ inline bool robust_spin_mutex<Mutex>::check_if_owner_dead_and_take_ownership_ato } template<class Mutex> -inline bool robust_spin_mutex<Mutex>::is_owner_dead(boost::uint32_t owner) +inline bool robust_spin_mutex<Mutex>::is_owner_dead(boost::uint32_t own) { //If owner is an invalid id, then it's clear it's dead - if(owner == (boost::uint32_t)get_invalid_process_id()){ + if(own == (boost::uint32_t)get_invalid_process_id()){ return true; } //Obtain the lock filename of the owner field std::string file; - this->owner_to_filename(owner, file); + this->owner_to_filename(own, file); //Now the logic is to open and lock it file_handle_t fhnd = open_existing_file(file.c_str(), read_write); @@ -404,7 +346,7 @@ inline bool robust_spin_mutex<Mutex>::previous_owner_dead() { //Notifies if a owner recovery has been performed in the last lock() return atomic_read32(&this->state) == fixing_state; -}; +} template<class Mutex> inline void robust_spin_mutex<Mutex>::unlock() diff --git a/boost/interprocess/detail/segment_manager_helper.hpp b/boost/interprocess/detail/segment_manager_helper.hpp index 2b715d8f5e..1809a8d91a 100644 --- a/boost/interprocess/detail/segment_manager_helper.hpp +++ b/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) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_SEGMENT_MANAGER_BASE_HPP #define BOOST_INTERPROCESS_SEGMENT_MANAGER_BASE_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -32,6 +32,7 @@ #include <string> //char_traits #include <new> //std::nothrow #include <utility> //std::pair +#include <iterator> //std::iterator_traits #include <boost/assert.hpp> //BOOST_ASSERT #include <functional> //unary_function #ifndef BOOST_NO_EXCEPTIONS @@ -72,7 +73,6 @@ class mem_algo_deallocator { if(m_ptr) m_algo.deallocate(m_ptr); } }; -/// @cond template<class size_type> struct block_header { @@ -81,21 +81,18 @@ struct block_header unsigned char m_value_alignment; unsigned char m_alloc_type_sizeof_char; - block_header(size_type value_bytes - ,size_type value_alignment - ,unsigned char alloc_type - ,std::size_t sizeof_char + block_header(size_type val_bytes + ,size_type val_alignment + ,unsigned char al_type + ,std::size_t szof_char ,std::size_t num_char ) - : m_value_bytes(value_bytes) + : m_value_bytes(val_bytes) , m_num_char((unsigned short)num_char) - , m_value_alignment((unsigned char)value_alignment) - , m_alloc_type_sizeof_char - ( (alloc_type << 5u) | - ((unsigned char)sizeof_char & 0x1F) ) + , m_value_alignment((unsigned char)val_alignment) + , m_alloc_type_sizeof_char( (al_type << 5u) | ((unsigned char)szof_char & 0x1F) ) {}; - template<class T> block_header &operator= (const T& ) { return *this; } @@ -118,7 +115,7 @@ struct block_header { return get_rounded_size ( size_type(sizeof(Header)) - , size_type(::boost::alignment_of<block_header<size_type> >::value)) + , size_type(::boost::alignment_of<block_header<size_type> >::value)) + total_size(); } @@ -130,7 +127,7 @@ struct block_header template<class CharType> CharType *name() const - { + { return const_cast<CharType*>(reinterpret_cast<const CharType*> (reinterpret_cast<const char*>(this) + name_offset())); } @@ -175,7 +172,7 @@ struct block_header { return block_header_from_value(value, sizeof(T), ::boost::alignment_of<T>::value); } static block_header<size_type> *block_header_from_value(const void *value, std::size_t sz, std::size_t algn) - { + { block_header * hdr = const_cast<block_header*> (reinterpret_cast<const block_header*>(reinterpret_cast<const char*>(value) - @@ -189,20 +186,20 @@ struct block_header template<class Header> static block_header<size_type> *from_first_header(Header *header) - { + { block_header<size_type> * hdr = reinterpret_cast<block_header<size_type>*>(reinterpret_cast<char*>(header) + - get_rounded_size(size_type(sizeof(Header)), size_type(::boost::alignment_of<block_header<size_type> >::value))); + get_rounded_size(size_type(sizeof(Header)), size_type(::boost::alignment_of<block_header<size_type> >::value))); //Some sanity checks return hdr; } template<class Header> static Header *to_first_header(block_header<size_type> *bheader) - { + { Header * hdr = reinterpret_cast<Header*>(reinterpret_cast<char*>(bheader) - - get_rounded_size(size_type(sizeof(Header)), size_type(::boost::alignment_of<block_header<size_type> >::value))); + get_rounded_size(size_type(sizeof(Header)), size_type(::boost::alignment_of<block_header<size_type> >::value))); //Some sanity checks return hdr; } @@ -326,6 +323,15 @@ class char_ptr_holder operator const CharType *() { return m_name; } + const CharType *get() const + { return m_name; } + + bool is_unique() const + { return m_name == reinterpret_cast<CharType*>(-1); } + + bool is_anonymous() const + { return m_name == static_cast<CharType*>(0); } + private: const CharType *m_name; }; @@ -350,8 +356,9 @@ struct index_key public: //!Constructor of the key - index_key (const char_type *name, size_type length) - : mp_str(name), m_len(length) {} + index_key (const char_type *nm, size_type length) + : mp_str(nm), m_len(length) + {} //!Less than function for index ordering bool operator < (const index_key & right) const @@ -372,8 +379,8 @@ struct index_key to_raw_pointer(right.mp_str), m_len) == 0; } - void name(const CharT *name) - { mp_str = name; } + void name(const CharT *nm) + { mp_str = nm; } void name_length(size_type len) { m_len = len; } @@ -474,12 +481,12 @@ class segment_manager_iterator_value_adaptor<Iterator, false> template<class Iterator, bool intrusive> struct segment_manager_iterator_transform - : std::unary_function< typename Iterator::value_type + : std::unary_function< typename std::iterator_traits<Iterator>::value_type , segment_manager_iterator_value_adaptor<Iterator, intrusive> > { typedef segment_manager_iterator_value_adaptor<Iterator, intrusive> result_type; - - result_type operator()(const typename Iterator::value_type &arg) const + + result_type operator()(const typename std::iterator_traits<Iterator>::value_type &arg) const { return result_type(arg); } }; diff --git a/boost/interprocess/detail/tmp_dir_helpers.hpp b/boost/interprocess/detail/shared_dir_helpers.hpp index 28e7341406..469ea04ac1 100644 --- a/boost/interprocess/detail/tmp_dir_helpers.hpp +++ b/boost/interprocess/detail/shared_dir_helpers.hpp @@ -1,6 +1,6 @@ ////////////////////////////////////////////////////////////////////////////// // -// (C) Copyright Ion Gaztanaga 2007-2011. Distributed under the Boost +// (C) Copyright Ion Gaztanaga 2007-2014. Distributed under the 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,8 +8,12 @@ // ////////////////////////////////////////////////////////////////////////////// -#ifndef BOOST_INTERPROCESS_DETAIL_TMP_DIR_HELPERS_HPP -#define BOOST_INTERPROCESS_DETAIL_TMP_DIR_HELPERS_HPP +#ifndef BOOST_INTERPROCESS_DETAIL_SHARED_DIR_HELPERS_HPP +#define BOOST_INTERPROCESS_DETAIL_SHARED_DIR_HELPERS_HPP + +#if defined(_MSC_VER) +# pragma once +#endif #include <boost/interprocess/detail/config_begin.hpp> #include <boost/interprocess/detail/workaround.hpp> @@ -33,7 +37,11 @@ namespace ipcdetail { { windows_bootstamp() { - winapi::get_last_bootup_time(stamp); + //Throw if bootstamp not available + if(!winapi::get_last_bootup_time(stamp)){ + error_info err = system_error_code(); + throw interprocess_exception(err); + } } //Use std::string. Even if this will be constructed in shared memory, all //modules/dlls are from this process so internal raw pointers to heap are always valid @@ -58,7 +66,7 @@ namespace ipcdetail { struct ::timeval result; std::size_t result_len = sizeof result; - if (::sysctl (request, 2, &result, &result_len, NULL, 0) < 0) + if (::sysctl (request, 2, &result, &result_len, 0, 0) < 0) return; char bootstamp_str[256]; @@ -90,78 +98,84 @@ namespace ipcdetail { #endif #endif //#if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME) -inline void get_tmp_base_dir(std::string &tmp_name) +inline void get_shared_dir_root(std::string &dir_path) { #if defined (BOOST_INTERPROCESS_WINDOWS) - winapi::get_shared_documents_folder(tmp_name); - if(tmp_name.empty() || !winapi::is_directory(tmp_name.c_str())){ - tmp_name = get_temporary_path(); - } + winapi::get_shared_documents_folder(dir_path); #else - tmp_name = get_temporary_path(); + dir_path = "/tmp"; #endif - if(tmp_name.empty()){ + //We always need this path, so throw on error + if(dir_path.empty()){ error_info err = system_error_code(); throw interprocess_exception(err); } //Remove final null. - tmp_name += "/boost_interprocess"; + dir_path += "/boost_interprocess"; } -inline void tmp_folder(std::string &tmp_name) +inline void get_shared_dir(std::string &shared_dir) { - get_tmp_base_dir(tmp_name); - #if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME) - tmp_name += "/"; - get_bootstamp(tmp_name, true); + #if defined(BOOST_INTERPROCESS_SHARED_DIR_PATH) + shared_dir = BOOST_INTERPROCESS_SHARED_DIR_PATH; + #else + get_shared_dir_root(shared_dir); + #if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME) + shared_dir += "/"; + get_bootstamp(shared_dir, true); + #endif #endif } -inline void tmp_filename(const char *filename, std::string &tmp_name) +inline void shared_filepath(const char *filename, std::string &filepath) { - tmp_folder(tmp_name); - tmp_name += "/"; - tmp_name += filename; + get_shared_dir(filepath); + filepath += "/"; + filepath += filename; } -inline void create_tmp_and_clean_old(std::string &tmp_name) +inline void create_shared_dir_and_clean_old(std::string &shared_dir) { - //First get the temp directory - std::string root_tmp_name; - get_tmp_base_dir(root_tmp_name); - - //If fails, check that it's because already exists - if(!create_directory(root_tmp_name.c_str())){ - error_info info(system_error_code()); - if(info.get_error_code() != already_exists_error){ - throw interprocess_exception(info); - } - } - - #if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME) - tmp_folder(tmp_name); + #if defined(BOOST_INTERPROCESS_SHARED_DIR_PATH) + shared_dir = BOOST_INTERPROCESS_SHARED_DIR_PATH; + #else + //First get the temp directory + std::string root_shared_dir; + get_shared_dir_root(root_shared_dir); //If fails, check that it's because already exists - if(!create_directory(tmp_name.c_str())){ + if(!create_directory(root_shared_dir.c_str())){ error_info info(system_error_code()); if(info.get_error_code() != already_exists_error){ throw interprocess_exception(info); } } - //Now erase all old directories created in the previous boot sessions - std::string subdir = tmp_name; - subdir.erase(0, root_tmp_name.size()+1); - delete_subdirectories(root_tmp_name, subdir.c_str()); - #else - tmp_name = root_tmp_name; + + #if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME) + get_shared_dir(shared_dir); + + //If fails, check that it's because already exists + if(!create_directory(shared_dir.c_str())){ + error_info info(system_error_code()); + if(info.get_error_code() != already_exists_error){ + throw interprocess_exception(info); + } + } + //Now erase all old directories created in the previous boot sessions + std::string subdir = shared_dir; + subdir.erase(0, root_shared_dir.size()+1); + delete_subdirectories(root_shared_dir, subdir.c_str()); + #else + shared_dir = root_shared_dir; + #endif #endif } -inline void create_tmp_and_clean_old_and_get_filename(const char *filename, std::string &tmp_name) +inline void create_shared_dir_cleaning_old_and_get_filepath(const char *filename, std::string &shared_dir) { - create_tmp_and_clean_old(tmp_name); - tmp_name += "/"; - tmp_name += filename; + create_shared_dir_and_clean_old(shared_dir); + shared_dir += "/"; + shared_dir += filename; } inline void add_leading_slash(const char *name, std::string &new_name) @@ -178,4 +192,4 @@ inline void add_leading_slash(const char *name, std::string &new_name) #include <boost/interprocess/detail/config_end.hpp> -#endif //ifndef BOOST_INTERPROCESS_DETAIL_TMP_DIR_HELPERS_HPP +#endif //ifndef BOOST_INTERPROCESS_DETAIL_SHARED_DIR_HELPERS_HPP diff --git a/boost/interprocess/detail/transform_iterator.hpp b/boost/interprocess/detail/transform_iterator.hpp index 922c875d6d..5496d19568 100644 --- a/boost/interprocess/detail/transform_iterator.hpp +++ b/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. @@ -14,7 +14,7 @@ #ifndef BOOST_INTERPROCESS_DETAIL_TRANSFORM_ITERATORS_HPP #define BOOST_INTERPROCESS_DETAIL_TRANSFORM_ITERATORS_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -61,9 +61,9 @@ template <class Iterator, class UnaryFunction> class transform_iterator : public UnaryFunction , public std::iterator - < typename Iterator::iterator_category + < typename std::iterator_traits<Iterator>::iterator_category , typename ipcdetail::remove_reference<typename UnaryFunction::result_type>::type - , typename Iterator::difference_type + , typename std::iterator_traits<Iterator>::difference_type , operator_arrow_proxy<typename UnaryFunction::result_type> , typename UnaryFunction::result_type> { @@ -115,33 +115,33 @@ class transform_iterator friend bool operator>= (const transform_iterator& i, const transform_iterator& i2) { return !(i < i2); } - friend typename Iterator::difference_type operator- (const transform_iterator& i, const transform_iterator& i2) + friend typename std::iterator_traits<Iterator>::difference_type operator- (const transform_iterator& i, const transform_iterator& i2) { return i2.distance_to(i); } //Arithmetic - transform_iterator& operator+=(typename Iterator::difference_type off) + transform_iterator& operator+=(typename std::iterator_traits<Iterator>::difference_type off) { this->advance(off); return *this; } - transform_iterator operator+(typename Iterator::difference_type off) const + transform_iterator operator+(typename std::iterator_traits<Iterator>::difference_type off) const { transform_iterator other(*this); other.advance(off); return other; } - friend transform_iterator operator+(typename Iterator::difference_type off, const transform_iterator& right) + friend transform_iterator operator+(typename std::iterator_traits<Iterator>::difference_type off, const transform_iterator& right) { return right + off; } - transform_iterator& operator-=(typename Iterator::difference_type off) + transform_iterator& operator-=(typename std::iterator_traits<Iterator>::difference_type off) { this->advance(-off); return *this; } - transform_iterator operator-(typename Iterator::difference_type off) const + transform_iterator operator-(typename std::iterator_traits<Iterator>::difference_type off) const { return *this + (-off); } typename UnaryFunction::result_type operator*() const { return dereference(); } - typename UnaryFunction::result_type operator[](typename Iterator::difference_type off) const + typename UnaryFunction::result_type operator[](typename std::iterator_traits<Iterator>::difference_type off) const { return UnaryFunction::operator()(m_it[off]); } operator_arrow_proxy<typename UnaryFunction::result_type> @@ -172,10 +172,10 @@ class transform_iterator typename UnaryFunction::result_type dereference() const { return UnaryFunction::operator()(*m_it); } - void advance(typename Iterator::difference_type n) + void advance(typename std::iterator_traits<Iterator>::difference_type n) { std::advance(m_it, n); } - typename Iterator::difference_type distance_to(const transform_iterator &other)const + typename std::iterator_traits<Iterator>::difference_type distance_to(const transform_iterator &other)const { return std::distance(other.m_it, m_it); } }; diff --git a/boost/interprocess/detail/type_traits.hpp b/boost/interprocess/detail/type_traits.hpp index 7a582fee5c..e56a495754 100644 --- a/boost/interprocess/detail/type_traits.hpp +++ b/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 @@ -13,7 +13,7 @@ #ifndef BOOST_INTERPROCESS_DETAIL_TYPE_TRAITS_HPP #define BOOST_INTERPROCESS_DETAIL_TYPE_TRAITS_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -117,6 +117,12 @@ struct remove_volatile<volatile T> typedef T type; }; +template<class T> +struct remove_const_volatile +{ + typedef typename remove_const<typename remove_volatile<T>::type>::type type; +}; + template <typename T, typename U> struct is_same { @@ -136,6 +142,13 @@ struct is_same static const bool value = sizeof(yes_type) == sizeof(is_same_tester(t,u)); }; +template<class T, class U> +struct is_cv_same +{ + static const bool value = is_same< typename remove_const_volatile<T>::type + , typename remove_const_volatile<U>::type >::value; +}; + } // namespace ipcdetail } //namespace interprocess { } //namespace boost { diff --git a/boost/interprocess/detail/utilities.hpp b/boost/interprocess/detail/utilities.hpp index fcb211fb09..351b76cce4 100644 --- a/boost/interprocess/detail/utilities.hpp +++ b/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. @@ -14,7 +14,7 @@ #ifndef BOOST_INTERPROCESS_DETAIL_UTILITIES_HPP #define BOOST_INTERPROCESS_DETAIL_UTILITIES_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif @@ -22,7 +22,7 @@ #include <boost/interprocess/detail/workaround.hpp> #include <boost/interprocess/interprocess_fwd.hpp> -#include <boost/move/move.hpp> +#include <boost/move/utility_core.hpp> #include <boost/type_traits/has_trivial_destructor.hpp> #include <boost/interprocess/detail/min_max.hpp> #include <boost/interprocess/detail/type_traits.hpp> @@ -30,9 +30,11 @@ #include <boost/interprocess/detail/mpl.hpp> #include <boost/interprocess/containers/version_type.hpp> #include <boost/intrusive/pointer_traits.hpp> -#include <boost/move/move.hpp> +#include <boost/move/utility_core.hpp> +#include <boost/static_assert.hpp> #include <utility> #include <algorithm> +#include <climits> namespace boost { namespace interprocess { @@ -86,7 +88,10 @@ inline SizeType get_truncated_size_po2(SizeType orig_size, SizeType multiple) template <std::size_t OrigSize, std::size_t RoundTo> 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,61 @@ addressof(T& v) &const_cast<char&>(reinterpret_cast<const volatile char &>(v))); } +template<class SizeType> +struct sqrt_size_type_max +{ + static const SizeType value = (SizeType(1) << (sizeof(SizeType)*(CHAR_BIT/2)))-1; +}; + +template<class SizeType> +inline bool multiplication_overflows(SizeType a, SizeType b) +{ + const SizeType sqrt_size_max = sqrt_size_type_max<SizeType>::value; + return //Fast runtime check + ( (a | b) > sqrt_size_max && + //Slow division check + b && a > SizeType(-1)/b + ); +} + +template<std::size_t SztSizeOfType, class SizeType> +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 RawPointer> +class pointer_size_t_caster +{ + public: + BOOST_STATIC_ASSERT(sizeof(std::size_t) == sizeof(void*)); + + explicit pointer_size_t_caster(std::size_t sz) + : m_ptr(reinterpret_cast<RawPointer>(sz)) + {} + + explicit pointer_size_t_caster(RawPointer p) + : m_ptr(p) + {} + + std::size_t size() const + { return reinterpret_cast<std::size_t>(m_ptr); } + + RawPointer pointer() const + { return m_ptr; } + + private: + RawPointer m_ptr; +}; + + +template<class SizeType> +inline bool sum_overflows(SizeType a, SizeType b) +{ return SizeType(-1) - a < b; } + //Anti-exception node eraser template<class Cont> class value_eraser @@ -140,7 +200,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/boost/interprocess/detail/variadic_templates_tools.hpp b/boost/interprocess/detail/variadic_templates_tools.hpp index 482a0056a7..80154e05d2 100644 --- a/boost/interprocess/detail/variadic_templates_tools.hpp +++ b/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) // @@ -11,7 +11,7 @@ #ifndef BOOST_INTERPROCESS_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP #define BOOST_INTERPROCESS_DETAIL_VARIADIC_TEMPLATES_TOOLS_HPP -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#if defined(_MSC_VER) # pragma once #endif diff --git a/boost/interprocess/detail/win32_api.hpp b/boost/interprocess/detail/win32_api.hpp index c53725ca3b..d9d3e70330 100644 --- a/boost/interprocess/detail/win32_api.hpp +++ b/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) // @@ -8,248 +8,154 @@ // ////////////////////////////////////////////////////////////////////////////// -#ifndef BOOST_INTERPROCESS_WIN32_PRIMITIVES_HPP -#define BOOST_INTERPROCESS_WIN32_PRIMITIVES_HPP +#ifndef BOOST_INTERPROCESS_WIN32_API_HPP +#define BOOST_INTERPROCESS_WIN32_API_HPP + +#if defined(_MSC_VER) +# pragma once +#endif #include <boost/interprocess/detail/config_begin.hpp> #include <boost/interprocess/detail/workaround.hpp> #include <boost/date_time/filetime_functions.hpp> #include <cstddef> #include <cstring> -#include <cassert> +#include <cstdlib> +#include <cstdio> + +#include <boost/assert.hpp> #include <string> #include <vector> #include <memory> -#if (defined _MSC_VER) && (_MSC_VER >= 1200) +#ifdef BOOST_USE_WINDOWS_H +#include <windows.h> +#include <Wbemidl.h> +#include <Objbase.h> +#include <Shlobj.h> +#endif + +#if defined(_MSC_VER) # pragma once -# pragma comment( lib, "advapi32.lib" ) +# pragma comment( lib, "Advapi32.lib" ) # pragma comment( lib, "oleaut32.lib" ) # pragma comment( lib, "Ole32.lib" ) # pragma comment( lib, "Psapi.lib" ) +# pragma comment( lib, "Shell32.lib" ) //SHGetSpecialFolderPathA #endif -#if (defined BOOST_INTERPROCESS_WINDOWS) +#if defined (BOOST_INTERPROCESS_WINDOWS) # include <cstdarg> # include <boost/detail/interlocked.hpp> #else # error "This file can only be included in Windows OS" #endif +////////////////////////////////////////////////////////////////////////////// +// +// Declaration of Windows structures or typedefs if BOOST_USE_WINDOWS_H is used +// +////////////////////////////////////////////////////////////////////////////// -//The structures used in Interprocess with the -//same binary interface as windows ones -namespace boost { -namespace interprocess { +namespace boost { +namespace interprocess { namespace winapi { -//Some used constants -static const unsigned long infinite_time = 0xFFFFFFFF; -static const unsigned long error_already_exists = 183L; -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; -//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; -static const unsigned int error_file_too_large = 223u; +//Own defines +static const unsigned long MaxPath = 260; -static const unsigned long semaphore_all_access = (0x000F0000L)|(0x00100000L)|0x3; -static const unsigned long mutex_all_access = (0x000F0000L)|(0x00100000L)|0x0001; +#ifndef BOOST_USE_WINDOWS_H -static const unsigned long page_readonly = 0x02; -static const unsigned long page_readwrite = 0x04; -static const unsigned long page_writecopy = 0x08; +struct GUID_BIPC +{ + unsigned long Data1; + unsigned short Data2; + unsigned short Data3; + unsigned char Data4[8]; +}; -static const unsigned long standard_rights_required = 0x000F0000L; -static const unsigned long section_query = 0x0001; -static const unsigned long section_map_write = 0x0002; -static const unsigned long section_map_read = 0x0004; -static const unsigned long section_map_execute = 0x0008; -static const unsigned long section_extend_size = 0x0010; -static const unsigned long section_all_access = standard_rights_required | - section_query | - section_map_write | - section_map_read | - section_map_execute | - section_extend_size; +#if defined(_MSC_VER) +#pragma warning (push) +#pragma warning (disable : 4201) // nonstandard extension used +#endif -static const unsigned long file_map_copy = section_query; -static const unsigned long file_map_write = section_map_write; -static const unsigned long file_map_read = section_map_read; -static const unsigned long file_map_all_access = section_all_access; -static const unsigned long delete_access = 0x00010000L; -static const unsigned long file_flag_backup_semantics = 0x02000000; -static const long file_flag_delete_on_close = 0x04000000; +struct decimal +{ + unsigned short wReserved; + union { + struct { + unsigned char scale; + unsigned char sign; + }; + unsigned short signscale; + }; + unsigned long Hi32; + union { + struct { + unsigned long Lo32; + unsigned long Mid32; + }; + unsigned __int64 Lo64; + }; +}; -//Native API constants -static const unsigned long file_open_for_backup_intent = 0x00004000; -static const int file_share_valid_flags = 0x00000007; -static const long file_delete_on_close = 0x00001000L; -static const long obj_case_insensitive = 0x00000040L; +typedef unsigned short *bstr; -static const unsigned long movefile_copy_allowed = 0x02; -static const unsigned long movefile_delay_until_reboot = 0x04; -static const unsigned long movefile_replace_existing = 0x01; -static const unsigned long movefile_write_through = 0x08; -static const unsigned long movefile_create_hardlink = 0x10; -static const unsigned long movefile_fail_if_not_trackable = 0x20; -static const unsigned long file_share_read = 0x00000001; -static const unsigned long file_share_write = 0x00000002; -static const unsigned long file_share_delete = 0x00000004; +struct wchar_variant +{ + union + { + struct + { + unsigned short vt; + unsigned short wReserved1; + unsigned short wReserved2; + unsigned short wReserved3; + union + { + bstr bstrVal; + struct + { + void* pvRecord; + void* pRecInfo; + }; + }; + }; + decimal decVal; + }; +}; -static const unsigned long file_attribute_readonly = 0x00000001; -static const unsigned long file_attribute_hidden = 0x00000002; -static const unsigned long file_attribute_system = 0x00000004; -static const unsigned long file_attribute_directory = 0x00000010; -static const unsigned long file_attribute_archive = 0x00000020; -static const unsigned long file_attribute_device = 0x00000040; -static const unsigned long file_attribute_normal = 0x00000080; -static const unsigned long file_attribute_temporary = 0x00000100; +#if defined(_MSC_VER) +#pragma warning (pop) +#endif -static const unsigned long generic_read = 0x80000000L; -static const unsigned long generic_write = 0x40000000L; -static const unsigned long wait_object_0 = 0; -static const unsigned long wait_abandoned = 0x00000080L; -static const unsigned long wait_timeout = 258L; -static const unsigned long wait_failed = (unsigned long)0xFFFFFFFF; -static const unsigned long duplicate_close_source = (unsigned long)0x00000001; -static const unsigned long duplicate_same_access = (unsigned long)0x00000002; -static const unsigned long format_message_allocate_buffer - = (unsigned long)0x00000100; -static const unsigned long format_message_ignore_inserts - = (unsigned long)0x00000200; -static const unsigned long format_message_from_string - = (unsigned long)0x00000400; -static const unsigned long format_message_from_hmodule - = (unsigned long)0x00000800; -static const unsigned long format_message_from_system - = (unsigned long)0x00001000; -static const unsigned long format_message_argument_array - = (unsigned long)0x00002000; -static const unsigned long format_message_max_width_mask - = (unsigned long)0x000000FF; -static const unsigned long lang_neutral = (unsigned long)0x00; -static const unsigned long sublang_default = (unsigned long)0x01; -static const unsigned long invalid_file_size = (unsigned long)0xFFFFFFFF; -static const unsigned long invalid_file_attributes = ((unsigned long)-1); -static void * const invalid_handle_value = ((void*)(long)(-1)); -static const unsigned long file_type_char = 0x0002L; -static const unsigned long file_type_disk = 0x0001L; -static const unsigned long file_type_pipe = 0x0003L; -static const unsigned long file_type_remote = 0x8000L; -static const unsigned long file_type_unknown = 0x0000L; -static const unsigned long create_new = 1; -static const unsigned long create_always = 2; -static const unsigned long open_existing = 3; -static const unsigned long open_always = 4; -static const unsigned long truncate_existing = 5; -static const unsigned long file_begin = 0; -static const unsigned long file_current = 1; -static const unsigned long file_end = 2; -static const unsigned long lockfile_fail_immediately = 1; -static const unsigned long lockfile_exclusive_lock = 2; -static const unsigned long error_lock_violation = 33; -static const unsigned long security_descriptor_revision = 1; -//Own defines -static const long SystemTimeOfDayInfoLength = 48; -static const long BootAndSystemstampLength = 16; -static const long BootstampLength = 8; -static const unsigned long MaxPath = 260; -//Keys -static void * const hkey_local_machine = (void*)(unsigned long*)(long)(0x80000002); -static unsigned long key_query_value = 0x0001; -//COM API -const unsigned long RPC_C_AUTHN_LEVEL_PKT_BIPC = 4; -const unsigned long RPC_C_AUTHN_DEFAULT_BIPC = 0xffffffffL; -const unsigned long RPC_C_AUTHZ_DEFAULT_BIPC = 0xffffffffL; -const unsigned long RPC_C_IMP_LEVEL_IMPERSONATE_BIPC = 3; -const signed long EOAC_NONE_BIPC = 0; -const signed long CLSCTX_INPROC_SERVER_BIPC = 0x1; -const signed long CLSCTX_LOCAL_SERVER_BIPC = 0x4; -const signed long WBEM_FLAG_RETURN_IMMEDIATELY_BIPC = 0x10; -const signed long WBEM_FLAG_RETURN_WHEN_COMPLETE_BIPC = 0x0; -const signed long WBEM_FLAG_FORWARD_ONLY_BIPC = 0x20; -const signed long WBEM_INFINITE_BIPC = 0xffffffffL; -const signed long RPC_E_TOO_LATE_BIPC = 0x80010119L; -const signed long S_OK_BIPC = 0L; -const signed long S_FALSE_BIPC = 1; -const signed long RPC_E_CHANGED_MODE_BIPC = 0x80010106L; -const unsigned long COINIT_APARTMENTTHREADED_BIPC = 0x2; -const unsigned long COINIT_MULTITHREADED_BIPC = 0x0; -const unsigned long COINIT_DISABLE_OLE1DDE_BIPC = 0x4; -const unsigned long COINIT_SPEED_OVER_MEMORY_BIPC = 0x4; -//If the user needs to change default COM initialization model, -//it can define BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL to one of these: -// -// COINIT_APARTMENTTHREADED_BIPC -// COINIT_MULTITHREADED_BIPC -// COINIT_DISABLE_OLE1DDE_BIPC -// COINIT_SPEED_OVER_MEMORY_BIPC -#if !defined(BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL) - #define BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL COINIT_APARTMENTTHREADED_BIPC -#elif (BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL != COINIT_APARTMENTTHREADED_BIPC) &&\ - (BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL != COINIT_MULTITHREADED_BIPC) &&\ - (BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL != COINIT_DISABLE_OLE1DDE_BIPC) &&\ - (BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL != COINIT_SPEED_OVER_MEMORY_BIPC) - #error "Wrong value for BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL macro" -#endif -} //namespace winapi { -} //namespace interprocess { -} //namespace boost { -namespace boost { -namespace interprocess { -namespace winapi { -struct GUID_BIPC -{ - unsigned long Data1; - unsigned short Data2; - unsigned short Data3; - unsigned char Data4[8]; -}; - -const GUID_BIPC CLSID_WbemAdministrativeLocator = - { 0xcb8555cc, 0x9128, 0x11d1, {0xad, 0x9b, 0x00, 0xc0, 0x4f, 0xd8, 0xfd, 0xff}}; - -const GUID_BIPC IID_IUnknown = { 0x00000000, 0x0000, 0x0000, {0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}}; -struct wchar_variant +struct IUnknown_BIPC { - unsigned long long dummy; - union value_t{ - wchar_t *pbstrVal; - unsigned long long dummy; - } value; -}; - - struct IUnknown_BIPC - { - public: - virtual long __stdcall QueryInterface( - /* [in] */ const GUID_BIPC &riid, - /* [iid_is][out] */ void **ppvObject) = 0; - - virtual unsigned long __stdcall AddRef( void) = 0; + public: + virtual long __stdcall QueryInterface( + const GUID_BIPC &riid, // [in] + void **ppvObject) = 0; // [iid_is][out] - 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 { @@ -258,23 +164,23 @@ struct IWbemClassObject_BIPC : public IUnknown_BIPC /* [out] */ void **ppQualSet) = 0; virtual long __stdcall Get( - /* [string][in] */ const wchar_t * wszName, + /* [string][in] */ const bstr wszName, /* [in] */ long lFlags, /* [unique][in][out] */ wchar_variant *pVal, /* [unique][in][out] */ long *pType, /* [unique][in][out] */ long *plFlavor) = 0; virtual long __stdcall Put( - /* [string][in] */ const wchar_t * wszName, + /* [string][in] */ const bstr wszName, /* [in] */ long lFlags, /* [in] */ wchar_variant *pVal, /* [in] */ long Type) = 0; virtual long __stdcall Delete( - /* [string][in] */ const wchar_t * wszName) = 0; + /* [string][in] */ const bstr wszName) = 0; virtual long __stdcall GetNames( - /* [string][in] */ const wchar_t * wszQualifierName, + /* [string][in] */ const bstr wszQualifierName, /* [in] */ long lFlags, /* [in] */ wchar_variant *pQualifierVal, /* [out] */ void * *pNames) = 0; @@ -284,7 +190,7 @@ struct IWbemClassObject_BIPC : public IUnknown_BIPC virtual long __stdcall Next( /* [in] */ long lFlags, - /* [unique][in][out] */ wchar_t * *strName, + /* [unique][in][out] */ bstr *strName, /* [unique][in][out] */ wchar_variant *pVal, /* [unique][in][out] */ long *pType, /* [unique][in][out] */ long *plFlavor) = 0; @@ -292,7 +198,7 @@ struct IWbemClassObject_BIPC : public IUnknown_BIPC virtual long __stdcall EndEnumeration( void) = 0; virtual long __stdcall GetPropertyQualifierSet( - /* [string][in] */ const wchar_t * wszProperty, + /* [string][in] */ const bstr wszProperty, /* [out] */ void **ppQualSet) = 0; virtual long __stdcall Clone( @@ -300,7 +206,7 @@ struct IWbemClassObject_BIPC : public IUnknown_BIPC virtual long __stdcall GetObjectText( /* [in] */ long lFlags, - /* [out] */ wchar_t * *pstrObjectText) = 0; + /* [out] */ bstr *pstrObjectText) = 0; virtual long __stdcall SpawnDerivedClass( /* [in] */ long lFlags, @@ -315,49 +221,48 @@ struct IWbemClassObject_BIPC : public IUnknown_BIPC /* [in] */ IWbemClassObject_BIPC *pCompareTo) = 0; virtual long __stdcall GetPropertyOrigin( - /* [string][in] */ const wchar_t * wszName, - /* [out] */ wchar_t * *pstrClassName) = 0; + /* [string][in] */ const bstr wszName, + /* [out] */ bstr *pstrClassName) = 0; virtual long __stdcall InheritsFrom( - /* [in] */ const wchar_t * strAncestor) = 0; + /* [in] */ const bstr strAncestor) = 0; virtual long __stdcall GetMethod( - /* [string][in] */ const wchar_t * wszName, + /* [string][in] */ const bstr wszName, /* [in] */ long lFlags, /* [out] */ IWbemClassObject_BIPC **ppInSignature, /* [out] */ IWbemClassObject_BIPC **ppOutSignature) = 0; virtual long __stdcall PutMethod( - /* [string][in] */ const wchar_t * wszName, + /* [string][in] */ const bstr wszName, /* [in] */ long lFlags, /* [in] */ IWbemClassObject_BIPC *pInSignature, /* [in] */ IWbemClassObject_BIPC *pOutSignature) = 0; virtual long __stdcall DeleteMethod( - /* [string][in] */ const wchar_t * wszName) = 0; + /* [string][in] */ const bstr wszName) = 0; virtual long __stdcall BeginMethodEnumeration( /* [in] */ long lEnumFlags) = 0; virtual long __stdcall NextMethod( /* [in] */ long lFlags, - /* [unique][in][out] */ wchar_t * *pstrName, + /* [unique][in][out] */ bstr *pstrName, /* [unique][in][out] */ IWbemClassObject_BIPC **ppInSignature, /* [unique][in][out] */ IWbemClassObject_BIPC **ppOutSignature) = 0; virtual long __stdcall EndMethodEnumeration( void) = 0; virtual long __stdcall GetMethodQualifierSet( - /* [string][in] */ const wchar_t * wszMethod, + /* [string][in] */ const bstr wszMethod, /* [out] */ void **ppQualSet) = 0; virtual long __stdcall GetMethodOrigin( - /* [string][in] */ const wchar_t * wszMethodName, - /* [out] */ wchar_t * *pstrClassName) = 0; + /* [string][in] */ const bstr wszMethodName, + /* [out] */ bstr *pstrClassName) = 0; }; - struct IWbemContext_BIPC : public IUnknown_BIPC { public: @@ -373,23 +278,23 @@ public: virtual long __stdcall Next( /* [in] */ long lFlags, - /* [out] */ wchar_t * *pstrName, + /* [out] */ bstr *pstrName, /* [out] */ wchar_variant *pValue) = 0; virtual long __stdcall EndEnumeration( void) = 0; virtual long __stdcall SetValue( - /* [string][in] */ const wchar_t * wszName, + /* [string][in] */ const bstr wszName, /* [in] */ long lFlags, /* [in] */ wchar_variant *pValue) = 0; virtual long __stdcall GetValue( - /* [string][in] */ const wchar_t * wszName, + /* [string][in] */ const bstr wszName, /* [in] */ long lFlags, /* [out] */ wchar_variant *pValue) = 0; virtual long __stdcall DeleteValue( - /* [string][in] */ const wchar_t * wszName, + /* [string][in] */ const bstr wszName, /* [in] */ long lFlags) = 0; virtual long __stdcall DeleteAll( void) = 0; @@ -425,7 +330,7 @@ struct IWbemServices_BIPC : public IUnknown_BIPC { public: virtual long __stdcall OpenNamespace( - /* [in] */ const wchar_t * strNamespace, + /* [in] */ const bstr strNamespace, /* [in] */ long lFlags, /* [in] */ void *pCtx, /* [unique][in][out] */ void **ppWorkingNamespace, @@ -439,14 +344,14 @@ public: /* [out] */ void **ppResponseHandler) = 0; virtual long __stdcall GetObject( - /* [in] */ const wchar_t * strObjectPath, + /* [in] */ const bstr strObjectPath, /* [in] */ long lFlags, /* [in] */ void *pCtx, /* [unique][in][out] */ void **ppObject, /* [unique][in][out] */ void **ppCallResult) = 0; virtual long __stdcall GetObjectAsync( - /* [in] */ const wchar_t * strObjectPath, + /* [in] */ const bstr strObjectPath, /* [in] */ long lFlags, /* [in] */ void *pCtx, /* [in] */ void *pResponseHandler) = 0; @@ -464,25 +369,25 @@ public: /* [in] */ void *pResponseHandler) = 0; virtual long __stdcall DeleteClass( - /* [in] */ const wchar_t * strClass, + /* [in] */ const bstr strClass, /* [in] */ long lFlags, /* [in] */ void *pCtx, /* [unique][in][out] */ void **ppCallResult) = 0; virtual long __stdcall DeleteClassAsync( - /* [in] */ const wchar_t * strClass, + /* [in] */ const bstr strClass, /* [in] */ long lFlags, /* [in] */ void *pCtx, /* [in] */ void *pResponseHandler) = 0; virtual long __stdcall CreateClassEnum( - /* [in] */ const wchar_t * strSuperclass, + /* [in] */ const bstr strSuperclass, /* [in] */ long lFlags, /* [in] */ void *pCtx, /* [out] */ void **ppEnum) = 0; virtual long __stdcall CreateClassEnumAsync( - /* [in] */ const wchar_t * strSuperclass, + /* [in] */ const bstr strSuperclass, /* [in] */ long lFlags, /* [in] */ void *pCtx, /* [in] */ void *pResponseHandler) = 0; @@ -500,60 +405,60 @@ public: /* [in] */ void *pResponseHandler) = 0; virtual long __stdcall DeleteInstance( - /* [in] */ const wchar_t * strObjectPath, + /* [in] */ const bstr strObjectPath, /* [in] */ long lFlags, /* [in] */ void *pCtx, /* [unique][in][out] */ void **ppCallResult) = 0; virtual long __stdcall DeleteInstanceAsync( - /* [in] */ const wchar_t * strObjectPath, + /* [in] */ const bstr strObjectPath, /* [in] */ long lFlags, /* [in] */ void *pCtx, /* [in] */ void *pResponseHandler) = 0; virtual long __stdcall CreateInstanceEnum( - /* [in] */ const wchar_t * strFilter, + /* [in] */ const bstr strFilter, /* [in] */ long lFlags, /* [in] */ void *pCtx, /* [out] */ void **ppEnum) = 0; virtual long __stdcall CreateInstanceEnumAsync( - /* [in] */ const wchar_t * strFilter, + /* [in] */ const bstr strFilter, /* [in] */ long lFlags, /* [in] */ void *pCtx, /* [in] */ void *pResponseHandler) = 0; virtual long __stdcall ExecQuery( - /* [in] */ const wchar_t * strQueryLanguage, - /* [in] */ const wchar_t * strQuery, + /* [in] */ const bstr strQueryLanguage, + /* [in] */ const bstr strQuery, /* [in] */ long lFlags, /* [in] */ IWbemContext_BIPC *pCtx, /* [out] */ IEnumWbemClassObject_BIPC **ppEnum) = 0; virtual long __stdcall ExecQueryAsync( - /* [in] */ const wchar_t * strQueryLanguage, - /* [in] */ const wchar_t * strQuery, + /* [in] */ const bstr strQueryLanguage, + /* [in] */ const bstr strQuery, /* [in] */ long lFlags, /* [in] */ IWbemContext_BIPC *pCtx, /* [in] */ void *pResponseHandler) = 0; virtual long __stdcall ExecNotificationQuery( - /* [in] */ const wchar_t * strQueryLanguage, - /* [in] */ const wchar_t * strQuery, + /* [in] */ const bstr strQueryLanguage, + /* [in] */ const bstr strQuery, /* [in] */ long lFlags, /* [in] */ IWbemContext_BIPC *pCtx, /* [out] */ void **ppEnum) = 0; virtual long __stdcall ExecNotificationQueryAsync( - /* [in] */ const wchar_t * strQueryLanguage, - /* [in] */ const wchar_t * strQuery, + /* [in] */ const bstr strQueryLanguage, + /* [in] */ const bstr strQuery, /* [in] */ long lFlags, /* [in] */ IWbemContext_BIPC *pCtx, /* [in] */ void *pResponseHandler) = 0; virtual long __stdcall ExecMethod( - /* [in] */ const wchar_t * strObjectPath, - /* [in] */ const wchar_t * strMethodName, + /* [in] */ const bstr strObjectPath, + /* [in] */ const bstr strMethodName, /* [in] */ long lFlags, /* [in] */ IWbemContext_BIPC *pCtx, /* [in] */ IWbemClassObject_BIPC *pInParams, @@ -561,8 +466,8 @@ public: /* [unique][in][out] */ void **ppCallResult) = 0; virtual long __stdcall ExecMethodAsync( - /* [in] */ const wchar_t * strObjectPath, - /* [in] */ const wchar_t * strMethodName, + /* [in] */ const bstr strObjectPath, + /* [in] */ const bstr strMethodName, /* [in] */ long lFlags, /* [in] */ IWbemContext_BIPC *pCtx, /* [in] */ IWbemClassObject_BIPC *pInParams, @@ -574,19 +479,17 @@ struct IWbemLocator_BIPC : public IUnknown_BIPC { public: virtual long __stdcall ConnectServer( - /* [in] */ const wchar_t * strNetworkResource, - /* [in] */ const wchar_t * strUser, - /* [in] */ const wchar_t * strPassword, - /* [in] */ const wchar_t * strLocale, + /* [in] */ const bstr strNetworkResource, + /* [in] */ const bstr strUser, + /* [in] */ const bstr strPassword, + /* [in] */ const bstr strLocale, /* [in] */ long lSecurityFlags, - /* [in] */ const wchar_t * strAuthority, + /* [in] */ const bstr strAuthority, /* [in] */ void *pCtx, /* [out] */ IWbemServices_BIPC **ppNamespace) = 0; }; - - struct interprocess_overlapped { unsigned long *internal; @@ -602,18 +505,6 @@ struct interprocess_overlapped void *h_event; }; -struct interprocess_semaphore_basic_information -{ - unsigned int count; // current semaphore count - unsigned int limit; // max semaphore count -}; - -struct interprocess_section_basic_information -{ - void * base_address; - unsigned long section_attributes; - __int64 section_size; -}; struct interprocess_filetime { @@ -621,7 +512,7 @@ struct interprocess_filetime unsigned long dwHighDateTime; }; -struct win32_find_data_t +struct win32_find_data { unsigned long dwFileAttributes; interprocess_filetime ftCreationTime; @@ -661,27 +552,16 @@ struct system_info { unsigned short wProcessorRevision; }; -typedef struct _interprocess_memory_basic_information -{ - void * BaseAddress; - void * AllocationBase; - unsigned long AllocationProtect; - unsigned long RegionSize; - 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 +struct interprocess_security_descriptor { unsigned char Revision; unsigned char Sbz1; @@ -690,59 +570,134 @@ typedef struct _interprocess_security_descriptor void *Group; interprocess_acl *Sacl; interprocess_acl *Dacl; -} interprocess_security_descriptor; +}; -enum file_information_class_t { - file_directory_information = 1, - file_full_directory_information, - file_both_directory_information, - file_basic_information, - file_standard_information, - file_internal_information, - file_ea_information, - file_access_information, - file_name_information, - file_rename_information, - file_link_information, - file_names_information, - file_disposition_information, - file_position_information, - file_full_ea_information, - file_mode_information, - file_alignment_information, - file_all_information, - file_allocation_information, - file_end_of_file_information, - file_alternate_name_information, - file_stream_information, - file_pipe_information, - file_pipe_local_information, - file_pipe_remote_information, - file_mailslot_query_information, - file_mailslot_set_information, - file_compression_information, - file_copy_on_write_information, - file_completion_information, - file_move_cluster_information, - file_quota_information, - file_reparse_point_information, - file_network_open_information, - file_object_id_information, - file_tracking_information, - file_ole_directory_information, - file_content_index_information, - file_inherit_content_index_information, - file_ole_information, - file_maximum_information +struct interprocess_by_handle_file_information +{ + unsigned long dwFileAttributes; + interprocess_filetime ftCreationTime; + interprocess_filetime ftLastAccessTime; + interprocess_filetime ftLastWriteTime; + unsigned long dwVolumeSerialNumber; + unsigned long nFileSizeHigh; + unsigned long nFileSizeLow; + unsigned long nNumberOfLinks; + unsigned long nFileIndexHigh; + unsigned long nFileIndexLow; }; -enum semaphore_information_class { - semaphore_basic_information = 0 +struct interprocess_eventlogrecord +{ + unsigned long Length; // Length of full record + unsigned long Reserved; // Used by the service + unsigned long RecordNumber; // Absolute record number + unsigned long TimeGenerated; // Seconds since 1-1-1970 + unsigned long TimeWritten; // Seconds since 1-1-1970 + unsigned long EventID; + unsigned short EventType; + unsigned short NumStrings; + unsigned short EventCategory; + unsigned short ReservedFlags; // For use with paired events (auditing) + unsigned long ClosingRecordNumber; // For use with paired events (auditing) + unsigned long StringOffset; // Offset from beginning of record + unsigned long UserSidLength; + unsigned long UserSidOffset; + unsigned long DataLength; + unsigned long DataOffset; // Offset from beginning of record + // + // Then follow: + // + // wchar_t SourceName[] + // wchar_t Computername[] + // SID UserSid + // wchar_t Strings[] + // BYTE Data[] + // CHAR Pad[] + // unsigned long Length; + // }; -struct file_name_information_t { - unsigned long FileNameLength; - wchar_t FileName[1]; +union large_integer +{ + __int64 QuadPart; +}; + +struct hinstance_struct { int unused; }; +typedef hinstance_struct *hmodule; + +struct hkey_struct; +typedef hkey_struct *hkey; + +#ifdef _WIN64 +typedef __int64 (__stdcall *farproc_t)(); +#else +typedef int (__stdcall *farproc_t)(); +#endif // _WIN64 + +#else //#ifndef BOOST_USE_WINDOWS_H + +typedef GUID GUID_BIPC; +typedef VARIANT wchar_variant; + +typedef IUnknown IUnknown_BIPC; + +typedef IWbemClassObject IWbemClassObject_BIPC; + +typedef IWbemContext IWbemContext_BIPC; + +typedef IEnumWbemClassObject IEnumWbemClassObject_BIPC; + +typedef IWbemServices IWbemServices_BIPC; + +typedef IWbemLocator IWbemLocator_BIPC; + +typedef OVERLAPPED interprocess_overlapped; + +typedef FILETIME interprocess_filetime; + +typedef WIN32_FIND_DATAA win32_find_data; + +typedef SECURITY_ATTRIBUTES interprocess_security_attributes; + +typedef SYSTEM_INFO system_info; + +typedef ACL interprocess_acl; + +typedef SECURITY_DESCRIPTOR interprocess_security_descriptor; + +typedef BY_HANDLE_FILE_INFORMATION interprocess_by_handle_file_information; + +typedef EVENTLOGRECORD interprocess_eventlogrecord; + +typedef LARGE_INTEGER large_integer; + +typedef HMODULE hmodule; + +typedef HKEY hkey; + +typedef BSTR bstr; + +typedef FARPROC farproc_t; + +#endif //#ifndef BOOST_USE_WINDOWS_H + +////////////////////////////////////////////////////////////////////////////// +// +// Nt native structures +// +////////////////////////////////////////////////////////////////////////////// + +struct interprocess_semaphore_basic_information +{ + unsigned int count; // current semaphore count + unsigned int limit; // max semaphore count +}; + +struct interprocess_section_basic_information +{ + void * base_address; + unsigned long section_attributes; + __int64 section_size; }; struct file_rename_information_t { @@ -785,24 +740,71 @@ union system_timeofday_information __int64 liExpTimeZoneBias; unsigned long uCurrentTimeZoneId; unsigned long dwReserved; + unsigned __int64 ullBootTimeBias; + unsigned __int64 ullSleepTimeBias; } data; - unsigned char Reserved1[SystemTimeOfDayInfoLength]; + unsigned char Reserved1[sizeof(data_t)]; }; -struct interprocess_by_handle_file_information +static const long BootstampLength = sizeof(__int64); +static const long BootAndSystemstampLength = sizeof(__int64)*2; +static const long SystemTimeOfDayInfoLength = sizeof(system_timeofday_information::data_t); + +struct object_name_information_t { - unsigned long dwFileAttributes; - interprocess_filetime ftCreationTime; - interprocess_filetime ftLastAccessTime; - interprocess_filetime ftLastWriteTime; - unsigned long dwVolumeSerialNumber; - unsigned long nFileSizeHigh; - unsigned long nFileSizeLow; - unsigned long nNumberOfLinks; - unsigned long nFileIndexHigh; - unsigned long nFileIndexLow; + unicode_string_t Name; + wchar_t NameBuffer[1]; }; +enum file_information_class_t { + file_directory_information = 1, + file_full_directory_information, + file_both_directory_information, + file_basic_information, + file_standard_information, + file_internal_information, + file_ea_information, + file_access_information, + file_name_information, + file_rename_information, + file_link_information, + file_names_information, + file_disposition_information, + file_position_information, + file_full_ea_information, + file_mode_information, + file_alignment_information, + file_all_information, + file_allocation_information, + file_end_of_file_information, + file_alternate_name_information, + file_stream_information, + file_pipe_information, + file_pipe_local_information, + file_pipe_remote_information, + file_mailslot_query_information, + file_mailslot_set_information, + file_compression_information, + file_copy_on_write_information, + file_completion_information, + file_move_cluster_information, + file_quota_information, + file_reparse_point_information, + file_network_open_information, + file_object_id_information, + file_tracking_information, + file_ole_directory_information, + file_content_index_information, + file_inherit_content_index_information, + file_ole_information, + file_maximum_information +}; + +enum semaphore_information_class { + semaphore_basic_information = 0 +}; + + enum system_information_class { system_basic_information = 0, system_performance_information = 2, @@ -830,11 +832,15 @@ enum section_information_class section_image_information }; -struct object_name_information_t -{ - unicode_string_t Name; - wchar_t NameBuffer[1]; -}; +////////////////////////////////////////////////////////////////////////////// +// +// Forward declaration of winapi +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_USE_WINDOWS_H + +//Kernel32.dll //Some windows API declarations extern "C" __declspec(dllimport) unsigned long __stdcall GetCurrentProcessId(); @@ -844,6 +850,7 @@ extern "C" __declspec(dllimport) int __stdcall GetProcessTimes , interprocess_filetime *lpExitTime,interprocess_filetime *lpKernelTime , interprocess_filetime *lpUserTime ); extern "C" __declspec(dllimport) void __stdcall Sleep(unsigned long); +extern "C" __declspec(dllimport) unsigned long __stdcall GetTickCount(void); extern "C" __declspec(dllimport) int __stdcall SwitchToThread(); extern "C" __declspec(dllimport) unsigned long __stdcall GetLastError(); extern "C" __declspec(dllimport) void __stdcall SetLastError(unsigned long); @@ -855,8 +862,8 @@ extern "C" __declspec(dllimport) int __stdcall DuplicateHandle , unsigned long dwDesiredAccess, int bInheritHandle , unsigned long dwOptions); extern "C" __declspec(dllimport) long __stdcall GetFileType(void *hFile); -extern "C" __declspec(dllimport) void *__stdcall FindFirstFileA(const char *lpFileName, win32_find_data_t *lpFindFileData); -extern "C" __declspec(dllimport) int __stdcall FindNextFileA(void *hFindFile, win32_find_data_t *lpFindFileData); +extern "C" __declspec(dllimport) void *__stdcall FindFirstFileA(const char *lpFileName, win32_find_data *lpFindFileData); +extern "C" __declspec(dllimport) int __stdcall FindNextFileA(void *hFindFile, win32_find_data *lpFindFileData); extern "C" __declspec(dllimport) int __stdcall FindClose(void *hFindFile); //extern "C" __declspec(dllimport) void __stdcall GetSystemTimeAsFileTime(interprocess_filetime*); //extern "C" __declspec(dllimport) int __stdcall FileTimeToLocalFileTime(const interprocess_filetime *in, const interprocess_filetime *out); @@ -872,12 +879,12 @@ extern "C" __declspec(dllimport) void * __stdcall CreateFileMappingA (void *, in extern "C" __declspec(dllimport) void * __stdcall MapViewOfFileEx (void *, unsigned long, unsigned long, unsigned long, std::size_t, void*); extern "C" __declspec(dllimport) void * __stdcall OpenFileMappingA (unsigned long, int, const char *); extern "C" __declspec(dllimport) void * __stdcall CreateFileA (const char *, unsigned long, unsigned long, struct interprocess_security_attributes*, unsigned long, unsigned long, void *); -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) int __stdcall GetFileSizeEx (void *, large_integer *size); extern "C" __declspec(dllimport) unsigned long __stdcall FormatMessageA (unsigned long dwFlags, const void *lpSource, unsigned long dwMessageId, unsigned long dwLanguageId, char *lpBuffer, unsigned long nSize, @@ -890,7 +897,7 @@ extern "C" __declspec(dllimport) int __stdcall GetTempPathA(unsigned long length extern "C" __declspec(dllimport) int __stdcall CreateDirectory(const char *, interprocess_security_attributes*); extern "C" __declspec(dllimport) int __stdcall SetFileValidData(void *, __int64 size); extern "C" __declspec(dllimport) int __stdcall SetEndOfFile(void *); -extern "C" __declspec(dllimport) int __stdcall SetFilePointerEx(void *, __int64 distance, __int64 *new_file_pointer, unsigned long move_method); +extern "C" __declspec(dllimport) int __stdcall SetFilePointerEx(void *, large_integer distance, large_integer *new_file_pointer, unsigned long move_method); extern "C" __declspec(dllimport) int __stdcall LockFile (void *hnd, unsigned long offset_low, unsigned long offset_high, unsigned long size_low, unsigned long size_high); extern "C" __declspec(dllimport) int __stdcall UnlockFile(void *hnd, unsigned long offset_low, unsigned long offset_high, unsigned long size_low, unsigned long size_high); extern "C" __declspec(dllimport) int __stdcall LockFileEx(void *hnd, unsigned long flags, unsigned long reserved, unsigned long size_low, unsigned long size_high, interprocess_overlapped* overlapped); @@ -899,18 +906,18 @@ extern "C" __declspec(dllimport) int __stdcall WriteFile(void *hnd, const void * extern "C" __declspec(dllimport) int __stdcall ReadFile(void *hnd, void *buffer, unsigned long bytes_to_read, unsigned long *bytes_read, interprocess_overlapped* overlapped); extern "C" __declspec(dllimport) int __stdcall InitializeSecurityDescriptor(interprocess_security_descriptor *pSecurityDescriptor, unsigned long dwRevision); extern "C" __declspec(dllimport) int __stdcall SetSecurityDescriptorDacl(interprocess_security_descriptor *pSecurityDescriptor, int bDaclPresent, interprocess_acl *pDacl, int bDaclDefaulted); -extern "C" __declspec(dllimport) void *__stdcall LoadLibraryA(const char *); -extern "C" __declspec(dllimport) int __stdcall FreeLibrary(void *); -extern "C" __declspec(dllimport) void *__stdcall GetProcAddress(void *, const char*); -extern "C" __declspec(dllimport) void *__stdcall GetModuleHandleA(const char*); +extern "C" __declspec(dllimport) hmodule __stdcall LoadLibraryA(const char *); +extern "C" __declspec(dllimport) int __stdcall FreeLibrary(hmodule); +extern "C" __declspec(dllimport) farproc_t __stdcall GetProcAddress(void *, const char*); +extern "C" __declspec(dllimport) hmodule __stdcall GetModuleHandleA(const char*); extern "C" __declspec(dllimport) void *__stdcall GetFileInformationByHandle(void *, interprocess_by_handle_file_information*); -extern "C" __declspec(dllimport) unsigned long __stdcall GetMappedFileNameW(void *, void *, wchar_t *, unsigned long); -extern "C" __declspec(dllimport) long __stdcall RegOpenKeyExA(void *, const char *, unsigned long, unsigned long, void **); -extern "C" __declspec(dllimport) long __stdcall RegQueryValueExA(void *, const char *, unsigned long*, unsigned long*, unsigned char *, unsigned long*); -extern "C" __declspec(dllimport) long __stdcall RegCloseKey(void *); -extern "C" __declspec(dllimport) int __stdcall QueryPerformanceCounter(__int64 *lpPerformanceCount); -//COM API +//Advapi32.dll +extern "C" __declspec(dllimport) long __stdcall RegOpenKeyExA(hkey, const char *, unsigned long, unsigned long, hkey*); +extern "C" __declspec(dllimport) long __stdcall RegQueryValueExA(hkey, const char *, unsigned long*, unsigned long*, unsigned char *, unsigned long*); +extern "C" __declspec(dllimport) long __stdcall RegCloseKey(hkey); + +//Ole32.dll extern "C" __declspec(dllimport) long __stdcall CoInitializeEx(void *pvReserved, unsigned long dwCoInit); extern "C" __declspec(dllimport) long __stdcall CoInitializeSecurity( void* pSecDesc, @@ -932,18 +939,47 @@ extern "C" __declspec(dllimport) long __stdcall CoInitializeSecurity( unsigned long dwImpLevel, void *pAuthInfo, unsigned long dwCapabilities); - -extern "C" __declspec(dllimport) long __stdcall VariantClear(wchar_variant * pvarg); extern "C" __declspec(dllimport) long __stdcall CoCreateInstance(const GUID_BIPC & rclsid, IUnknown_BIPC *pUnkOuter, unsigned long dwClsContext, const GUID_BIPC & riid, void** ppv); extern "C" __declspec(dllimport) void __stdcall CoUninitialize(void); +//OleAut32.dll +extern "C" __declspec(dllimport) long __stdcall VariantClear(wchar_variant * pvarg); + +//Shell32.dll +extern "C" __declspec(dllimport) int __stdcall SHGetSpecialFolderPathA + (void* hwnd, const char *pszPath, int csidl, int fCreate); + +extern "C" __declspec(dllimport) int __stdcall SHGetFolderPathA(void *hwnd, int csidl, void *hToken, unsigned long dwFlags, const char *pszPath); + +//EventLog access functions +extern "C" __declspec(dllimport) void* __stdcall OpenEventLogA + (const char* lpUNCServerName, const char* lpSourceName); -//API function typedefs -//Pointer to functions +extern "C" __declspec(dllimport) int __stdcall CloseEventLog(void *hEventLog); + +extern "C" __declspec(dllimport) int __stdcall ReadEventLogA + (void *hEventLog, + unsigned long dwReadFlags, + unsigned long dwRecordOffset, + void *lpBuffer, + unsigned long nNumberOfBytesToRead, + unsigned long *pnBytesRead, + unsigned long *pnMinNumberOfBytesNeeded + ); + +#endif //#ifndef BOOST_USE_WINDOWS_H + +//kernel32.dll +typedef int (__stdcall *QueryPerformanceCounter_t) (__int64 *lpPerformanceCount); +typedef int (__stdcall *QueryPerformanceFrequency_t)(__int64 *lpFrequency); + +//ntdll.dll typedef long (__stdcall *NtDeleteFile_t)(object_attributes_t *ObjectAttributes); typedef long (__stdcall *NtSetInformationFile_t)(void *FileHandle, io_status_block_t *IoStatusBlock, void *FileInformation, unsigned long Length, int FileInformationClass ); +typedef long (__stdcall *NtOpenFile)(void **FileHandle, unsigned long DesiredAccess, object_attributes_t *ObjectAttributes + , io_status_block_t *IoStatusBlock, unsigned long ShareAccess, unsigned long Length, unsigned long OpenOptions); typedef long (__stdcall *NtQuerySystemInformation_t)(int, void*, unsigned long, unsigned long *); typedef long (__stdcall *NtQueryObject_t)(void*, object_information_class, void *, unsigned long, unsigned long *); typedef long (__stdcall *NtQuerySemaphore_t)(void*, unsigned int info_class, interprocess_semaphore_basic_information *pinfo, unsigned int info_size, unsigned int *ret_len); @@ -951,19 +987,203 @@ typedef long (__stdcall *NtQuerySection_t)(void*, section_information_class, int typedef long (__stdcall *NtQueryInformationFile_t)(void *,io_status_block_t *,void *, long, int); typedef long (__stdcall *NtOpenFile_t)(void*,unsigned long ,object_attributes_t*,io_status_block_t*,unsigned long,unsigned long); typedef long (__stdcall *NtClose_t) (void*); -typedef long (__stdcall *RtlCreateUnicodeStringFromAsciiz_t)(unicode_string_t *, const char *); -typedef void (__stdcall *RtlFreeUnicodeString_t)(unicode_string_t *); -typedef void (__stdcall *RtlInitUnicodeString_t)( unicode_string_t *, const wchar_t * ); -typedef long (__stdcall *RtlAppendUnicodeToString_t)(unicode_string_t *Destination, const wchar_t *Source); -typedef unsigned long (__stdcall * GetMappedFileName_t)(void *, void *, wchar_t *, unsigned long); -typedef long (__stdcall * RegOpenKeyEx_t)(void *, const char *, unsigned long, unsigned long, void **); -typedef long (__stdcall * RegQueryValueEx_t)(void *, const char *, unsigned long*, unsigned long*, unsigned char *, unsigned long*); -typedef long (__stdcall * RegCloseKey_t)(void *); +typedef long (__stdcall *NtQueryTimerResolution_t) (unsigned long* LowestResolution, unsigned long* HighestResolution, unsigned long* CurrentResolution); +typedef long (__stdcall *NtSetTimerResolution_t) (unsigned long RequestedResolution, int Set, unsigned long* ActualResolution); + +} //namespace winapi { +} //namespace interprocess { +} //namespace boost { + +////////////////////////////////////////////////////////////////////////////// +// +// Forward declaration of constants +// +////////////////////////////////////////////////////////////////////////////// + +namespace boost { +namespace interprocess { +namespace winapi { + +//Some used constants +static const unsigned long infinite_time = 0xFFFFFFFF; +static const unsigned long error_already_exists = 183L; +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 long error_sharing_violation_tries = 3L; +static const unsigned long error_sharing_violation_sleep_ms = 250L; +static const unsigned long error_file_too_large = 223L; +static const unsigned long error_insufficient_buffer = 122L; +static const unsigned long error_handle_eof = 38L; +static const unsigned long semaphore_all_access = (0x000F0000L)|(0x00100000L)|0x3; +static const unsigned long mutex_all_access = (0x000F0000L)|(0x00100000L)|0x0001; + +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; +static const unsigned long section_map_write = 0x0002; +static const unsigned long section_map_read = 0x0004; +static const unsigned long section_map_execute = 0x0008; +static const unsigned long section_extend_size = 0x0010; +static const unsigned long section_all_access = standard_rights_required | + section_query | + section_map_write | + section_map_read | + section_map_execute | + section_extend_size; + +static const unsigned long file_map_copy = section_query; +static const unsigned long file_map_write = section_map_write; +static const unsigned long file_map_read = section_map_read; +static const unsigned long file_map_all_access = section_all_access; +static const unsigned long delete_access = 0x00010000L; +static const unsigned long file_flag_backup_semantics = 0x02000000; +static const long file_flag_delete_on_close = 0x04000000; + +//Native API constants +static const unsigned long file_open_for_backup_intent = 0x00004000; +static const int file_share_valid_flags = 0x00000007; +static const long file_delete_on_close = 0x00001000L; +static const long obj_case_insensitive = 0x00000040L; +static const long delete_flag = 0x00010000L; + +static const unsigned long movefile_copy_allowed = 0x02; +static const unsigned long movefile_delay_until_reboot = 0x04; +static const unsigned long movefile_replace_existing = 0x01; +static const unsigned long movefile_write_through = 0x08; +static const unsigned long movefile_create_hardlink = 0x10; +static const unsigned long movefile_fail_if_not_trackable = 0x20; + +static const unsigned long file_share_read = 0x00000001; +static const unsigned long file_share_write = 0x00000002; +static const unsigned long file_share_delete = 0x00000004; + +static const unsigned long file_attribute_readonly = 0x00000001; +static const unsigned long file_attribute_hidden = 0x00000002; +static const unsigned long file_attribute_system = 0x00000004; +static const unsigned long file_attribute_directory = 0x00000010; +static const unsigned long file_attribute_archive = 0x00000020; +static const unsigned long file_attribute_device = 0x00000040; +static const unsigned long file_attribute_normal = 0x00000080; +static const unsigned long file_attribute_temporary = 0x00000100; + +static const unsigned long generic_read = 0x80000000L; +static const unsigned long generic_write = 0x40000000L; + +static const unsigned long wait_object_0 = 0; +static const unsigned long wait_abandoned = 0x00000080L; +static const unsigned long wait_timeout = 258L; +static const unsigned long wait_failed = (unsigned long)0xFFFFFFFF; + +static const unsigned long duplicate_close_source = (unsigned long)0x00000001; +static const unsigned long duplicate_same_access = (unsigned long)0x00000002; + +static const unsigned long format_message_allocate_buffer + = (unsigned long)0x00000100; +static const unsigned long format_message_ignore_inserts + = (unsigned long)0x00000200; +static const unsigned long format_message_from_string + = (unsigned long)0x00000400; +static const unsigned long format_message_from_hmodule + = (unsigned long)0x00000800; +static const unsigned long format_message_from_system + = (unsigned long)0x00001000; +static const unsigned long format_message_argument_array + = (unsigned long)0x00002000; +static const unsigned long format_message_max_width_mask + = (unsigned long)0x000000FF; +static const unsigned long lang_neutral = (unsigned long)0x00; +static const unsigned long sublang_default = (unsigned long)0x01; +static const unsigned long invalid_file_size = (unsigned long)0xFFFFFFFF; +static const unsigned long invalid_file_attributes = ((unsigned long)-1); +static void * const invalid_handle_value = ((void*)(long)(-1)); + +static const unsigned long file_type_char = 0x0002L; +static const unsigned long file_type_disk = 0x0001L; +static const unsigned long file_type_pipe = 0x0003L; +static const unsigned long file_type_remote = 0x8000L; +static const unsigned long file_type_unknown = 0x0000L; + +static const unsigned long create_new = 1; +static const unsigned long create_always = 2; +static const unsigned long open_existing = 3; +static const unsigned long open_always = 4; +static const unsigned long truncate_existing = 5; + +static const unsigned long file_begin = 0; +static const unsigned long file_current = 1; +static const unsigned long file_end = 2; + +static const unsigned long lockfile_fail_immediately = 1; +static const unsigned long lockfile_exclusive_lock = 2; +static const unsigned long error_lock_violation = 33; +static const unsigned long security_descriptor_revision = 1; + +const unsigned long max_record_buffer_size = 0x10000L; // 64K +const unsigned long max_path = 260; + +//Keys +static const hkey hkey_local_machine = (hkey)(unsigned long*)(long)(0x80000002); +static unsigned long key_query_value = 0x0001; + +//COM API +const unsigned long RPC_C_AUTHN_LEVEL_PKT_BIPC = 4; +const unsigned long RPC_C_AUTHN_DEFAULT_BIPC = 0xffffffffL; +const unsigned long RPC_C_AUTHZ_DEFAULT_BIPC = 0xffffffffL; +const unsigned long RPC_C_IMP_LEVEL_IMPERSONATE_BIPC = 3; +const signed long EOAC_NONE_BIPC = 0; +const signed long CLSCTX_INPROC_SERVER_BIPC = 0x1; +const signed long CLSCTX_LOCAL_SERVER_BIPC = 0x4; +const signed long WBEM_FLAG_RETURN_IMMEDIATELY_BIPC = 0x10; +const signed long WBEM_FLAG_RETURN_WHEN_COMPLETE_BIPC = 0x0; +const signed long WBEM_FLAG_FORWARD_ONLY_BIPC = 0x20; +const signed long WBEM_INFINITE_BIPC = 0xffffffffL; +const signed long RPC_E_TOO_LATE_BIPC = 0x80010119L; +const signed long S_OK_BIPC = 0L; +const signed long S_FALSE_BIPC = 1; +const signed long RPC_E_CHANGED_MODE_BIPC = 0x80010106L; +const unsigned long COINIT_APARTMENTTHREADED_BIPC = 0x2; +const unsigned long COINIT_MULTITHREADED_BIPC = 0x0; +const unsigned long COINIT_DISABLE_OLE1DDE_BIPC = 0x4; +const unsigned long COINIT_SPEED_OVER_MEMORY_BIPC = 0x4; + + +//If the user needs to change default COM initialization model, +//it can define BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL to one of these: +// +// COINIT_APARTMENTTHREADED_BIPC +// COINIT_MULTITHREADED_BIPC +// COINIT_DISABLE_OLE1DDE_BIPC +// COINIT_SPEED_OVER_MEMORY_BIPC +#if !defined(BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL) + #define BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL COINIT_APARTMENTTHREADED_BIPC +#elif (BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL != COINIT_APARTMENTTHREADED_BIPC) &&\ + (BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL != COINIT_MULTITHREADED_BIPC) &&\ + (BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL != COINIT_DISABLE_OLE1DDE_BIPC) &&\ + (BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL != COINIT_SPEED_OVER_MEMORY_BIPC) + #error "Wrong value for BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL macro" +#endif + +const GUID_BIPC CLSID_WbemAdministrativeLocator = + { 0xcb8555cc, 0x9128, 0x11d1, {0xad, 0x9b, 0x00, 0xc0, 0x4f, 0xd8, 0xfd, 0xff}}; + +const GUID_BIPC IID_IUnknown = { 0x00000000, 0x0000, 0x0000, {0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}}; + +static const unsigned long eventlog_sequential_read = 0x0001; +static const unsigned long eventlog_backwards_read = 0x0008; } //namespace winapi { } //namespace interprocess { } //namespace boost { + namespace boost { namespace interprocess { namespace winapi { @@ -993,10 +1213,13 @@ inline unsigned long make_lang_id(unsigned long p, unsigned long s) inline void sched_yield() { if(!SwitchToThread()){ - Sleep(1); + Sleep(0); } } +inline void sleep_tick() +{ Sleep(1); } + inline void sleep(unsigned long ms) { Sleep(ms); } @@ -1015,10 +1238,10 @@ inline unsigned long get_current_process_id() inline unsigned int close_handle(void* handle) { return CloseHandle(handle); } -inline void * find_first_file(const char *lpFileName, win32_find_data_t *lpFindFileData) +inline void * find_first_file(const char *lpFileName, win32_find_data *lpFindFileData) { return FindFirstFileA(lpFileName, lpFindFileData); } -inline bool find_next_file(void *hFindFile, win32_find_data_t *lpFindFileData) +inline bool find_next_file(void *hFindFile, win32_find_data *lpFindFileData) { return FindNextFileA(hFindFile, lpFindFileData) != 0; } inline bool find_close(void *handle) @@ -1033,7 +1256,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); } @@ -1125,23 +1348,23 @@ inline void *create_file(const char *name, unsigned long access, unsigned long c return invalid_handle_value; } -inline bool delete_file(const char *name) -{ return 0 != DeleteFileA(name); } - -inline bool move_file_ex(const char *source_filename, const char *destination_filename, unsigned long flags) -{ return 0 != MoveFileExA(source_filename, destination_filename, flags); } - inline void get_system_info(system_info *info) { GetSystemInfo(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); } inline bool get_file_size(void *handle, __int64 &size) -{ return 0 != GetFileSizeEx(handle, &size); } +{ return 0 != GetFileSizeEx(handle, (large_integer*)&size); } inline bool create_directory(const char *name) { @@ -1159,7 +1382,10 @@ inline int set_end_of_file(void *handle) { return 0 != SetEndOfFile(handle); } inline bool set_file_pointer_ex(void *handle, __int64 distance, __int64 *new_file_pointer, unsigned long move_method) -{ return 0 != SetFilePointerEx(handle, distance, new_file_pointer, move_method); } +{ + large_integer d; d.QuadPart = distance; + return 0 != SetFilePointerEx(handle, d, (large_integer*)new_file_pointer, move_method); +} inline bool lock_file_ex(void *hnd, unsigned long flags, unsigned long reserved, unsigned long size_low, unsigned long size_high, interprocess_overlapped *overlapped) { return 0 != LockFileEx(hnd, flags, reserved, size_low, size_high, overlapped); } @@ -1192,38 +1418,30 @@ inline long interlocked_exchange(long volatile* addend, long value) { return BOOST_INTERLOCKED_EXCHANGE(const_cast<long*>(addend), value); } //Forward functions -inline void *load_library(const char *name) +inline hmodule load_library(const char *name) { return LoadLibraryA(name); } -inline bool free_library(void *module) +inline bool free_library(hmodule module) { return 0 != FreeLibrary(module); } -inline void *get_proc_address(void *module, const char *name) +inline farproc_t get_proc_address(hmodule module, const char *name) { return GetProcAddress(module, name); } inline void *get_current_process() { return GetCurrentProcess(); } -inline void *get_module_handle(const char *name) +inline hmodule get_module_handle(const char *name) { return GetModuleHandleA(name); } -inline unsigned long get_mapped_file_name(void *process, void *lpv, wchar_t *lpfilename, unsigned long nSize) -{ return GetMappedFileNameW(process, lpv, lpfilename, nSize); } - -inline long reg_open_key_ex(void *hKey, const char *lpSubKey, unsigned long ulOptions, unsigned long samDesired, void **phkResult) +inline long reg_open_key_ex(hkey hKey, const char *lpSubKey, unsigned long ulOptions, unsigned long samDesired, hkey *phkResult) { return RegOpenKeyExA(hKey, lpSubKey, ulOptions, samDesired, phkResult); } -inline long reg_query_value_ex(void *hKey, const char *lpValueName, unsigned long*lpReserved, unsigned long*lpType, unsigned char *lpData, unsigned long*lpcbData) +inline long reg_query_value_ex(hkey hKey, const char *lpValueName, unsigned long*lpReserved, unsigned long*lpType, unsigned char *lpData, unsigned long*lpcbData) { return RegQueryValueExA(hKey, lpValueName, lpReserved, lpType, lpData, lpcbData); } -inline long reg_close_key(void *hKey) +inline long reg_close_key(hkey hKey) { return RegCloseKey(hKey); } -inline bool query_performance_counter(__int64 *lpPerformanceCount) -{ - return 0 != QueryPerformanceCounter(lpPerformanceCount); -} - inline void initialize_object_attributes ( object_attributes_t *pobject_attr, unicode_string_t *name , unsigned long attr, void *rootdir, void *security_descr) @@ -1248,75 +1466,134 @@ inline void rtl_init_empty_unicode_string(unicode_string_t *ucStr, wchar_t *buf, template<int Dummy> struct function_address_holder { - enum { NtSetInformationFile, NtQuerySystemInformation, NtQueryObject, NtQuerySemaphore, NtQuerySection, NumFunction }; - enum { NtDll_dll, NumModule }; + enum { NtSetInformationFile + , NtQuerySystemInformation + , NtQueryObject + , NtQuerySemaphore + , NtQuerySection + , NtOpenFile + , NtClose + , NtQueryTimerResolution + , NtSetTimerResolution + , QueryPerformanceCounter + , QueryPerformanceFrequency + , NumFunction + }; + enum { NtDll_dll, Kernel32_dll, NumModule }; private: - static void *FunctionAddresses[NumFunction]; + static const char *FunctionNames[NumFunction]; + static const char *ModuleNames[NumModule]; + static farproc_t FunctionAddresses[NumFunction]; + static unsigned int FunctionModules[NumFunction]; static volatile long FunctionStates[NumFunction]; - static void *ModuleAddresses[NumModule]; + static hmodule ModuleAddresses[NumModule]; static volatile long ModuleStates[NumModule]; - static void *get_module_from_id(unsigned int id) + static hmodule get_module_from_id(unsigned int id) { - assert(id < (unsigned int)NumModule); - const char *module[] = { "ntdll.dll" }; - bool compile_check[sizeof(module)/sizeof(module[0]) == NumModule]; - (void)compile_check; - return get_module_handle(module[id]); + BOOST_ASSERT(id < (unsigned int)NumModule); + hmodule addr = get_module_handle(ModuleNames[id]); + BOOST_ASSERT(addr); + return addr; } - static void *get_module(const unsigned int id) + static hmodule get_module(const unsigned int id) { - assert(id < (unsigned int)NumModule); - while(ModuleStates[id] < 2){ + BOOST_ASSERT(id < (unsigned int)NumModule); + for(unsigned i = 0; ModuleStates[id] < 2; ++i){ if(interlocked_compare_exchange(&ModuleStates[id], 1, 0) == 0){ ModuleAddresses[id] = get_module_from_id(id); interlocked_increment(&ModuleStates[id]); break; } - else{ + else if(i & 1){ sched_yield(); } + else{ + sleep_tick(); + } } return ModuleAddresses[id]; } - static void *get_address_from_dll(const unsigned int id) + static farproc_t get_address_from_dll(const unsigned int id) { - assert(id < (unsigned int)NumFunction); - const char *function[] = { "NtSetInformationFile", "NtQuerySystemInformation", "NtQueryObject", "NtQuerySemaphore", "NtQuerySection" }; - bool compile_check[sizeof(function)/sizeof(function[0]) == NumFunction]; - (void)compile_check; - return get_proc_address(get_module(NtDll_dll), function[id]); + BOOST_ASSERT(id < (unsigned int)NumFunction); + farproc_t addr = get_proc_address(get_module(FunctionModules[id]), FunctionNames[id]); + BOOST_ASSERT(addr); + return addr; } public: - static void *get(const unsigned int id) + static farproc_t get(const unsigned int id) { - assert(id < (unsigned int)NumFunction); - while(FunctionStates[id] < 2){ + BOOST_ASSERT(id < (unsigned int)NumFunction); + for(unsigned i = 0; FunctionStates[id] < 2; ++i){ if(interlocked_compare_exchange(&FunctionStates[id], 1, 0) == 0){ FunctionAddresses[id] = get_address_from_dll(id); interlocked_increment(&FunctionStates[id]); break; } - else{ + else if(i & 1){ sched_yield(); } + else{ + sleep_tick(); + } } return FunctionAddresses[id]; } }; template<int Dummy> -void *function_address_holder<Dummy>::FunctionAddresses[function_address_holder<Dummy>::NumFunction]; +const char *function_address_holder<Dummy>::FunctionNames[function_address_holder<Dummy>::NumFunction] = +{ + "NtSetInformationFile", + "NtQuerySystemInformation", + "NtQueryObject", + "NtQuerySemaphore", + "NtQuerySection", + "NtOpenFile", + "NtClose", + "NtQueryTimerResolution", + "NtSetTimerResolution", + "QueryPerformanceCounter", + "QueryPerformanceFrequency" +}; + +template<int Dummy> +unsigned int function_address_holder<Dummy>::FunctionModules[function_address_holder<Dummy>::NumFunction] = +{ + NtDll_dll, + NtDll_dll, + NtDll_dll, + NtDll_dll, + NtDll_dll, + NtDll_dll, + NtDll_dll, + NtDll_dll, + NtDll_dll, + Kernel32_dll, + Kernel32_dll +}; + +template<int Dummy> +const char *function_address_holder<Dummy>::ModuleNames[function_address_holder<Dummy>::NumModule] = +{ + "ntdll.dll", + "kernel32.dll" +}; + + +template<int Dummy> +farproc_t function_address_holder<Dummy>::FunctionAddresses[function_address_holder<Dummy>::NumFunction]; template<int Dummy> volatile long function_address_holder<Dummy>::FunctionStates[function_address_holder<Dummy>::NumFunction]; template<int Dummy> -void *function_address_holder<Dummy>::ModuleAddresses[function_address_holder<Dummy>::NumModule]; +hmodule function_address_holder<Dummy>::ModuleAddresses[function_address_holder<Dummy>::NumModule]; template<int Dummy> volatile long function_address_holder<Dummy>::ModuleStates[function_address_holder<Dummy>::NumModule]; @@ -1329,52 +1606,11 @@ struct dll_func //Complex winapi based functions... struct library_unloader { - void *lib_; - library_unloader(void *module) : lib_(module){} + hmodule lib_; + library_unloader(hmodule module) : lib_(module){} ~library_unloader(){ free_library(lib_); } }; -//pszFilename must have room for at least MaxPath+1 characters -inline bool get_file_name_from_handle_function - (void * hFile, wchar_t *pszFilename, std::size_t length, std::size_t &out_length) -{ - if(length <= MaxPath){ - return false; - } - -// void *hiPSAPI = load_library("PSAPI.DLL"); -// if (0 == hiPSAPI) -// return 0; -// library_unloader unloader(hiPSAPI); - -// Pointer to function getMappedFileName() in PSAPI.DLL -// GetMappedFileName_t pfGMFN = -// (GetMappedFileName_t)get_proc_address(hiPSAPI, "GetMappedFileNameW"); -// if (! pfGMFN){ -// return 0; // Failed: unexpected error -// } - - bool bSuccess = false; - - // Create a file mapping object. - void * hFileMap = create_file_mapping(hFile, page_readonly, 1, 0, 0); - if(hFileMap){ - // Create a file mapping to get the file name. - void* pMem = map_view_of_file_ex(hFileMap, file_map_read, 0, 1, 0); - - if (pMem){ - //out_length = pfGMFN(get_current_process(), pMem, pszFilename, MaxPath); - out_length = get_mapped_file_name(get_current_process(), pMem, pszFilename, MaxPath); - if(out_length){ - bSuccess = true; - } - unmap_view_of_file(pMem); - } - close_handle(hFileMap); - } - - return(bSuccess); -} inline bool get_system_time_of_day_information(system_timeofday_information &info) { @@ -1410,7 +1646,8 @@ inline bool get_boot_and_system_time(unsigned char (&bootsystemstamp) [BootAndSy return true; } -inline bool get_boot_time_str(char *bootstamp_str, std::size_t &s) //will write BootstampLength chars +inline bool get_boot_time_str(char *bootstamp_str, std::size_t &s) + //will write BootstampLength chars { if(s < (BootstampLength*2)) return false; @@ -1431,7 +1668,23 @@ inline bool get_boot_time_str(char *bootstamp_str, std::size_t &s) //will write return true; } -inline bool get_boot_and_system_time_wstr(wchar_t *bootsystemstamp, std::size_t &s) //will write BootAndSystemstampLength chars +//Writes the hexadecimal value of the buffer, in the wide character string. +//str must be twice length +inline void buffer_to_wide_str(const void *buf, std::size_t length, wchar_t *str) +{ + const wchar_t Characters [] = + { L'0', L'1', L'2', L'3', L'4', L'5', L'6', L'7' + , L'8', L'9', L'A', L'B', L'C', L'D', L'E', L'F' }; + std::size_t char_counter = 0; + const char *chbuf = static_cast<const char *>(buf); + for(std::size_t i = 0; i != length; ++i){ + str[char_counter++] = Characters[(chbuf[i]&0xF0)>>4]; + str[char_counter++] = Characters[(chbuf[i]&0x0F)]; + } +} + +inline bool get_boot_and_system_time_wstr(wchar_t *bootsystemstamp, std::size_t &s) + //will write BootAndSystemstampLength chars { if(s < (BootAndSystemstampLength*2)) return false; @@ -1440,14 +1693,8 @@ inline bool get_boot_and_system_time_wstr(wchar_t *bootsystemstamp, std::size_t if(!ret){ return false; } - const wchar_t Characters [] = - { L'0', L'1', L'2', L'3', L'4', L'5', L'6', L'7' - , L'8', L'9', L'A', L'B', L'C', L'D', L'E', L'F' }; - std::size_t char_counter = 0; - for(std::size_t i = 0; i != static_cast<std::size_t>(BootAndSystemstampLength); ++i){ - bootsystemstamp[char_counter++] = Characters[(info.Reserved1[i]&0xF0)>>4]; - bootsystemstamp[char_counter++] = Characters[(info.Reserved1[i]&0x0F)]; - } + + buffer_to_wide_str(&info.Reserved1[0], BootAndSystemstampLength, bootsystemstamp); s = BootAndSystemstampLength*2; return true; } @@ -1463,16 +1710,99 @@ class handle_closer { close_handle(handle_); } }; +class eventlog_handle_closer +{ + void *handle_; + eventlog_handle_closer(const handle_closer &); + eventlog_handle_closer& operator=(const eventlog_handle_closer &); + public: + explicit eventlog_handle_closer(void *handle) : handle_(handle){} + ~eventlog_handle_closer() + { CloseEventLog(handle_); } +}; + union ntquery_mem_t { object_name_information_t name; struct ren_t { file_rename_information_t info; - wchar_t buf[32767]; + wchar_t buf[1]; } ren; }; +class nt_query_mem_deleter +{ + static const std::size_t rename_offset = offsetof(ntquery_mem_t, ren.info.FileName) - + offsetof(ntquery_mem_t, name.Name.Buffer); + // Timestamp process id atomic count + static const std::size_t rename_suffix = + (SystemTimeOfDayInfoLength + sizeof(unsigned long) + sizeof(boost::uint32_t))*2; + + public: + nt_query_mem_deleter(std::size_t object_name_information_size) + : m_size(object_name_information_size + rename_offset + rename_suffix) + , m_buf(new char [m_size]) + {} + + ~nt_query_mem_deleter() + { + delete[]m_buf; + } + + void realloc_mem(std::size_t num_bytes) + { + num_bytes += rename_suffix + rename_offset; + char *buf = m_buf; + m_buf = new char[num_bytes]; + delete[]buf; + m_size = num_bytes; + } + + ntquery_mem_t *query_mem() const + { return static_cast<ntquery_mem_t *>(static_cast<void*>(m_buf)); } + + unsigned long object_name_information_size() const + { + return static_cast<unsigned long>(m_size - rename_offset - SystemTimeOfDayInfoLength*2); + } + + std::size_t file_rename_information_size() const + { return static_cast<unsigned long>(m_size); } + + private: + std::size_t m_size; + char *m_buf; +}; + +class c_heap_deleter +{ + public: + c_heap_deleter(std::size_t size) + : m_buf(::malloc(size)) + {} + + ~c_heap_deleter() + { + if(m_buf) ::free(m_buf); + } + + void realloc_mem(std::size_t num_bytes) + { + void *buf = ::realloc(m_buf, num_bytes); + if(!buf){ + free(m_buf); + m_buf = 0; + } + } + + void *get() const + { return m_buf; } + + private: + void *m_buf; +}; + inline bool unlink_file(const char *filename) { //Don't try to optimize doing a DeleteFile first @@ -1493,71 +1823,96 @@ inline bool unlink_file(const char *filename) try{ NtSetInformationFile_t pNtSetInformationFile = (NtSetInformationFile_t)dll_func::get(dll_func::NtSetInformationFile); - if(!pNtSetInformationFile){ - return false; - } - NtQueryObject_t pNtQueryObject = - (NtQueryObject_t)dll_func::get(dll_func::NtQueryObject); + NtQueryObject_t pNtQueryObject = (NtQueryObject_t)dll_func::get(dll_func::NtQueryObject); //First step: Obtain a handle to the file using Win32 rules. This resolves relative paths - void *fh = create_file(filename, generic_read | delete_access, open_existing, - file_flag_backup_semantics | file_flag_delete_on_close, 0); + void *fh = create_file(filename, generic_read | delete_access, open_existing, 0, 0); if(fh == invalid_handle_value){ return false; } handle_closer h_closer(fh); + { + //Obtain name length + unsigned long size; + const std::size_t initial_string_mem = 512u; + + nt_query_mem_deleter nt_query_mem(sizeof(ntquery_mem_t)+initial_string_mem); + //Obtain file name with guessed length + if(pNtQueryObject(fh, object_name_information, nt_query_mem.query_mem(), nt_query_mem.object_name_information_size(), &size)){ + //Obtain file name with exact length buffer + nt_query_mem.realloc_mem(size); + if(pNtQueryObject(fh, object_name_information, nt_query_mem.query_mem(), nt_query_mem.object_name_information_size(), &size)){ + return false; + } + } + ntquery_mem_t *pmem = nt_query_mem.query_mem(); + file_rename_information_t *pfri = &pmem->ren.info; + const std::size_t RenMaxNumChars = + (((char*)(pmem) + nt_query_mem.file_rename_information_size()) - (char*)&pmem->ren.info.FileName[0])/sizeof(wchar_t); + + //Copy filename to the rename member + std::memmove(pmem->ren.info.FileName, pmem->name.Name.Buffer, pmem->name.Name.Length); + std::size_t filename_string_length = pmem->name.Name.Length/sizeof(wchar_t); + + //Search '\\' character to replace from it + for(std::size_t i = filename_string_length; i != 0; --filename_string_length){ + if(pmem->ren.info.FileName[--i] == L'\\') + break; + } - std::auto_ptr<ntquery_mem_t> pmem(new ntquery_mem_t); - file_rename_information_t *pfri = &pmem->ren.info; - const std::size_t RenMaxNumChars = - ((char*)pmem.get() - (char*)&pmem->ren.info.FileName[0])/sizeof(wchar_t); - - //Obtain file name - unsigned long size; - if(pNtQueryObject(fh, object_name_information, pmem.get(), sizeof(ntquery_mem_t), &size)){ - return false; - } - - //Copy filename to the rename member - std::memmove(pmem->ren.info.FileName, pmem->name.Name.Buffer, pmem->name.Name.Length); - std::size_t filename_string_length = pmem->name.Name.Length/sizeof(wchar_t); - - //Second step: obtain the complete native-nt filename - //if(!get_file_name_from_handle_function(fh, pfri->FileName, RenMaxNumChars, filename_string_length)){ - //return 0; - //} - - //Add trailing mark - if((RenMaxNumChars-filename_string_length) < (SystemTimeOfDayInfoLength*2)){ - return false; - } - - //Search '\\' character to replace it - for(std::size_t i = filename_string_length; i != 0; --filename_string_length){ - if(pmem->ren.info.FileName[--i] == L'\\') - break; - } - - //Add random number - std::size_t s = RenMaxNumChars - filename_string_length; - if(!get_boot_and_system_time_wstr(&pfri->FileName[filename_string_length], s)){ - return false; + //Add random number + std::size_t s = RenMaxNumChars - filename_string_length; + if(!get_boot_and_system_time_wstr(&pfri->FileName[filename_string_length], s)){ + return false; + } + filename_string_length += s; + + //Sometimes the precission of the timestamp is not enough and we need to add another random number. + //The process id (to exclude concurrent processes) and an atomic count (to exclude concurrent threads). + //should be enough + const unsigned long pid = get_current_process_id(); + buffer_to_wide_str(&pid, sizeof(pid), &pfri->FileName[filename_string_length]); + filename_string_length += sizeof(pid)*2; + + static volatile boost::uint32_t u32_count = 0; + interlocked_decrement(reinterpret_cast<volatile long*>(&u32_count)); + buffer_to_wide_str(const_cast<const boost::uint32_t *>(&u32_count), sizeof(boost::uint32_t), &pfri->FileName[filename_string_length]); + filename_string_length += sizeof(boost::uint32_t)*2; + + //Fill rename information (FileNameLength is in bytes) + pfri->FileNameLength = static_cast<unsigned long>(sizeof(wchar_t)*(filename_string_length)); + pfri->Replace = 1; + pfri->RootDir = 0; + + //Cange the name of the in-use file... + io_status_block_t io; + if(0 != pNtSetInformationFile(fh, &io, pfri, nt_query_mem.file_rename_information_size(), file_rename_information)){ + return false; + } } - filename_string_length += s; - - //Fill rename information (FileNameLength is in bytes) - pfri->FileNameLength = static_cast<unsigned long>(sizeof(wchar_t)*(filename_string_length)); - pfri->Replace = 1; - pfri->RootDir = 0; - - //Final step: change the name of the in-use file: - io_status_block_t io; - if(0 != pNtSetInformationFile(fh, &io, pfri, sizeof(ntquery_mem_t::ren_t), file_rename_information)){ - return false; + //...and mark it as delete-on-close + { + //Don't use pNtSetInformationFile with file_disposition_information as it can return STATUS_CANNOT_DELETE + //if the file is still mapped. Reopen it with NtOpenFile and file_delete_on_close + NtOpenFile_t pNtOpenFile = (NtOpenFile_t)dll_func::get(dll_func::NtOpenFile); + NtClose_t pNtClose = (NtClose_t)dll_func::get(dll_func::NtClose); + const wchar_t empty_str [] = L""; + unicode_string_t ustring = { sizeof(empty_str) - sizeof (wchar_t) //length in bytes without null + , sizeof(empty_str) //total size in bytes of memory allocated for Buffer. + , const_cast<wchar_t*>(empty_str) + }; + object_attributes_t object_attr; + initialize_object_attributes(&object_attr, &ustring, 0, fh, 0); + void* fh2 = 0; + io_status_block_t io; + pNtOpenFile( &fh2, delete_flag, &object_attr, &io + , file_share_read | file_share_write | file_share_delete, file_delete_on_close); + pNtClose(fh2); + //Even if NtOpenFile fails, the file was renamed and the original no longer exists, so return a success status + return true; } - return true; } catch(...){ return false; @@ -1567,18 +1922,16 @@ inline bool unlink_file(const char *filename) struct reg_closer { - //reg_closer(RegCloseKey_t func, void *key) : func_(func), key_(key){} - //~reg_closer(){ (*func_)(key_); } - //RegCloseKey_t func_; - void *key_; - reg_closer(void *key) : key_(key){} + hkey key_; + reg_closer(hkey key) : key_(key){} ~reg_closer(){ reg_close_key(key_); } }; inline void get_shared_documents_folder(std::string &s) { + #if 1 //Original registry search code s.clear(); - void *key; + hkey key; if (reg_open_key_ex( hkey_local_machine , "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders" , 0 @@ -1602,12 +1955,24 @@ inline void get_shared_documents_folder(std::string &s) (void)err; } } + #else //registry alternative: SHGetSpecialFolderPathA + const int BIPC_CSIDL_COMMON_APPDATA = 0x0023; // All Users\Application Data + const int BIPC_CSIDL_FLAG_CREATE = 0x8000; // new for Win2K, or this in to force creation of folder + const int BIPC_SHGFP_TYPE_CURRENT = 0; // current value for user, verify it exists + + s.clear(); + char szPath[max_path]; + if(0 == SHGetFolderPathA(0, BIPC_CSIDL_COMMON_APPDATA | BIPC_CSIDL_FLAG_CREATE, 0, BIPC_SHGFP_TYPE_CURRENT, szPath)){ + s = szPath; + } + + #endif } inline void get_registry_value(const char *folder, const char *value_key, std::vector<unsigned char> &s) { s.clear(); - void *key; + hkey key; if (reg_open_key_ex( hkey_local_machine , folder , 0 @@ -1700,7 +2065,7 @@ inline bool get_wmi_class_attribute( std::wstring& strValue, const wchar_t *wmi_ IWbemServices_BIPC *pWbemServices = 0; if( 0 != pIWbemLocator->ConnectServer( - bstrNamespace, // Namespace + (bstr)bstrNamespace, // Namespace 0, // Userid 0, // PW 0, // Locale @@ -1738,8 +2103,8 @@ inline bool get_wmi_class_attribute( std::wstring& strValue, const wchar_t *wmi_ IEnumWbemClassObject_BIPC * pEnumObject = 0; if ( 0 != pWbemServices->ExecQuery( - L"WQL", - strValue.c_str(), + (bstr)L"WQL", + (bstr)strValue.c_str(), //WBEM_FLAG_RETURN_IMMEDIATELY_BIPC, WBEM_FLAG_RETURN_WHEN_COMPLETE_BIPC | WBEM_FLAG_FORWARD_ONLY_BIPC, 0, @@ -1762,9 +2127,9 @@ inline bool get_wmi_class_attribute( std::wstring& strValue, const wchar_t *wmi_ while( 0 == pEnumObject->Next( WBEM_INFINITE_BIPC, uCount, &pClassObject, &uReturned ) ) { com_releaser<IWbemClassObject_BIPC> IWbemClassObject_releaser(pClassObject); - if ( 0 == pClassObject->Get( L"LastBootUpTime", 0, &vwchar, 0, 0 ) ){ + if ( 0 == pClassObject->Get( (bstr)L"LastBootUpTime", 0, &vwchar, 0, 0 ) ){ bRet = true; - strValue = vwchar.value.pbstrVal; + strValue = (wchar_t*)vwchar.bstrVal; VariantClear(&vwchar ); break; } @@ -1773,6 +2138,10 @@ inline bool get_wmi_class_attribute( std::wstring& strValue, const wchar_t *wmi_ return bRet; } +#ifdef BOOST_INTERPROCESS_BOOTSTAMP_IS_LASTBOOTUPTIME + +//Obtains the bootup time from WMI LastBootUpTime. +//This time seems to change with hibernation and clock synchronization so avoid it. inline bool get_last_bootup_time( std::wstring& strValue ) { bool ret = get_wmi_class_attribute(strValue, L"Win32_OperatingSystem", L"LastBootUpTime"); @@ -1798,12 +2167,110 @@ inline bool get_last_bootup_time( std::string& str ) return ret; } +#else + +// Loop through the buffer and obtain the contents of the +// requested record in the buffer. +inline bool find_record_in_buffer( const void* pBuffer, unsigned long dwBytesRead, const char *provider_name + , unsigned int id_to_find, interprocess_eventlogrecord *&pevent_log_record) +{ + const unsigned char * pRecord = static_cast<const unsigned char*>(pBuffer); + const unsigned char * pEndOfRecords = pRecord + dwBytesRead; + + while (pRecord < pEndOfRecords){ + interprocess_eventlogrecord *pTypedRecord = (interprocess_eventlogrecord*)pRecord; + // Check provider, written at the end of the fixed-part of the record + if (0 == std::strcmp(provider_name, (char*)(pRecord + sizeof(interprocess_eventlogrecord)))) + { + // Check event id + if(id_to_find == (pTypedRecord->EventID & 0xFFFF)){ + pevent_log_record = pTypedRecord; + return true; + } + } + + pRecord += pTypedRecord->Length; + } + pevent_log_record = 0; + return false; +} + +//Obtains the bootup time from the System Event Log, +//event ID == 6005 (event log started). +//Adapted from http://msdn.microsoft.com/en-us/library/windows/desktop/bb427356.aspx +inline bool get_last_bootup_time(std::string &stamp) +{ + const char *source_name = "System"; + const char *provider_name = "EventLog"; + const unsigned short event_id = 6005u; + + unsigned long status = 0; + unsigned long dwBytesToRead = 0; + unsigned long dwBytesRead = 0; + unsigned long dwMinimumBytesToRead = 0; + + // The source name (provider) must exist as a subkey of Application. + void *hEventLog = OpenEventLogA(0, source_name); + if (hEventLog){ + eventlog_handle_closer hnd_closer(hEventLog); (void)hnd_closer; + // Allocate an initial block of memory used to read event records. The number + // of records read into the buffer will vary depending on the size of each event. + // The size of each event will vary based on the size of the user-defined + // data included with each event, the number and length of insertion + // strings, and other data appended to the end of the event record. + dwBytesToRead = max_record_buffer_size; + c_heap_deleter heap_deleter(dwBytesToRead); + + // Read blocks of records until you reach the end of the log or an + // error occurs. The records are read from newest to oldest. If the buffer + // is not big enough to hold a complete event record, reallocate the buffer. + if (heap_deleter.get() != 0){ + while (0 == status){ + if (!ReadEventLogA(hEventLog, + eventlog_sequential_read | eventlog_backwards_read, + 0, + heap_deleter.get(), + dwBytesToRead, + &dwBytesRead, + &dwMinimumBytesToRead)) { + status = get_last_error(); + if (error_insufficient_buffer == status) { + status = 0; + dwBytesToRead = dwMinimumBytesToRead; + heap_deleter.realloc_mem(dwMinimumBytesToRead); + if (!heap_deleter.get()){ + return false; + } + } + else{ //Not found or EOF + return false; + } + } + else + { + interprocess_eventlogrecord *pTypedRecord; + // Print the contents of each record in the buffer. + if(find_record_in_buffer(heap_deleter.get(), dwBytesRead, provider_name, event_id, pTypedRecord)){ + char stamp_str[sizeof(unsigned long)*3+1]; + std::sprintf(&stamp_str[0], "%u", ((unsigned int)pTypedRecord->TimeGenerated)); + stamp = stamp_str; + break; + } + } + } + } + } + return true; +} + +#endif + inline bool is_directory(const char *path) { - unsigned long attrib = GetFileAttributesA(path); + unsigned long attrib = GetFileAttributesA(path); - return (attrib != invalid_file_attributes && - (attrib & file_attribute_directory)); + return (attrib != invalid_file_attributes && + (attrib & file_attribute_directory)); } inline bool get_file_mapping_size(void *file_mapping_hnd, __int64 &size) @@ -1814,11 +2281,8 @@ inline bool get_file_mapping_size(void *file_mapping_hnd, __int64 &size) interprocess_section_basic_information info; unsigned long ntstatus = pNtQuerySection(file_mapping_hnd, section_basic_information, &info, sizeof(info), 0); - if(ntstatus){ - return false; - } size = info.section_size; - return true; + return !ntstatus; } inline bool get_semaphore_info(void *handle, long &count, long &limit) @@ -1828,14 +2292,41 @@ inline bool get_semaphore_info(void *handle, long &count, long &limit) (winapi::NtQuerySemaphore_t)dll_func::get(winapi::dll_func::NtQuerySemaphore); unsigned int ret_len; long status = pNtQuerySemaphore(handle, winapi::semaphore_basic_information, &info, sizeof(info), &ret_len); - if(status){ - return false; - } count = info.count; limit = info.limit; - return true; + return !status; +} + +inline bool query_timer_resolution(unsigned long *lowres, unsigned long *highres, unsigned long *curres) +{ + winapi::NtQueryTimerResolution_t pNtQueryTimerResolution = + (winapi::NtQueryTimerResolution_t)dll_func::get(winapi::dll_func::NtQueryTimerResolution); + return !pNtQueryTimerResolution(lowres, highres, curres); +} + +inline bool set_timer_resolution(unsigned long RequestedResolution, int Set, unsigned long* ActualResolution) +{ + winapi::NtSetTimerResolution_t pNtSetTimerResolution = + (winapi::NtSetTimerResolution_t)dll_func::get(winapi::dll_func::NtSetTimerResolution); + return !pNtSetTimerResolution(RequestedResolution, Set, ActualResolution); +} + +inline bool query_performance_counter(__int64 *lpPerformanceCount) +{ + QueryPerformanceCounter_t pQueryPerformanceCounter = (QueryPerformanceCounter_t) + dll_func::get(dll_func::QueryPerformanceCounter); + return 0 != pQueryPerformanceCounter(lpPerformanceCount); +} + +inline bool query_performance_frequency(__int64 *lpFrequency) +{ + QueryPerformanceCounter_t pQueryPerformanceFrequency = (QueryPerformanceFrequency_t) + dll_func::get(dll_func::QueryPerformanceFrequency); + return 0 != pQueryPerformanceFrequency(lpFrequency); } +inline unsigned long get_tick_count() +{ return GetTickCount(); } } //namespace winapi } //namespace interprocess @@ -1843,4 +2334,4 @@ inline bool get_semaphore_info(void *handle, long &count, long &limit) #include <boost/interprocess/detail/config_end.hpp> -#endif //#ifdef BOOST_INTERPROCESS_WIN32_PRIMITIVES_HPP +#endif //#ifdef BOOST_INTERPROCESS_WIN32_API_HPP diff --git a/boost/interprocess/detail/windows_intermodule_singleton.hpp b/boost/interprocess/detail/windows_intermodule_singleton.hpp index a716e270a7..58102689da 100644 --- a/boost/interprocess/detail/windows_intermodule_singleton.hpp +++ b/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) // @@ -11,12 +11,13 @@ #ifndef BOOST_INTERPROCESS_WINDOWS_INTERMODULE_SINGLETON_HPP #define BOOST_INTERPROCESS_WINDOWS_INTERMODULE_SINGLETON_HPP -#if defined(_MSC_VER)&&(_MSC_VER>=1200) +#if defined(_MSC_VER) #pragma once #endif #include <boost/interprocess/detail/config_begin.hpp> #include <boost/interprocess/detail/workaround.hpp> +#include <boost/container/string.hpp> #if !defined(BOOST_INTERPROCESS_WINDOWS) #error "This header can't be included from non-windows operating systems" @@ -29,7 +30,7 @@ #include <boost/interprocess/sync/scoped_lock.hpp> #include <boost/cstdint.hpp> #include <string> -#include <map> +#include <boost/container/map.hpp> namespace boost{ namespace interprocess{ @@ -49,7 +50,7 @@ namespace intermodule_singleton_helpers { // max and current semaphore count. class windows_semaphore_based_map { - typedef std::map<std::string, ref_count_ptr> map_type; + typedef boost::container::map<boost::container::string, ref_count_ptr> map_type; public: windows_semaphore_based_map() @@ -68,8 +69,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. // @@ -135,6 +136,7 @@ class windows_semaphore_based_map success = success && m_sem_map.open_or_create (name.c_str(), initial_count, max_count, perm, created); if(!success){ + delete m; //winapi_xxx wrappers do the cleanup... throw int(0); } @@ -181,7 +183,7 @@ class windows_semaphore_based_map { scoped_lock<winapi_mutex_wrapper> lck(m_mtx_lock); map_type &map = this->get_map_unlocked(); - map_type::iterator it = map.find(std::string(name)); + map_type::iterator it = map.find(boost::container::string(name)); if(it != map.end()){ return &it->second; } @@ -194,7 +196,7 @@ class windows_semaphore_based_map { scoped_lock<winapi_mutex_wrapper> lck(m_mtx_lock); map_type &map = this->get_map_unlocked(); - map_type::iterator it = map.insert(map_type::value_type(std::string(name), ref)).first; + map_type::iterator it = map.insert(map_type::value_type(boost::container::string(name), ref)).first; return &it->second; } @@ -202,7 +204,7 @@ class windows_semaphore_based_map { scoped_lock<winapi_mutex_wrapper> lck(m_mtx_lock); map_type &map = this->get_map_unlocked(); - return map.erase(std::string(name)) != 0; + return map.erase(boost::container::string(name)) != 0; } template<class F> @@ -217,14 +219,16 @@ class windows_semaphore_based_map scoped_lock<winapi_mutex_wrapper> lck(m_mtx_lock); m_sem_count.wait(); if(0 == m_sem_count.value()){ - delete &this->get_map_unlocked(); + map_type &map = this->get_map_unlocked(); + BOOST_ASSERT(map.empty()); + delete ↦ } //First close sems to protect this with the external mutex m_sem_map.close(); 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; @@ -287,7 +291,7 @@ struct thread_safe_global_map_dependant<windows_semaphore_based_map> } //namespace intermodule_singleton_helpers { -template<typename C, bool LazyInit = true, bool Phoenix = true> +template<typename C, bool LazyInit = true, bool Phoenix = false> class windows_intermodule_singleton : public intermodule_singleton_impl < C diff --git a/boost/interprocess/detail/workaround.hpp b/boost/interprocess/detail/workaround.hpp index 884b8680a6..d0456b5053 100644 --- a/boost/interprocess/detail/workaround.hpp +++ b/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) // @@ -11,23 +11,46 @@ #ifndef BOOST_INTERPROCESS_DETAIL_WORKAROUND_HPP #define BOOST_INTERPROCESS_DETAIL_WORKAROUND_HPP +#if defined(_MSC_VER) +# pragma once +#endif + #include <boost/interprocess/detail/config_begin.hpp> #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) #define BOOST_INTERPROCESS_WINDOWS #define BOOST_INTERPROCESS_FORCE_GENERIC_EMULATION #define BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME + //Define this to connect with shared memory created with versions < 1.54 + //#define BOOST_INTERPROCESS_BOOTSTAMP_IS_LASTBOOTUPTIME #else #include <unistd.h> #if defined(_POSIX_THREAD_PROCESS_SHARED) && ((_POSIX_THREAD_PROCESS_SHARED - 0) > 0) //Cygwin defines _POSIX_THREAD_PROCESS_SHARED but does not implement it. - //Mac Os X >= Leopard defines _POSIX_THREAD_PROCESS_SHARED but does not seems to work. - #if !defined(__CYGWIN__) && !defined(__APPLE__) + #if defined(__CYGWIN__) + #define BOOST_INTERPROCESS_BUGGY_POSIX_PROCESS_SHARED + //Mac Os X < Lion (10.7) might define _POSIX_THREAD_PROCESS_SHARED but there is no real support. + #elif defined(__APPLE__) + #include "TargetConditionals.h" + //Check we're on Mac OS target + #if defined(TARGET_OS_MAC) + #include "AvailabilityMacros.h" + //If minimum target for this compilation is older than Mac Os Lion, then we are out of luck + #if MAC_OS_X_VERSION_MIN_REQUIRED < 1070 + #define BOOST_INTERPROCESS_BUGGY_POSIX_PROCESS_SHARED + #endif + #endif + #endif + + //If buggy _POSIX_THREAD_PROCESS_SHARED is detected avoid using it + #if defined(BOOST_INTERPROCESS_BUGGY_POSIX_PROCESS_SHARED) + #undef BOOST_INTERPROCESS_BUGGY_POSIX_PROCESS_SHARED + #else #define BOOST_INTERPROCESS_POSIX_PROCESS_SHARED #endif #endif - + #if defined(_POSIX_BARRIERS) && ((_POSIX_BARRIERS - 0) > 0) #define BOOST_INTERPROCESS_POSIX_BARRIERS #endif @@ -39,22 +62,22 @@ #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)) ||\ - ((defined _V6_LP64_OFF64) &&(_V6_LP64_OFF64 - 0 > 0)) ||\ - ((defined _V6_LPBIG_OFFBIG) &&(_V6_LPBIG_OFFBIG - 0 > 0)) ||\ - ((defined _XBS5_ILP32_OFFBIG)&&(_XBS5_ILP32_OFFBIG - 0 > 0)) ||\ - ((defined _XBS5_LP64_OFF64) &&(_XBS5_LP64_OFF64 - 0 > 0)) ||\ - ((defined _XBS5_LPBIG_OFFBIG)&&(_XBS5_LPBIG_OFFBIG - 0 > 0)) ||\ - ((defined _FILE_OFFSET_BITS) &&(_FILE_OFFSET_BITS - 0 >= 64))||\ - ((defined _FILE_OFFSET_BITS) &&(_FILE_OFFSET_BITS - 0 >= 64)) + #if (defined (_V6_ILP32_OFFBIG) &&(_V6_ILP32_OFFBIG - 0 > 0)) ||\ + (defined (_V6_LP64_OFF64) &&(_V6_LP64_OFF64 - 0 > 0)) ||\ + (defined (_V6_LPBIG_OFFBIG) &&(_V6_LPBIG_OFFBIG - 0 > 0)) ||\ + (defined (_XBS5_ILP32_OFFBIG)&&(_XBS5_ILP32_OFFBIG - 0 > 0)) ||\ + (defined (_XBS5_LP64_OFF64) &&(_XBS5_LP64_OFF64 - 0 > 0)) ||\ + (defined (_XBS5_LPBIG_OFFBIG)&&(_XBS5_LPBIG_OFFBIG - 0 > 0)) ||\ + (defined (_FILE_OFFSET_BITS) &&(_FILE_OFFSET_BITS - 0 >= 64))||\ + (defined (_FILE_OFFSET_BITS) &&(_FILE_OFFSET_BITS - 0 >= 64)) #define BOOST_INTERPROCESS_UNIX_64_BIT_OR_BIGGER_OFF_T #endif //Check for XSI shared memory objects. They are available in nearly all UNIX platforms - #if !defined(__QNXNTO__) + #if !defined(__QNXNTO__) && !defined(__ANDROID__) #define BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS #endif @@ -90,6 +113,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 @@ -108,6 +133,10 @@ #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__) #define BOOST_INTERPROCESS_BSD_DERIVATIVE + //Some *BSD systems (OpenBSD & NetBSD) need sys/param.h before sys/sysctl.h, whereas + //others (FreeBSD & Darwin) need sys/types.h + #include <sys/types.h> + #include <sys/param.h> #include <sys/sysctl.h> #if defined(CTL_KERN) && defined (KERN_BOOTTIME) //#define BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME @@ -115,7 +144,7 @@ #endif #endif //!defined(BOOST_INTERPROCESS_WINDOWS) -#if !defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_NO_VARIADIC_TEMPLATES) +#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) #define BOOST_INTERPROCESS_PERFECT_FORWARDING #endif @@ -130,6 +159,44 @@ #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 + +//Macros for documentation purposes. For code, expands to the argument +#define BOOST_INTERPROCESS_IMPDEF(TYPE) TYPE +#define BOOST_INTERPROCESS_SEEDOC(TYPE) TYPE + +#if defined(BOOST_NO_CXX11_NOEXCEPT) + #if defined(BOOST_MSVC) + #define BOOST_INTERPROCESS_NOEXCEPT throw() + #else + #define BOOST_INTERPROCESS_NOEXCEPT + #endif + #define BOOST_INTERPROCESS_NOEXCEPT_IF(x) +#else + #define BOOST_INTERPROCESS_NOEXCEPT noexcept + #define BOOST_INTERPROCESS_NOEXCEPT_IF(x) noexcept(x) +#endif + #include <boost/interprocess/detail/config_end.hpp> #endif //#ifndef BOOST_INTERPROCESS_DETAIL_WORKAROUND_HPP diff --git a/boost/interprocess/detail/xsi_shared_memory_device.hpp b/boost/interprocess/detail/xsi_shared_memory_device.hpp index ef4b009bc1..5bb077179a 100644 --- a/boost/interprocess/detail/xsi_shared_memory_device.hpp +++ b/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) // @@ -11,6 +11,10 @@ #ifndef BOOST_INTERPROCESS_XSI_SHARED_MEMORY_DEVICE_HPP #define BOOST_INTERPROCESS_XSI_SHARED_MEMORY_DEVICE_HPP +#if defined(_MSC_VER) +# pragma once +#endif + #include <boost/interprocess/detail/config_begin.hpp> #include <boost/interprocess/detail/workaround.hpp> #include <boost/detail/workaround.hpp> @@ -23,7 +27,7 @@ #include <boost/interprocess/exceptions.hpp> #include <boost/interprocess/detail/utilities.hpp> #include <boost/interprocess/detail/os_file_functions.hpp> -#include <boost/interprocess/detail/tmp_dir_helpers.hpp> +#include <boost/interprocess/detail/shared_dir_helpers.hpp> #include <boost/interprocess/interprocess_fwd.hpp> #include <boost/interprocess/exceptions.hpp> @@ -44,9 +48,9 @@ namespace interprocess { class xsi_shared_memory_device { - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) BOOST_MOVABLE_BUT_NOT_COPYABLE(xsi_shared_memory_file_wrapper) - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: @@ -74,10 +78,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 @@ -113,7 +117,7 @@ class xsi_shared_memory_device //!Returns false on error. Never throws static bool remove(int shmid); - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: template<int Dummy> struct info_constants_t @@ -147,7 +151,7 @@ class xsi_shared_memory_device xsi_shared_memory m_shm; mode_t m_mode; std::string m_name; - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }; template<int Dummy> @@ -162,7 +166,7 @@ const std::size_t xsi_shared_memory_device::info_constants_t<Dummy>::LastID; template<int Dummy> const std::size_t xsi_shared_memory_device::info_constants_t<Dummy>::NumID; -/// @cond +#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) inline xsi_shared_memory_device::xsi_shared_memory_device() : m_shm(), m_mode(invalid_mode), m_name() @@ -178,7 +182,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 @@ -197,7 +201,7 @@ inline void xsi_shared_memory_device::priv_obtain_index permissions p; p.set_unrestricted(); std::string xsi_shm_emulation_file_path; - ipcdetail::create_tmp_and_clean_old_and_get_filename(filename, xsi_shm_emulation_file_path); + ipcdetail::create_shared_dir_cleaning_old_and_get_filepath(filename, xsi_shm_emulation_file_path); ipcdetail::create_or_open_file(xsi_shm_emulation_file_path.c_str(), read_write, p); const std::size_t MemSize = sizeof(info_t); @@ -382,7 +386,7 @@ inline bool xsi_shared_memory_device::remove(const char *shmname) inline bool xsi_shared_memory_device::remove(int shmid) { return xsi_shared_memory::remove(shmid); } -///@endcond +#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED } //namespace interprocess { } //namespace boost { diff --git a/boost/interprocess/detail/xsi_shared_memory_file_wrapper.hpp b/boost/interprocess/detail/xsi_shared_memory_file_wrapper.hpp index 14811e7e62..d1c71d55f5 100644 --- a/boost/interprocess/detail/xsi_shared_memory_file_wrapper.hpp +++ b/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) // @@ -11,6 +11,10 @@ #ifndef BOOST_INTERPROCESS_XSI_SHARED_MEMORY_FILE_WRAPPER_HPP #define BOOST_INTERPROCESS_XSI_SHARED_MEMORY_FILE_WRAPPER_HPP +#if defined(_MSC_VER) +# pragma once +#endif + #include <boost/interprocess/detail/config_begin.hpp> #include <boost/interprocess/detail/workaround.hpp> #include <boost/detail/workaround.hpp> @@ -23,7 +27,7 @@ #include <boost/interprocess/exceptions.hpp> #include <boost/interprocess/detail/utilities.hpp> #include <boost/interprocess/detail/os_file_functions.hpp> -#include <boost/interprocess/detail/tmp_dir_helpers.hpp> +#include <boost/interprocess/detail/shared_dir_helpers.hpp> #include <boost/interprocess/interprocess_fwd.hpp> #include <boost/interprocess/exceptions.hpp> @@ -38,22 +42,22 @@ namespace interprocess { class xsi_shared_memory_file_wrapper : public xsi_shared_memory { - /// @cond + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) BOOST_MOVABLE_BUT_NOT_COPYABLE(xsi_shared_memory_file_wrapper) - /// @endcond + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: xsi_shared_memory_file_wrapper() : xsi_shared_memory() {} - xsi_shared_memory_file_wrapper(create_only_t, const xsi_key &key, mode_t mode, std::size_t size, const permissions& perm = permissions()) + xsi_shared_memory_file_wrapper(create_only_t, const xsi_key &key, mode_t , std::size_t size, const permissions& perm = permissions()) : xsi_shared_memory(create_only_t(), key, size, perm.get_permissions()) {} - xsi_shared_memory_file_wrapper(open_or_create_t, const xsi_key &key, mode_t mode, std::size_t size, const permissions& perm = permissions()) + xsi_shared_memory_file_wrapper(open_or_create_t, const xsi_key &key, mode_t , std::size_t size, const permissions& perm = permissions()) : xsi_shared_memory(open_or_create_t(), key, size, perm.get_permissions()) {} - xsi_shared_memory_file_wrapper(open_only_t, const xsi_key &key, mode_t mode, const permissions& perm = permissions()) + xsi_shared_memory_file_wrapper(open_only_t, const xsi_key &key, mode_t, const permissions& = permissions()) : xsi_shared_memory(open_only_t(), key) {} @@ -61,10 +65,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 |