diff --git a/doc/interprocess.qbk b/doc/interprocess.qbk index 8da5f63..0139b61 100644 --- a/doc/interprocess.qbk +++ b/doc/interprocess.qbk @@ -6754,6 +6754,21 @@ thank them: [section:release_notes Release Notes] +[section:release_notes_boost_1_64_00 Boost 1.64 Release] +* Fixed bugs: + * [@https://svn.boost.org/trac/boost/ticket/12617 Trac #12617 (['"clock_gettime not available on OS X 10.11"])]. + * [@https://svn.boost.org/trac/boost/ticket/12744 Trac #12744 (['"winapi::set_timer_resolution inadvertently changes timer resolution (Windows)"])]. + * [@https://github.com/boostorg/interprocess/pull/32 GitHub Pull #32 (['"Conform to std::pointer_traits requirements"])]. + * [@https://github.com/boostorg/interprocess/pull/33 GitHub Pull #33 (['"explicit cast to derived class" and "64/32 bit processes sharing"])]. + * [@https://github.com/boostorg/interprocess/pull/34 GitHub Pull #34 (['"Update example to use multi_index::member instead of BOOST_MULTI_INDEX_MEMBER"])]. + * [@https://github.com/boostorg/interprocess/pull/35 GitHub Pull #35 (['"Fixed options for cross-compilation"])]. + +* New experimental option `BOOST_INTERPROCESS_BOOTSTAMP_IS_SESSION_MANAGER_BASED` from Windows systems. + This option derives the unique booststamp used to name the folder where shared memory is placed from registry values associated + with the session manager. This option only works on Vista and later systems and might be more stable than the default version. + +[endsect] + [section:release_notes_boost_1_63_00 Boost 1.63 Release] * Fixed bugs: * [@https://svn.boost.org/trac/boost/ticket/12499 Trac #12499 (['"Memory allocation fails"])]. @@ -6770,7 +6785,7 @@ thank them: [section:release_notes_boost_1_61_00 Boost 1.61 Release] * Fixed bugs: - * [@https://github.com/boostorg/interprocess/pull/23 GitHub Pull #23 (['"Fixed case sensetive for linux mingw"])]. + * [@https://github.com/boostorg/interprocess/pull/23 GitHub Pull #23 (['"Fixed case sensitive for linux mingw"])]. [endsect] diff --git a/example/Jamfile.v2 b/example/Jamfile.v2 index ac4f4ab..22da3e0 100644 --- a/example/Jamfile.v2 +++ b/example/Jamfile.v2 @@ -26,9 +26,9 @@ rule test_all acc:-lrt acc-pa_risc:-lrt gcc,windows:"-lole32 -loleaut32 -lpsapi -ladvapi32" - hpux,gcc:"-Wl,+as,mpas" - windows,clang:"-lole32 -loleaut32 -lpsapi -ladvapi32" - linux:"-lrt" + hpux,gcc:"-Wl,+as,mpas" + windows,clang:"-lole32 -loleaut32 -lpsapi -ladvapi32" + linux:"-lrt" : # test-files : # requirements ] ; @@ -43,9 +43,9 @@ rule test_all acc:-lrt acc-pa_risc:-lrt gcc-mingw:"-lole32 -loleaut32 -lpsapi -ladvapi32" - hpux,gcc:"-Wl,+as,mpas" - windows,clang:"-lole32 -loleaut32 -lpsapi -ladvapi32" - linux:"-lrt" + hpux,gcc:"-Wl,+as,mpas" + windows,clang:"-lole32 -loleaut32 -lpsapi -ladvapi32" + linux:"-lrt" ] ; } diff --git a/example/doc_multi_index.cpp b/example/doc_multi_index.cpp index e1ef258..df4fd72 100644 --- a/example/doc_multi_index.cpp +++ b/example/doc_multi_index.cpp @@ -61,11 +61,11 @@ typedef bmi::multi_index_container< employee, bmi::indexed_by< bmi::ordered_unique - , BOOST_MULTI_INDEX_MEMBER(employee,int,id)>, + , bmi::member >, bmi::ordered_non_unique< - bmi::tag,BOOST_MULTI_INDEX_MEMBER(employee,shm_string,name)>, + bmi::tag, bmi::member >, bmi::ordered_non_unique - , BOOST_MULTI_INDEX_MEMBER(employee,int,age)> >, + , bmi::member > >, managed_shared_memory::allocator::type > employee_set; diff --git a/include/boost/interprocess/detail/os_file_functions.hpp b/include/boost/interprocess/detail/os_file_functions.hpp index bcb9576..7a41868 100644 --- a/include/boost/interprocess/detail/os_file_functions.hpp +++ b/include/boost/interprocess/detail/os_file_functions.hpp @@ -102,6 +102,9 @@ 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 bool remove_directory(const char *path) +{ return winapi::remove_directory(path); } + inline bool get_temporary_path(char *buffer, std::size_t buf_len, std::size_t &required_len) { required_len = 0; @@ -422,6 +425,9 @@ 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 bool remove_directory(const char *path) +{ return ::rmdir(path) == 0; } + inline bool get_temporary_path(char *buffer, std::size_t buf_len, std::size_t &required_len) { required_len = 5u; diff --git a/include/boost/interprocess/detail/os_thread_functions.hpp b/include/boost/interprocess/detail/os_thread_functions.hpp index 3ff0a40..8a0a47c 100644 --- a/include/boost/interprocess/detail/os_thread_functions.hpp +++ b/include/boost/interprocess/detail/os_thread_functions.hpp @@ -53,7 +53,12 @@ # include # endif //According to the article "C/C++ tip: How to measure elapsed real time for benchmarking" -# if defined(CLOCK_MONOTONIC_PRECISE) //BSD +//Check MacOs first as macOS 10.12 SDK defines both CLOCK_MONOTONIC and +//CLOCK_MONOTONIC_RAW and no clock_gettime. +# if (defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)) +# include // mach_absolute_time, mach_timebase_info_data_t +# define BOOST_INTERPROCESS_MATCH_ABSOLUTE_TIME +# elif 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 @@ -61,9 +66,6 @@ # 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_absolute_time, mach_timebase_info_data_t -# define BOOST_INTERPROCESS_MATCH_ABSOLUTE_TIME # else # error "No high resolution steady clock in your system, please provide a patch" # endif @@ -112,8 +114,8 @@ inline bool equal_thread_id(OS_thread_id_t id1, OS_thread_id_t id2) //return the system tick in ns inline unsigned long get_system_tick_ns() { - unsigned long curres; - winapi::set_timer_resolution(10000, 0, &curres); + unsigned long curres, ignore1, ignore2; + winapi::query_timer_resolution(&ignore1, &ignore2, &curres); //Windows API returns the value in hundreds of ns return (curres - 1ul)*100ul; } @@ -121,8 +123,8 @@ inline unsigned long get_system_tick_ns() //return the system tick in us inline unsigned long get_system_tick_us() { - unsigned long curres; - winapi::set_timer_resolution(10000, 0, &curres); + unsigned long curres, ignore1, ignore2; + winapi::query_timer_resolution(&ignore1, &ignore2, &curres); //Windows API returns the value in hundreds of ns return (curres - 1ul)/10ul + 1ul; } @@ -132,8 +134,8 @@ 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); + unsigned long curres, ignore1, ignore2; + winapi::query_timer_resolution(&ignore1, &ignore2, &curres); //Frequency in counts per second if(!winapi::query_performance_frequency(&freq)){ //Tick resolution in ms diff --git a/include/boost/interprocess/detail/utilities.hpp b/include/boost/interprocess/detail/utilities.hpp index e1be2f1..c1b2342 100644 --- a/include/boost/interprocess/detail/utilities.hpp +++ b/include/boost/interprocess/detail/utilities.hpp @@ -156,29 +156,29 @@ BOOST_INTERPROCESS_FORCEINLINE bool size_overflows(SizeType count) return multiplication_overflows(SizeType(SztSizeOfType), count); } -template -class pointer_uintptr_caster; +template +class pointer_offset_caster; -template -class pointer_uintptr_caster +template +class pointer_offset_caster { public: - BOOST_INTERPROCESS_FORCEINLINE explicit pointer_uintptr_caster(uintptr_t sz) - : m_uintptr(sz) + BOOST_INTERPROCESS_FORCEINLINE explicit pointer_offset_caster(OffsetType offset) + : m_offset(offset) {} - BOOST_INTERPROCESS_FORCEINLINE explicit pointer_uintptr_caster(const volatile T *p) - : m_uintptr(reinterpret_cast(p)) + BOOST_INTERPROCESS_FORCEINLINE explicit pointer_offset_caster(const volatile T *p) + : m_offset(reinterpret_cast(p)) {} - BOOST_INTERPROCESS_FORCEINLINE uintptr_t uintptr() const - { return m_uintptr; } + BOOST_INTERPROCESS_FORCEINLINE OffsetType offset() const + { return m_offset; } BOOST_INTERPROCESS_FORCEINLINE T* pointer() const - { return reinterpret_cast(m_uintptr); } + { return reinterpret_cast(m_offset); } private: - uintptr_t m_uintptr; + OffsetType m_offset; }; diff --git a/include/boost/interprocess/detail/win32_api.hpp b/include/boost/interprocess/detail/win32_api.hpp index 02c7b42..1ea8cec 100644 --- a/include/boost/interprocess/detail/win32_api.hpp +++ b/include/boost/interprocess/detail/win32_api.hpp @@ -31,9 +31,45 @@ #include #include +//#define BOOST_INTERPROCESS_BOOTSTAMP_IS_LASTBOOTUPTIME +//#define BOOST_INTERPROCESS_BOOTSTAMP_IS_EVENTLOG_BASED +//#define BOOST_INTERPROCESS_BOOTSTAMP_IS_SESSION_MANAGER_BASED + +#ifdef BOOST_INTERPROCESS_BOOTSTAMP_IS_LASTBOOTUPTIME +# define BOOST_INTERPROCESS_BOOTSTAMP_IS_LASTBOOTUPTIME_VALUE 1 +#else +# define BOOST_INTERPROCESS_BOOTSTAMP_IS_LASTBOOTUPTIME_VALUE 0 +#endif + +#ifdef BOOST_INTERPROCESS_BOOTSTAMP_IS_EVENTLOG_BASED +# define BOOST_INTERPROCESS_BOOTSTAMP_IS_EVENTLOG_BASED_VALUE 1 +#else +# define BOOST_INTERPROCESS_BOOTSTAMP_IS_EVENTLOG_BASED_VALUE 0 +#endif + +#ifdef BOOST_INTERPROCESS_BOOTSTAMP_IS_SESSION_MANAGER_BASED +# define BOOST_INTERPROCESS_BOOTSTAMP_IS_SESSION_MANAGER_BASED_VALUE 1 +#else +# define BOOST_INTERPROCESS_BOOTSTAMP_IS_SESSION_MANAGER_BASED_VALUE 0 +#endif + +#define BOOST_INTERPROCESS_BOOTSTAMP_VALUE_SUM \ + (BOOST_INTERPROCESS_BOOTSTAMP_IS_EVENTLOG_BASED_VALUE + \ + BOOST_INTERPROCESS_BOOTSTAMP_IS_SESSION_MANAGER_BASED_VALUE + \ + BOOST_INTERPROCESS_BOOTSTAMP_IS_LASTBOOTUPTIME_VALUE) + +#if 1 < BOOST_INTERPROCESS_BOOTSTAMP_VALUE_SUM +# error "Only one of BOOST_INTERPROCESS_BOOTSTAMP_IS_LASTBOOTUPTIME, \ + BOOST_INTERPROCESS_BOOTSTAMP_IS_SESSION_MANAGER_BASED and \ + BOOST_INTERPROCESS_BOOTSTAMP_IS_EVENTLOG_BASED can be defined" +#endif + +#if 0 == BOOST_INTERPROCESS_BOOTSTAMP_VALUE_SUM +# define BOOST_INTERPROCESS_BOOTSTAMP_IS_EVENTLOG_BASED +#endif + #ifdef BOOST_USE_WINDOWS_H #include - # if defined(BOOST_INTERPROCESS_BOOTSTAMP_IS_LASTBOOTUPTIME) # include # include @@ -1162,6 +1198,23 @@ const unsigned long COINIT_MULTITHREADED_BIPC = 0x0; const unsigned long COINIT_DISABLE_OLE1DDE_BIPC = 0x4; const unsigned long COINIT_SPEED_OVER_MEMORY_BIPC = 0x4; +// Registry types +#define reg_none ( 0 ) // No value type +#define reg_sz ( 1 ) // Unicode nul terminated string +#define reg_expand_sz ( 2 ) // Unicode nul terminated string + // (with environment variable references) +#define reg_binary ( 3 ) // Free form binary +#define reg_dword ( 4 ) // 32-bit number +#define reg_dword_little_endian ( 4 ) // 32-bit number (same as REG_DWORD) +#define reg_dword_big_endian ( 5 ) // 32-bit number +#define reg_link ( 6 ) // Symbolic Link (unicode) +#define reg_multi_sz ( 7 ) // Multiple Unicode strings +#define reg_resource_list ( 8 ) // Resource list in the resource map +#define reg_full_resource_descriptor ( 9 ) // Resource list in the hardware description +#define reg_resource_requirements_list ( 10 ) +#define reg_qword ( 11 ) // 64-bit number +#define reg_qword_little_endian ( 11 ) // 64-bit number (same as reg_qword) + //If the user needs to change default COM initialization model, //it can define BOOST_INTERPROCESS_WINDOWS_COINIT_MODEL to one of these: @@ -1654,28 +1707,6 @@ 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 -{ - if(s < (BootstampLength*2)) - return false; - system_timeofday_information info; - bool ret = get_system_time_of_day_information(info); - if(!ret){ - return false; - } - const char Characters [] = - { '0', '1', '2', '3', '4', '5', '6', '7' - , '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; - std::size_t char_counter = 0; - for(std::size_t i = 0; i != static_cast(BootstampLength); ++i){ - bootstamp_str[char_counter++] = Characters[(info.Reserved1[i]&0xF0)>>4]; - bootstamp_str[char_counter++] = Characters[(info.Reserved1[i]&0x0F)]; - } - s = BootstampLength*2; - return true; -} - //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) @@ -1691,6 +1722,37 @@ inline void buffer_to_wide_str(const void *buf, std::size_t length, wchar_t *str } } +//Writes the hexadecimal value of the buffer, in the narrow character string. +//str must be twice length +inline void buffer_to_narrow_str(const void *buf, std::size_t length, char *str) +{ + const char Characters [] = + { '0', '1', '2', '3', '4', '5', '6', '7' + , '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + std::size_t char_counter = 0; + const char *chbuf = static_cast(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_time_str(char *bootstamp_str, std::size_t &s) + //will write BootstampLength chars +{ + if(s < (BootstampLength*2)) + return false; + system_timeofday_information info; + bool ret = get_system_time_of_day_information(info); + if(!ret){ + return false; + } + + buffer_to_narrow_str(info.Reserved1, BootstampLength, bootstamp_str); + s = BootstampLength*2; + return true; +} + inline bool get_boot_and_system_time_wstr(wchar_t *bootsystemstamp, std::size_t &s) //will write BootAndSystemstampLength chars { @@ -1748,7 +1810,7 @@ class nt_query_mem_deleter (SystemTimeOfDayInfoLength + sizeof(unsigned long) + sizeof(boost::uint32_t))*2; public: - nt_query_mem_deleter(std::size_t object_name_information_size) + explicit 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]) {} @@ -1786,7 +1848,7 @@ class nt_query_mem_deleter class c_heap_deleter { public: - c_heap_deleter(std::size_t size) + explicit c_heap_deleter(std::size_t size) : m_buf(::malloc(size)) {} @@ -1935,13 +1997,35 @@ struct reg_closer ~reg_closer(){ reg_close_key(key_); } }; -inline void get_shared_documents_folder(std::string &s) +inline bool get_registry_value_buffer(hkey key_type, const char *subkey_name, const char *value_name, void *buf, std::size_t &buflen) { - #if 1 //Original registry search code + bool bret = false; + hkey key; + if (reg_open_key_ex( key_type + , subkey_name + , 0 + , key_query_value + , &key) == 0){ + reg_closer key_closer(key); + + //Obtain the value + unsigned long size = buflen; + unsigned long type; + buflen = 0; + bret = 0 == reg_query_value_ex( key, value_name, 0, &type, (unsigned char*)buf, &size); + if(bret) + buflen = (std::size_t)size; + } + return bret; +} + +inline bool get_registry_value_string(hkey key_type, const char *subkey_name, const char *value_name, std::string &s) +{ + bool bret = false; s.clear(); hkey key; - if (reg_open_key_ex( hkey_local_machine - , "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders" + if (reg_open_key_ex( key_type + , subkey_name , 0 , key_query_value , &key) == 0){ @@ -1950,19 +2034,28 @@ inline void get_shared_documents_folder(std::string &s) //Obtain the value unsigned long size; unsigned long type; - const char *const reg_value = "Common AppData"; - //long err = (*pRegQueryValue)( key, reg_value, 0, &type, 0, &size); - long err = reg_query_value_ex( key, reg_value, 0, &type, 0, &size); - if(!err){ + long err = reg_query_value_ex( key, value_name, 0, &type, 0, &size); + if((reg_sz == type || reg_expand_sz != type) && !err){ //Size includes terminating NULL s.resize(size); - //err = (*pRegQueryValue)( key, reg_value, 0, &type, (unsigned char*)(&s[0]), &size); - err = reg_query_value_ex( key, reg_value, 0, &type, (unsigned char*)(&s[0]), &size); - if(!err) + err = reg_query_value_ex( key, value_name, 0, &type, (unsigned char*)(&s[0]), &size); + if(!err){ s.erase(s.end()-1); + bret = true; + } (void)err; } } + return bret; +} + +inline void get_shared_documents_folder(std::string &s) +{ + #if 1 //Original registry search code + get_registry_value_string( hkey_local_machine + , "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders" + , "Common AppData" + , s); #else //registry alternative: SHGetFolderPath 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 @@ -2175,7 +2268,9 @@ inline bool get_last_bootup_time( std::string& str ) return ret; } -#else +#endif //BOOST_INTERPROCESS_BOOTSTAMP_IS_LASTBOOTUPTIME + +#if defined(BOOST_INTERPROCESS_BOOTSTAMP_IS_EVENTLOG_BASED) // Loop through the buffer and obtain the contents of the // requested record in the buffer. @@ -2271,7 +2366,41 @@ inline bool get_last_bootup_time(std::string &stamp) return true; } -#endif +#endif //BOOST_INTERPROCESS_BOOTSTAMP_IS_EVENTLOG_BASED + +#if defined(BOOST_INTERPROCESS_BOOTSTAMP_IS_SESSION_MANAGER_BASED) + +inline bool get_last_bootup_time(std::string &stamp) +{ + unsigned dword_val = 0; + std::size_t dword_size = sizeof(dword_val); + bool b_ret = get_registry_value_buffer( hkey_local_machine + , "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management\\PrefetchParameters" + , "BootId", &dword_val, dword_size); + if (b_ret) + { + char dword_str[sizeof(dword_val)*2u+1]; + buffer_to_narrow_str(&dword_val, dword_size, dword_str); + dword_str[sizeof(dword_val)*2] = '\0'; + stamp = dword_str; + + b_ret = get_registry_value_buffer( hkey_local_machine + , "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Power" + , "HybridBootAnimationTime", &dword_val, dword_size); + //Old Windows versions have no HybridBootAnimationTime + if(b_ret) + { + buffer_to_narrow_str(&dword_val, dword_size, dword_str); + dword_str[sizeof(dword_val)*2] = '\0'; + stamp += "_"; + stamp += dword_str; + } + b_ret = true; + } + return b_ret; +} + +#endif //BOOST_INTERPROCESS_BOOTSTAMP_IS_SESSION_MANAGER_BASED inline bool is_directory(const char *path) { diff --git a/include/boost/interprocess/offset_ptr.hpp b/include/boost/interprocess/offset_ptr.hpp index fca444e..24b044a 100644 --- a/include/boost/interprocess/offset_ptr.hpp +++ b/include/boost/interprocess/offset_ptr.hpp @@ -23,6 +23,9 @@ #include #include +#include +#include +#include #include #include @@ -55,6 +58,7 @@ namespace ipcdetail { union offset_ptr_internal { BOOST_STATIC_ASSERT(sizeof(OffsetType) >= sizeof(uintptr_t)); + BOOST_STATIC_ASSERT(boost::is_integral::value && boost::is_unsigned::value); explicit offset_ptr_internal(OffsetType off) : m_offset(off) @@ -81,20 +85,21 @@ namespace ipcdetail { // //////////////////////////////////////////////////////////////////////// #define BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_PTR - BOOST_INTERPROCESS_FORCEINLINE void * offset_ptr_to_raw_pointer(const volatile void *this_ptr, uintptr_t offset) + template + BOOST_INTERPROCESS_FORCEINLINE void * offset_ptr_to_raw_pointer(const volatile void *this_ptr, OffsetType offset) { - typedef pointer_uintptr_caster caster_t; + typedef pointer_offset_caster caster_t; #ifndef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_PTR if(offset == 1){ return 0; } else{ - return caster_t(caster_t(this_ptr).uintptr() + offset).pointer(); + return caster_t(caster_t(this_ptr).offset() + offset).pointer(); } #else - uintptr_t mask = offset == 1; + OffsetType mask = offset == 1; --mask; - uintptr_t target_offset = caster_t(this_ptr).uintptr() + offset; + OffsetType target_offset = caster_t(this_ptr).offset() + offset; target_offset &= mask; return caster_t(target_offset).pointer(); #endif @@ -106,27 +111,28 @@ namespace ipcdetail { // //////////////////////////////////////////////////////////////////////// #define BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF - BOOST_INTERPROCESS_FORCEINLINE uintptr_t offset_ptr_to_offset(const volatile void *ptr, const volatile void *this_ptr) + template + BOOST_INTERPROCESS_FORCEINLINE OffsetType offset_ptr_to_offset(const volatile void *ptr, const volatile void *this_ptr) { - typedef pointer_uintptr_caster caster_t; + typedef pointer_offset_caster caster_t; #ifndef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF //offset == 1 && ptr != 0 is not legal for this pointer if(!ptr){ return 1; } else{ - uintptr_t offset = caster_t(ptr).uintptr() - caster_t(this_ptr).uintptr(); + OffsetType offset = caster_t(ptr).offset()- caster_t(this_ptr).offset(); BOOST_ASSERT(offset != 1); return offset; } #else - //const uintptr_t other = -uintptr_t(ptr != 0); - //const uintptr_t offset = (caster_t(ptr).uintptr() - caster_t(this_ptr).uintptr()) & other; - //return offset + uintptr_t(!other); + //const OffsetType other = -OffsetType(ptr != 0); + //const OffsetType offset = (caster_t(ptr).offset() - caster_t(this_ptr).offset()) & other; + //return offset + OffsetType(!other); // - uintptr_t offset = caster_t(ptr).uintptr() - caster_t(this_ptr).uintptr(); + OffsetType offset = caster_t(ptr).offset() - caster_t(this_ptr).offset(); --offset; - uintptr_t mask = uintptr_t(ptr == 0); + OffsetType mask = ptr == 0; --mask; offset &= mask; return ++offset; @@ -139,28 +145,29 @@ namespace ipcdetail { // //////////////////////////////////////////////////////////////////////// #define BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF_FROM_OTHER - BOOST_INTERPROCESS_FORCEINLINE uintptr_t offset_ptr_to_offset_from_other - (const volatile void *this_ptr, const volatile void *other_ptr, uintptr_t other_offset) + template + BOOST_INTERPROCESS_FORCEINLINE OffsetType offset_ptr_to_offset_from_other + (const volatile void *this_ptr, const volatile void *other_ptr, OffsetType other_offset) { - typedef pointer_uintptr_caster caster_t; + typedef pointer_offset_caster caster_t; #ifndef BOOST_INTERPROCESS_OFFSET_PTR_BRANCHLESS_TO_OFF_FROM_OTHER if(other_offset == 1){ return 1; } else{ - uintptr_t offset = caster_t(other_ptr).uintptr() - caster_t(this_ptr).uintptr() + other_offset; + OffsetType offset = caster_t(other_ptr).offset() - caster_t(this_ptr).offset() + other_offset; BOOST_ASSERT(offset != 1); return offset; } #else - uintptr_t mask = other_offset == 1; + OffsetType mask = other_offset == 1; --mask; - uintptr_t offset = caster_t(other_ptr).uintptr() - caster_t(this_ptr).uintptr(); + OffsetType offset = caster_t(other_ptr).offset() - caster_t(this_ptr).offset(); offset &= mask; return offset + other_offset; - //uintptr_t mask = -uintptr_t(other_offset != 1); - //uintptr_t offset = caster_t(other_ptr).uintptr() - caster_t(this_ptr).uintptr(); + //OffsetType mask = -OffsetType(other_offset != 1); + //OffsetType offset = caster_t(other_ptr).offset() - caster_t(this_ptr).offset(); //offset &= mask; //return offset + other_offset; #endif @@ -215,9 +222,9 @@ namespace ipcdetail { //! //!Note: offset_ptr uses implementation defined properties, present in most platforms, for //!performance reasons: -//! - Assumes that uintptr_t representation of nullptr is (uintptr_t)zero. -//! - Assumes that incrementing a uintptr_t obtained from a pointer is equivalent -//! to incrementing the pointer and then converting it back to uintptr_t. +//! - Assumes that OffsetType representation of nullptr is (OffsetType)zero. +//! - Assumes that incrementing a OffsetType obtained from a pointer is equivalent +//! to incrementing the pointer and then converting it back to OffsetType. template class offset_ptr { @@ -251,7 +258,7 @@ class offset_ptr //!Constructor from raw pointer (allows "0" pointer conversion). //!Never throws. BOOST_INTERPROCESS_FORCEINLINE offset_ptr(pointer ptr) BOOST_NOEXCEPT - : internal(static_cast(ipcdetail::offset_ptr_to_offset(ptr, this))) + : internal(ipcdetail::offset_ptr_to_offset(ptr, this)) {} //!Constructor from other pointer. @@ -259,78 +266,81 @@ class offset_ptr template BOOST_INTERPROCESS_FORCEINLINE offset_ptr( T *ptr , typename ipcdetail::enable_if< ::boost::is_convertible >::type * = 0) BOOST_NOEXCEPT - : internal(static_cast - (ipcdetail::offset_ptr_to_offset(static_cast(ptr), this))) + : internal(ipcdetail::offset_ptr_to_offset(static_cast(ptr), this)) {} //!Constructor from other offset_ptr //!Never throws. BOOST_INTERPROCESS_FORCEINLINE offset_ptr(const offset_ptr& ptr) BOOST_NOEXCEPT - : internal(static_cast - (ipcdetail::offset_ptr_to_offset_from_other(this, &ptr, ptr.internal.m_offset))) + : internal(ipcdetail::offset_ptr_to_offset_from_other(this, &ptr, ptr.internal.m_offset)) {} - //!Constructor from other offset_ptr. If pointers of pointee types are - //!convertible, offset_ptrs will be convertibles. Never throws. + //!Constructor from other offset_ptr. Only takes part in overload resolution + //!if T2* is convertible to PointedType*. Never throws. template BOOST_INTERPROCESS_FORCEINLINE offset_ptr( const offset_ptr &ptr #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED , typename ipcdetail::enable_if_convertible_equal_address::type* = 0 #endif ) BOOST_NOEXCEPT - : internal(static_cast - (ipcdetail::offset_ptr_to_offset_from_other(this, &ptr, ptr.get_offset()))) + : internal(ipcdetail::offset_ptr_to_offset_from_other(this, &ptr, ptr.get_offset())) {} #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - //!Constructor from other offset_ptr. If pointers of pointee types are - //!convertible, offset_ptrs will be convertibles. Never throws. template BOOST_INTERPROCESS_FORCEINLINE offset_ptr( const offset_ptr &ptr , typename ipcdetail::enable_if_convertible_unequal_address::type* = 0) BOOST_NOEXCEPT - : internal(static_cast - (ipcdetail::offset_ptr_to_offset(static_cast(ptr.get()), this))) + : internal(ipcdetail::offset_ptr_to_offset(static_cast(ptr.get()), this)) {} #endif + //!Constructor from other offset_ptr. Only takes part in overload resolution + //!if PointedType* is constructible from T2* other than via a conversion (e.g. cast to a derived class). Never throws. + template + BOOST_INTERPROCESS_FORCEINLINE explicit offset_ptr(const offset_ptr &ptr + #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + , typename ipcdetail::enable_if_c< + !::boost::is_convertible::value && ::boost::is_constructible::value + >::type * = 0 + #endif + ) BOOST_NOEXCEPT + : internal(ipcdetail::offset_ptr_to_offset(static_cast(ptr.get()), this)) + {} + //!Emulates static_cast operator. //!Never throws. template BOOST_INTERPROCESS_FORCEINLINE offset_ptr(const offset_ptr & r, ipcdetail::static_cast_tag) BOOST_NOEXCEPT - : internal(static_cast - (ipcdetail::offset_ptr_to_offset(static_cast(r.get()), this))) + : internal(ipcdetail::offset_ptr_to_offset(static_cast(r.get()), this)) {} //!Emulates const_cast operator. //!Never throws. template BOOST_INTERPROCESS_FORCEINLINE offset_ptr(const offset_ptr & r, ipcdetail::const_cast_tag) BOOST_NOEXCEPT - : internal(static_cast - (ipcdetail::offset_ptr_to_offset(const_cast(r.get()), this))) + : internal(ipcdetail::offset_ptr_to_offset(const_cast(r.get()), this)) {} //!Emulates dynamic_cast operator. //!Never throws. template BOOST_INTERPROCESS_FORCEINLINE offset_ptr(const offset_ptr & r, ipcdetail::dynamic_cast_tag) BOOST_NOEXCEPT - : internal(static_cast - (ipcdetail::offset_ptr_to_offset(dynamic_cast(r.get()), this))) + : internal(ipcdetail::offset_ptr_to_offset(dynamic_cast(r.get()), this)) {} //!Emulates reinterpret_cast operator. //!Never throws. template BOOST_INTERPROCESS_FORCEINLINE offset_ptr(const offset_ptr & r, ipcdetail::reinterpret_cast_tag) BOOST_NOEXCEPT - : internal(static_cast - (ipcdetail::offset_ptr_to_offset(reinterpret_cast(r.get()), this))) + : internal(ipcdetail::offset_ptr_to_offset(reinterpret_cast(r.get()), this)) {} //!Obtains raw pointer from offset. //!Never throws. BOOST_INTERPROCESS_FORCEINLINE pointer get() const BOOST_NOEXCEPT - { return (pointer)ipcdetail::offset_ptr_to_raw_pointer(this, this->internal.m_offset); } + { return static_cast(ipcdetail::offset_ptr_to_raw_pointer(this, this->internal.m_offset)); } BOOST_INTERPROCESS_FORCEINLINE offset_type get_offset() const BOOST_NOEXCEPT { return this->internal.m_offset; } @@ -358,8 +368,7 @@ class offset_ptr //!Never throws. BOOST_INTERPROCESS_FORCEINLINE offset_ptr& operator= (pointer from) BOOST_NOEXCEPT { - this->internal.m_offset = - static_cast(ipcdetail::offset_ptr_to_offset(from, this)); + this->internal.m_offset = ipcdetail::offset_ptr_to_offset(from, this); return *this; } @@ -367,8 +376,7 @@ class offset_ptr //!Never throws. BOOST_INTERPROCESS_FORCEINLINE offset_ptr& operator= (const offset_ptr & ptr) BOOST_NOEXCEPT { - this->internal.m_offset = - static_cast(ipcdetail::offset_ptr_to_offset_from_other(this, &ptr, ptr.internal.m_offset)); + this->internal.m_offset = ipcdetail::offset_ptr_to_offset_from_other(this, &ptr, ptr.internal.m_offset); return *this; } @@ -444,9 +452,17 @@ class offset_ptr //!Compatibility with pointer_traits //! + #if defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) template struct rebind { typedef offset_ptr other; }; + #else + template + using rebind = offset_ptr; + #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + typedef offset_ptr other; + #endif //BOOST_INTERPROCESS_DOXYGEN_INVOKED + #endif //!Compatibility with pointer_traits //! @@ -546,15 +562,13 @@ class offset_ptr template BOOST_INTERPROCESS_FORCEINLINE void assign(const offset_ptr &ptr, ipcdetail::bool_) BOOST_NOEXCEPT { //no need to pointer adjustment - this->internal.m_offset = - static_cast(ipcdetail::offset_ptr_to_offset_from_other(this, &ptr, ptr.get_offset())); + this->internal.m_offset = ipcdetail::offset_ptr_to_offset_from_other(this, &ptr, ptr.get_offset()); } template BOOST_INTERPROCESS_FORCEINLINE void assign(const offset_ptr &ptr, ipcdetail::bool_) BOOST_NOEXCEPT { //we must convert to raw before calculating the offset - this->internal.m_offset = - static_cast(ipcdetail::offset_ptr_to_offset(static_cast(ptr.get()), this)); + this->internal.m_offset = ipcdetail::offset_ptr_to_offset(static_cast(ptr.get()), this); } #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) @@ -692,7 +706,7 @@ struct pointer_plus_bits, NumBits> typedef boost::interprocess::offset_ptr pointer; //Bits are stored in the lower bits of the pointer except the LSB, //because this bit is used to represent the null pointer. - static const uintptr_t Mask = ((uintptr_t(1) << uintptr_t(NumBits)) - uintptr_t(1)) << uintptr_t(1); + static const O Mask = ((static_cast(1) << NumBits) - static_cast(1)) << 1; BOOST_STATIC_ASSERT(0 ==(Mask&1)); //We must ALWAYS take argument "n" by reference as a copy of a null pointer @@ -701,7 +715,7 @@ struct pointer_plus_bits, NumBits> BOOST_INTERPROCESS_FORCEINLINE static pointer get_pointer(const pointer &n) BOOST_NOEXCEPT { pointer p; - O const tmp_off = n.priv_offset() & O(~Mask); + O const tmp_off = n.priv_offset() & ~Mask; p.priv_offset() = boost::interprocess::ipcdetail::offset_ptr_to_offset_from_other(&p, &n, tmp_off); return p; } @@ -709,7 +723,7 @@ struct pointer_plus_bits, NumBits> BOOST_INTERPROCESS_FORCEINLINE static void set_pointer(pointer &n, const pointer &p) BOOST_NOEXCEPT { BOOST_ASSERT(0 == (get_bits)(p)); - O const stored_bits = O(n.priv_offset() & Mask); + O const stored_bits = n.priv_offset() & Mask; n = p; n.priv_offset() |= stored_bits; } @@ -723,7 +737,7 @@ struct pointer_plus_bits, NumBits> { BOOST_ASSERT(b < (std::size_t(1) << NumBits)); O tmp = n.priv_offset(); - tmp &= O(~Mask); + tmp &= ~Mask; tmp |= O(b << 1u); n.priv_offset() = tmp; } diff --git a/proj/vc7ide/Interprocess.sln b/proj/vc7ide/Interprocess.sln index be463eb..8c71e00 100644 --- a/proj/vc7ide/Interprocess.sln +++ b/proj/vc7ide/Interprocess.sln @@ -479,6 +479,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "segment_manager_test", "seg ProjectSection(ProjectDependencies) = postProject EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "windows_shared_dir_func", "windows_shared_dir_func.vcproj", "{E5C2683A-48EF-FA47-9164-5BA3C1006380}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject Global GlobalSection(SolutionConfiguration) = preSolution Debug = Debug @@ -967,6 +971,10 @@ Global {56CE18C9-0000-0000-0000-000000000000}.Debug.Build.0 = Debug|Win32 {56CE18C9-0000-0000-0000-000000000000}.Release.ActiveCfg = Release|Win32 {56CE18C9-0000-0000-0000-000000000000}.Release.Build.0 = Release|Win32 + {E5C2683A-48EF-FA47-9164-5BA3C1006380}.Debug.ActiveCfg = Debug|Win32 + {E5C2683A-48EF-FA47-9164-5BA3C1006380}.Debug.Build.0 = Debug|Win32 + {E5C2683A-48EF-FA47-9164-5BA3C1006380}.Release.ActiveCfg = Release|Win32 + {E5C2683A-48EF-FA47-9164-5BA3C1006380}.Release.Build.0 = Release|Win32 EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution EndGlobalSection diff --git a/proj/vc7ide/windows_shared_dir_func.vcproj b/proj/vc7ide/windows_shared_dir_func.vcproj new file mode 100644 index 0000000..1c0032d --- /dev/null +++ b/proj/vc7ide/windows_shared_dir_func.vcproj @@ -0,0 +1,138 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 58b81dd..a09bf8f 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -28,9 +28,9 @@ rule test_all acc:-lrt acc-pa_risc:-lrt gcc,windows:"-lole32 -loleaut32 -lpsapi -ladvapi32" - hpux,gcc:"-Wl,+as,mpas" - windows,clang:"-lole32 -loleaut32 -lpsapi -ladvapi32" - linux:"-lrt" + hpux,gcc:"-Wl,+as,mpas" + windows,clang:"-lole32 -loleaut32 -lpsapi -ladvapi32" + linux:"-lrt" ] ; } diff --git a/test/windows_shared_dir_func.cpp b/test/windows_shared_dir_func.cpp new file mode 100644 index 0000000..135f246 --- /dev/null +++ b/test/windows_shared_dir_func.cpp @@ -0,0 +1,84 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2004-2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include + +#ifdef BOOST_INTERPROCESS_WINDOWS + +#define BOOST_INTERPROCESS_WINDOWS + +//Force user-defined get_shared_dir +#define BOOST_INTERPROCESS_SHARED_DIR_FUNC +#include +#include + +#include "get_process_id_name.hpp" + +namespace boost { +namespace interprocess { +namespace ipcdetail { + +static bool dir_created = false; + +inline void get_shared_dir(std::string &shared_dir) +{ + shared_dir = boost::interprocess::ipcdetail::get_temporary_path(); + shared_dir += "/boostipctest_"; + shared_dir += boost::interprocess::test::get_process_id_name(); + if(!dir_created) + ipcdetail::create_directory(shared_dir.c_str()); + dir_created = true; +} + +}}} //namespace boost::interprocess::ipcdetail + +#include +#include + +int main () +{ + using namespace boost::interprocess; + const char *const shm_name = "test_shm"; + std::string shared_dir; + ipcdetail::get_shared_dir(shared_dir); + + std::string shm_path(shared_dir); + shm_path += shm_name; + + int ret = 0; + shared_memory_object::remove(shm_name); + { + shared_memory_object shm(create_only, shm_name, read_write); + + shm_path += shm_name; + int ret = ipcdetail::invalid_file() == ipcdetail::open_existing_file(shm_path.c_str(), read_only) ? + 1 : 0; + if(ret) + { + std::cerr << "Error opening user get_shared_dir()/shm file" << std::endl; + } + } + shared_memory_object::remove(shm_name); + ipcdetail::remove_directory(shared_dir.c_str()); + + return ret; +} + +#else + +int main() +{ + return 0; +} + +#endif //#ifdef BOOST_INTERPROCESS_WINDOWS + +#include