From 140b50efb3281fa3898f3a4cf939cfbda174718f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Sun, 31 Jan 2021 00:27:15 +0100 Subject: [PATCH] Added support for wide characters when creating named resources in operating systems with wide-char APIs (at this time, Windows). Fixes #93 and fixes #134. --- doc/interprocess.qbk | 22 ++ .../interprocess/anonymous_shared_memory.hpp | 2 +- .../interprocess/detail/char_wchar_holder.hpp | 127 +++++++++++ .../interprocess/detail/file_wrapper.hpp | 46 ++-- .../detail/managed_memory_impl.hpp | 8 +- .../detail/managed_open_or_create_impl.hpp | 62 ++--- .../interprocess/detail/os_file_functions.hpp | 116 ++++++++-- .../detail/shared_dir_helpers.hpp | 72 ++++-- .../boost/interprocess/detail/win32_api.hpp | 212 ++++++++++++++++-- .../boost/interprocess/detail/workaround.hpp | 7 + include/boost/interprocess/file_mapping.hpp | 57 ++++- .../boost/interprocess/ipc/message_queue.hpp | 109 ++++++++- .../interprocess/managed_mapped_file.hpp | 99 ++++++++ .../interprocess/managed_shared_memory.hpp | 105 +++++++++ .../managed_windows_shared_memory.hpp | 42 ++++ include/boost/interprocess/mapped_region.hpp | 2 +- .../boost/interprocess/segment_manager.hpp | 32 +-- .../interprocess/shared_memory_object.hpp | 92 ++++++-- include/boost/interprocess/sync/file_lock.hpp | 23 ++ .../interprocess/sync/named_condition.hpp | 72 ++++++ .../interprocess/sync/named_condition_any.hpp | 49 ++++ .../boost/interprocess/sync/named_mutex.hpp | 64 ++++++ .../sync/named_recursive_mutex.hpp | 62 +++++ .../interprocess/sync/named_semaphore.hpp | 66 ++++++ .../sync/named_sharable_mutex.hpp | 82 +++++++ .../sync/named_upgradable_mutex.hpp | 84 +++++++ .../interprocess/sync/shm/named_condition.hpp | 83 +++++++ .../sync/shm/named_condition_any.hpp | 12 +- .../interprocess/sync/shm/named_mutex.hpp | 70 ++++++ .../sync/shm/named_recursive_mutex.hpp | 70 ++++++ .../interprocess/sync/shm/named_semaphore.hpp | 60 +++++ .../sync/windows/named_condition_any.hpp | 27 +++ .../interprocess/sync/windows/named_mutex.hpp | 36 +++ .../sync/windows/named_recursive_mutex.hpp | 12 + .../sync/windows/named_semaphore.hpp | 29 +++ .../interprocess/sync/windows/named_sync.hpp | 10 +- .../interprocess/windows_shared_memory.hpp | 32 ++- test/file_lock_test.cpp | 29 ++- test/file_mapping_test.cpp | 29 ++- test/get_process_id_name.hpp | 48 ++++ test/managed_mapped_file_test.cpp | 57 ++++- test/managed_shared_memory_test.cpp | 45 +++- test/managed_xsi_shared_memory_test.cpp | 8 - test/mapped_file_test.cpp | 42 ++-- test/message_queue_test.cpp | 90 ++++++-- test/named_condition_any_test.cpp | 54 +++++ test/named_condition_test.cpp | 60 +++++ test/named_creation_template.hpp | 37 +++ test/named_mutex_test.cpp | 11 +- test/named_recursive_mutex_test.cpp | 11 +- test/named_semaphore_test.cpp | 34 +-- test/named_sharable_mutex_test.cpp | 73 +----- test/named_upgradable_mutex_test.cpp | 73 +----- test/shared_memory_mapping_test.cpp | 19 ++ test/shared_memory_test.cpp | 28 +++ ...dows_eventlog_stamp_shared_memory_test.cpp | 44 +++- test/windows_shared_dir_func.cpp | 10 + test/windows_shared_memory_test.cpp | 31 +++ test/xsi_shared_memory_mapping_test.cpp | 8 - 59 files changed, 2591 insertions(+), 405 deletions(-) create mode 100644 include/boost/interprocess/detail/char_wchar_holder.hpp diff --git a/doc/interprocess.qbk b/doc/interprocess.qbk index 001110d..3a6b8c8 100644 --- a/doc/interprocess.qbk +++ b/doc/interprocess.qbk @@ -6781,6 +6781,28 @@ thank them: [section:release_notes Release Notes] +[section:release_notes_boost_1_76_00 Boost 1.76 Release] + +* Added `wchar_t` API support for named resources in operating systems that offer native wide character API (e.g. Windows). + The following classes were updated with `wchar_t` name support: + * `file_mapping` + * `managed_mapped_file` + * `managed_shared_memory` + * `managed_windows_shared_memory` + * `shared_memory_object` + * `windows_shared_memory_object` + * `file_lock` + * `named_condition` + * `named_condition_any` + * `named_mutex` + * `named_recursive_mutex` + * `named_semaphore` + * `named_sharable_mutex` + * `named_upgradable_mutex` + * `message_queue` + +[endsect] + [section:release_notes_boost_1_75_00 Boost 1.75 Release] * Fixed bugs: diff --git a/include/boost/interprocess/anonymous_shared_memory.hpp b/include/boost/interprocess/anonymous_shared_memory.hpp index f73b557..dec6845 100644 --- a/include/boost/interprocess/anonymous_shared_memory.hpp +++ b/include/boost/interprocess/anonymous_shared_memory.hpp @@ -111,7 +111,7 @@ anonymous_shared_memory(std::size_t size, void *address = 0) } #else { - windows_shared_memory anonymous_mapping(create_only, 0, read_write, size); + windows_shared_memory anonymous_mapping(create_only, (char*)0, read_write, size); return mapped_region(anonymous_mapping, read_write, 0, size, address); } diff --git a/include/boost/interprocess/detail/char_wchar_holder.hpp b/include/boost/interprocess/detail/char_wchar_holder.hpp new file mode 100644 index 0000000..8831aa2 --- /dev/null +++ b/include/boost/interprocess/detail/char_wchar_holder.hpp @@ -0,0 +1,127 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2020-2021. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/interprocess for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_INTERPROCESS_DETAIL_CHAR_WCHAR_HOLDER_HPP +#define BOOST_INTERPROCESS_DETAIL_CHAR_WCHAR_HOLDER_HPP + +#ifndef BOOST_CONFIG_HPP +# include +#endif +# +#if defined(BOOST_HAS_PRAGMA_ONCE) +# pragma once +#endif + +#include +#include + +#include +#include + +namespace boost { +namespace interprocess { + +class char_wchar_holder +{ + public: + char_wchar_holder() + : m_str(), m_is_wide() + { + m_str.n = 0; + } + + char_wchar_holder(const char *nstr) + : m_str(), m_is_wide() + { + m_str.n = new char [std::strlen(nstr)+1]; + std::strcpy(m_str.n, nstr); + } + + char_wchar_holder(const wchar_t *wstr) + : m_str(), m_is_wide(true) + { + m_str.w = new wchar_t [std::wcslen(wstr)+1]; + std::wcscpy(m_str.w, wstr); + } + + char_wchar_holder& operator=(const char *nstr) + { + char *tmp = new char [std::strlen(nstr)+1]; + this->delete_mem(); + m_str.n = tmp; + std::strcpy(m_str.n, nstr); + return *this; + } + + char_wchar_holder& operator=(const wchar_t *wstr) + { + wchar_t *tmp = new wchar_t [std::wcslen(wstr)+1]; + this->delete_mem(); + m_str.w = tmp; + std::wcscpy(m_str.w, wstr); + return *this; + } + + char_wchar_holder& operator=(const char_wchar_holder &other) + { + if (other.m_is_wide) + *this = other.getn(); + else + *this = other.getw(); + return *this; + } + + ~char_wchar_holder() + { + this->delete_mem(); + } + + wchar_t *getw() const + { return m_is_wide ? m_str.w : 0; } + + char *getn() const + { return !m_is_wide ? m_str.n : 0; } + + void swap(char_wchar_holder& other) + { + char_wchar tmp; + std::memcpy(&tmp, &m_str, sizeof(char_wchar)); + std::memcpy(&m_str, &other.m_str, sizeof(char_wchar)); + std::memcpy(&other.m_str, &tmp, sizeof(char_wchar)); + // + bool b_tmp(m_is_wide); + m_is_wide = other.m_is_wide; + other.m_is_wide = b_tmp; + } + + private: + + void delete_mem() + { + if(m_is_wide) + delete [] m_str.w; + else + delete [] m_str.n; + } + + union char_wchar + { + char *n; + wchar_t *w; + } m_str; + bool m_is_wide; +}; + +} //namespace interprocess { +} //namespace boost { + +#include + +#endif //BOOST_INTERPROCESS_DETAIL_CHAR_WCHAR_HOLDER_HPP diff --git a/include/boost/interprocess/detail/file_wrapper.hpp b/include/boost/interprocess/detail/file_wrapper.hpp index 99e0fea..d70a679 100644 --- a/include/boost/interprocess/detail/file_wrapper.hpp +++ b/include/boost/interprocess/detail/file_wrapper.hpp @@ -58,6 +58,34 @@ class file_wrapper file_wrapper(open_only_t, const char *name, mode_t mode) { this->priv_open_or_create(ipcdetail::DoOpen, name, mode, permissions()); } + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Creates a file object with name "name" and mode "mode", with the access mode "mode" + //!If the file previously exists, throws an error. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + file_wrapper(create_only_t, const wchar_t *name, mode_t mode, const permissions &perm = permissions()) + { this->priv_open_or_create(ipcdetail::DoCreate, name, mode, perm); } + + //!Tries to create a file with name "name" and mode "mode", with the + //!access mode "mode". If the file previously exists, it tries to open it with mode "mode". + //!Otherwise throws an error. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + file_wrapper(open_or_create_t, const wchar_t *name, mode_t mode, const permissions &perm = permissions()) + { this->priv_open_or_create(ipcdetail::DoOpenOrCreate, name, mode, perm); } + + //!Tries to open a file with name "name", with the access mode "mode". + //!If the file does not previously exist, it throws an error. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + file_wrapper(open_only_t, const wchar_t *name, mode_t mode) + { this->priv_open_or_create(ipcdetail::DoOpen, name, mode, permissions()); } + + #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) //!Moves the ownership of "moved"'s file to *this. //!After the call, "moved" does not represent any file. //!Does not throw @@ -110,24 +138,21 @@ class file_wrapper //!Closes a previously opened file mapping. Never throws. void priv_close(); //!Closes a previously opened file mapping. Never throws. - bool priv_open_or_create(ipcdetail::create_enum_t type, const char *filename, mode_t mode, const permissions &perm); + template + bool priv_open_or_create(ipcdetail::create_enum_t type, const CharT *filename, mode_t mode, const permissions &perm); file_handle_t m_handle; mode_t m_mode; - std::string m_filename; }; inline file_wrapper::file_wrapper() : m_handle(file_handle_t(ipcdetail::invalid_file())) - , m_mode(read_only), m_filename() + , m_mode(read_only) {} inline file_wrapper::~file_wrapper() { this->priv_close(); } -inline const char *file_wrapper::get_name() const -{ return m_filename.c_str(); } - inline bool file_wrapper::get_size(offset_t &size) const { return get_file_size((file_handle_t)m_handle, size); } @@ -135,7 +160,6 @@ inline void file_wrapper::swap(file_wrapper &other) { (simple_swap)(m_handle, other.m_handle); (simple_swap)(m_mode, other.m_mode); - m_filename.swap(other.m_filename); } inline mapping_handle_t file_wrapper::get_mapping_handle() const @@ -144,14 +168,10 @@ inline mapping_handle_t file_wrapper::get_mapping_handle() const inline mode_t file_wrapper::get_mode() const { return m_mode; } +template inline bool file_wrapper::priv_open_or_create - (ipcdetail::create_enum_t type, - const char *filename, - mode_t mode, - const permissions &perm = permissions()) + ( ipcdetail::create_enum_t type, const CharT *filename, mode_t mode, const permissions &perm) { - m_filename = filename; - if(mode != read_only && mode != read_write){ error_info err(mode_error); throw interprocess_exception(err); diff --git a/include/boost/interprocess/detail/managed_memory_impl.hpp b/include/boost/interprocess/detail/managed_memory_impl.hpp index 25c6814..a3e4305 100644 --- a/include/boost/interprocess/detail/managed_memory_impl.hpp +++ b/include/boost/interprocess/detail/managed_memory_impl.hpp @@ -110,8 +110,8 @@ class basic_managed_memory_impl typedef basic_managed_memory_impl self_t; protected: - template - static bool grow(const char *filename, size_type extra_bytes) + template + static bool grow(const CharT *filename, size_type extra_bytes) { typedef typename ManagedMemory::device_type device_type; //Increase file size @@ -133,8 +133,8 @@ class basic_managed_memory_impl return true; } - template - static bool shrink_to_fit(const char *filename) + template + static bool shrink_to_fit(const CharT *filename) { typedef typename ManagedMemory::device_type device_type; size_type new_size; diff --git a/include/boost/interprocess/detail/managed_open_or_create_impl.hpp b/include/boost/interprocess/detail/managed_open_or_create_impl.hpp index b47c310..b65cd2c 100644 --- a/include/boost/interprocess/detail/managed_open_or_create_impl.hpp +++ b/include/boost/interprocess/detail/managed_open_or_create_impl.hpp @@ -38,35 +38,8 @@ namespace boost { namespace interprocess { - -#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) -namespace ipcdetail{ class interprocess_tester; } - - -template -struct managed_open_or_create_impl_device_id_t -{ - typedef const char *type; -}; - -#ifdef BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS - -class xsi_shared_memory_file_wrapper; -class xsi_key; - -template<> -struct managed_open_or_create_impl_device_id_t -{ - typedef xsi_key type; -}; - -#endif //BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS - -#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED - namespace ipcdetail { - template class managed_open_or_create_impl_device_holder { @@ -99,7 +72,6 @@ class managed_open_or_create_impl //Non-copyable BOOST_MOVABLE_BUT_NOT_COPYABLE(managed_open_or_create_impl) - typedef typename managed_open_or_create_impl_device_id_t::type device_id_t; typedef managed_open_or_create_impl_device_holder DevHolder; enum { @@ -122,8 +94,9 @@ class managed_open_or_create_impl managed_open_or_create_impl() {} + template managed_open_or_create_impl(create_only_t, - const device_id_t & id, + const DeviceId & id, std::size_t size, mode_t mode, const void *addr, @@ -139,8 +112,9 @@ class managed_open_or_create_impl , null_mapped_region_function()); } + template managed_open_or_create_impl(open_only_t, - const device_id_t & id, + const DeviceId & id, mode_t mode, const void *addr) { @@ -154,9 +128,9 @@ class managed_open_or_create_impl , null_mapped_region_function()); } - + template managed_open_or_create_impl(open_or_create_t, - const device_id_t & id, + const DeviceId & id, std::size_t size, mode_t mode, const void *addr, @@ -172,9 +146,9 @@ class managed_open_or_create_impl , null_mapped_region_function()); } - template + template managed_open_or_create_impl(create_only_t, - const device_id_t & id, + const DeviceId & id, std::size_t size, mode_t mode, const void *addr, @@ -191,9 +165,9 @@ class managed_open_or_create_impl , construct_func); } - template + template managed_open_or_create_impl(open_only_t, - const device_id_t & id, + const DeviceId & id, mode_t mode, const void *addr, const ConstructFunc &construct_func) @@ -208,9 +182,9 @@ class managed_open_or_create_impl , construct_func); } - template + template managed_open_or_create_impl(open_or_create_t, - const device_id_t & id, + const DeviceId & id, std::size_t size, mode_t mode, const void *addr, @@ -291,26 +265,26 @@ class managed_open_or_create_impl { return size == std::size_t(offset_t(size)); } //These are templatized to allow explicit instantiations - template - static void create_device(DeviceAbstraction &dev, const device_id_t & id, std::size_t size, const permissions &perm, false_ file_like) + template + static void create_device(DeviceAbstraction &dev, const DeviceId & id, std::size_t size, const permissions &perm, false_ file_like) { (void)file_like; DeviceAbstraction tmp(create_only, id, read_write, size, perm); tmp.swap(dev); } - template - static void create_device(DeviceAbstraction &dev, const device_id_t & id, std::size_t, const permissions &perm, true_ file_like) + template + static void create_device(DeviceAbstraction &dev, const DeviceId & id, std::size_t, const permissions &perm, true_ file_like) { (void)file_like; DeviceAbstraction tmp(create_only, id, read_write, perm); tmp.swap(dev); } - template inline + template inline void priv_open_or_create (create_enum_t type, - const device_id_t & id, + const DeviceId & id, std::size_t size, mode_t mode, const void *addr, const permissions &perm, diff --git a/include/boost/interprocess/detail/os_file_functions.hpp b/include/boost/interprocess/detail/os_file_functions.hpp index 17c5c94..e7f81a5 100644 --- a/include/boost/interprocess/detail/os_file_functions.hpp +++ b/include/boost/interprocess/detail/os_file_functions.hpp @@ -31,6 +31,7 @@ #if defined (BOOST_INTERPROCESS_WINDOWS) # include +# include //wcsxxx() #else # ifdef BOOST_HAS_UNISTD_H # include @@ -99,7 +100,8 @@ inline mapping_handle_t mapping_handle_from_shm_handle(file_handle_t hnd) inline file_handle_t file_handle_from_mapping_handle(mapping_handle_t hnd) { return hnd.handle; } -inline bool create_directory(const char *path) +template +inline bool create_directory(const CharT *path) { return winapi::create_directory(path); } inline bool remove_directory(const char *path) @@ -117,13 +119,31 @@ inline bool get_temporary_path(char *buffer, std::size_t buf_len, std::size_t &r 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; + buffer[required_len-1] = '\0'; } return ret; } +inline bool get_temporary_path(wchar_t *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] == L'\\'){ + buffer[required_len-1] = L'\0'; + } + return ret; +} + +template inline file_handle_t create_new_file - (const char *name, mode_t mode, const permissions & perm = permissions(), bool temporary = false) + (const CharT *name, mode_t mode, const permissions & perm = permissions(), bool temporary = false) { unsigned long attr = temporary ? winapi::file_attribute_temporary : 0; return winapi::create_file @@ -131,8 +151,9 @@ inline file_handle_t create_new_file , (winapi::interprocess_security_attributes*)perm.get_permissions()); } +template inline file_handle_t create_or_open_file - (const char *name, mode_t mode, const permissions & perm = permissions(), bool temporary = false) + (const CharT *name, mode_t mode, const permissions & perm = permissions(), bool temporary = false) { unsigned long attr = temporary ? winapi::file_attribute_temporary : 0; return winapi::create_file @@ -140,8 +161,9 @@ inline file_handle_t create_or_open_file , (winapi::interprocess_security_attributes*)perm.get_permissions()); } +template inline file_handle_t open_existing_file - (const char *name, mode_t mode, bool temporary = false) + (const CharT *name, mode_t mode, bool temporary = false) { unsigned long attr = temporary ? winapi::file_attribute_temporary : 0; return winapi::create_file @@ -151,6 +173,9 @@ inline file_handle_t open_existing_file inline bool delete_file(const char *name) { return winapi::unlink_file(name); } +inline bool delete_file(const wchar_t *name) +{ return winapi::unlink_file(name); } + inline bool truncate_file (file_handle_t hnd, std::size_t size) { offset_t filesize; @@ -274,26 +299,67 @@ inline bool try_acquire_file_lock_sharable(file_handle_t hnd, bool &acquired) inline bool release_file_lock_sharable(file_handle_t hnd) { return release_file_lock(hnd); } +template +struct os_file_traits; + +template<> +struct os_file_traits +{ + static const char *any_file() + { return "\\*.*"; } + + static const char *backslash() + { return "\\"; } + + static char dot() + { return '.'; } + + typedef winapi::win32_find_data_a win32_find_data_t; + + static int cmp(const char *a, const char *b) + { return std::strcmp(a, b); } +}; + +template<> +struct os_file_traits +{ + static const wchar_t *any_file() + { return L"\\*.*"; } + + static const wchar_t *backslash() + { return L"\\"; } + + static wchar_t dot() + { return L'.'; } + + typedef winapi::win32_find_data_w win32_find_data_t; + + static int cmp(const wchar_t *a, const wchar_t *b) + { return std::wcscmp(a, b); } +}; + +template inline bool delete_subdirectories_recursive - (const std::string &refcstrRootDirectory, const char *dont_delete_this, unsigned int count) + (const std::basic_string &refcstrRootDirectory, const CharT *dont_delete_this, unsigned int count) { bool bSubdirectory = false; // Flag, indicating whether // subdirectories have been found void * hFile; // Handle to directory - std::string strFilePath; // Filepath - std::string strPattern; // Pattern - winapi::win32_find_data FileInformation; // File information + std::basic_string strFilePath; // Filepath + std::basic_string strPattern; // Pattern + typedef os_file_traits traits_t; + typename traits_t::win32_find_data_t FileInformation; // File information //Find all files and directories - strPattern = refcstrRootDirectory + "\\*.*"; + strPattern = refcstrRootDirectory + traits_t::any_file(); hFile = winapi::find_first_file(strPattern.c_str(), &FileInformation); if(hFile != winapi::invalid_handle_value){ do{ //If it's not "." or ".." or the pointed root_level dont_delete_this erase it - if(FileInformation.cFileName[0] != '.' && - !(dont_delete_this && count == 0 && std::strcmp(dont_delete_this, FileInformation.cFileName) == 0)){ + if(FileInformation.cFileName[0] != traits_t::dot() && + !(dont_delete_this && count == 0 && traits_t::cmp(dont_delete_this, FileInformation.cFileName) == 0)){ strFilePath.erase(); - strFilePath = refcstrRootDirectory + "\\" + FileInformation.cFileName; + strFilePath = refcstrRootDirectory + traits_t::backslash() + FileInformation.cFileName; //If it's a directory, go recursive if(FileInformation.dwFileAttributes & winapi::file_attribute_directory){ @@ -340,7 +406,8 @@ inline bool delete_subdirectories_recursive } //This function erases all the subdirectories of a directory except the one pointed by "dont_delete_this" -inline bool delete_subdirectories(const std::string &refcstrRootDirectory, const char *dont_delete_this) +template +inline bool delete_subdirectories(const std::basic_string &refcstrRootDirectory, const CharT *dont_delete_this) { return delete_subdirectories_recursive(refcstrRootDirectory, dont_delete_this, 0u); } @@ -350,7 +417,7 @@ template inline bool for_each_file_in_dir(const char *dir, Function f) { void * hFile; // Handle to directory - winapi::win32_find_data FileInformation; // File information + winapi::win32_find_data_a FileInformation; // File information //Get base directory std::string str(dir); @@ -726,7 +793,7 @@ inline bool open_or_create_directory(const char *dir_name) inline std::string get_temporary_path() { std::size_t required_len = 0; - get_temporary_path(0, 0, required_len); + get_temporary_path((char*)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]){ @@ -736,6 +803,23 @@ inline std::string get_temporary_path() return ret_str; } +#ifdef BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES + +inline std::wstring get_temporary_wpath() +{ + std::size_t required_len = 0; + get_temporary_path((wchar_t*)0, 0, required_len); + std::wstring 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; +} + +#endif + } //namespace ipcdetail{ } //namespace interprocess { } //namespace boost { diff --git a/include/boost/interprocess/detail/shared_dir_helpers.hpp b/include/boost/interprocess/detail/shared_dir_helpers.hpp index 0fcd898..6cc5eb1 100644 --- a/include/boost/interprocess/detail/shared_dir_helpers.hpp +++ b/include/boost/interprocess/detail/shared_dir_helpers.hpp @@ -34,9 +34,33 @@ namespace boost { namespace interprocess { namespace ipcdetail { +template +struct shared_dir_constants; + +template<> +struct shared_dir_constants +{ + static char dir_separator() + { return '/'; } + + static const char *dir_interprocess() + { return "/boost_interprocess"; } +}; + +template<> +struct shared_dir_constants +{ + static wchar_t dir_separator() + { return L'/'; } + + static const wchar_t *dir_interprocess() + { return L"/boost_interprocess"; } +}; + #if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME) #if defined(BOOST_INTERPROCESS_WINDOWS) //This type will initialize the stamp + template struct windows_bootstamp { windows_bootstamp() @@ -49,12 +73,13 @@ namespace ipcdetail { } //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 - std::string stamp; + std::basic_string stamp; }; - inline void get_bootstamp(std::string &s, bool add = false) + template + inline void get_bootstamp(std::basic_string &s, bool add = false) { - const windows_bootstamp &bootstamp = windows_intermodule_singleton::get(); + const windows_bootstamp &bootstamp = windows_intermodule_singleton >::get(); if(add){ s += bootstamp.stamp; } @@ -102,7 +127,8 @@ namespace ipcdetail { #endif #endif //#if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME) -inline void get_shared_dir_root(std::string &dir_path) +template +inline void get_shared_dir_root(std::basic_string &dir_path) { #if defined (BOOST_INTERPROCESS_WINDOWS) winapi::get_shared_documents_folder(dir_path); @@ -115,8 +141,8 @@ inline void get_shared_dir_root(std::string &dir_path) error_info err = system_error_code(); throw interprocess_exception(err); } - //Remove final null. - dir_path += "/boost_interprocess"; + + dir_path += shared_dir_constants::dir_interprocess(); } #if defined(BOOST_INTERPROCESS_SHARED_DIR_FUNC) && defined(BOOST_INTERPROCESS_SHARED_DIR_PATH) @@ -129,35 +155,43 @@ inline void get_shared_dir_root(std::string &dir_path) // get_shared_dir void get_shared_dir(std::string &shared_dir); + // When BOOST_INTERPROCESS_SHARED_DIR_FUNC is defined, users have to implement + // get_shared_dir + void get_shared_dir(std::wstring &shared_dir); + #else -inline void get_shared_dir(std::string &shared_dir) + +template +inline void get_shared_dir(std::basic_string &shared_dir) { #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 += "/"; + shared_dir += shared_dir_constants::dir_separator(); get_bootstamp(shared_dir, true); #endif #endif } #endif -inline void shared_filepath(const char *filename, std::string &filepath) +template +inline void shared_filepath(const CharT *filename, std::basic_string &filepath) { get_shared_dir(filepath); - filepath += "/"; + filepath += shared_dir_constants::dir_separator(); filepath += filename; } -inline void create_shared_dir_and_clean_old(std::string &shared_dir) +template +inline void create_shared_dir_and_clean_old(std::basic_string &shared_dir) { #if defined(BOOST_INTERPROCESS_SHARED_DIR_PATH) || defined(BOOST_INTERPROCESS_SHARED_DIR_FUNC) get_shared_dir(shared_dir); #else //First get the temp directory - std::string root_shared_dir; + std::basic_string root_shared_dir; get_shared_dir_root(root_shared_dir); //If fails, check that it's because already exists @@ -179,7 +213,7 @@ inline void create_shared_dir_and_clean_old(std::string &shared_dir) } } //Now erase all old directories created in the previous boot sessions - std::string subdir = shared_dir; + std::basic_string subdir = shared_dir; subdir.erase(0, root_shared_dir.size()+1); delete_subdirectories(root_shared_dir, subdir.c_str()); #else @@ -188,17 +222,19 @@ inline void create_shared_dir_and_clean_old(std::string &shared_dir) #endif } -inline void create_shared_dir_cleaning_old_and_get_filepath(const char *filename, std::string &shared_dir) +template +inline void create_shared_dir_cleaning_old_and_get_filepath(const CharT *filename, std::basic_string &shared_dir) { create_shared_dir_and_clean_old(shared_dir); - shared_dir += "/"; + shared_dir += shared_dir_constants::dir_separator(); shared_dir += filename; } -inline void add_leading_slash(const char *name, std::string &new_name) +template +inline void add_leading_slash(const CharT *name, std::basic_string &new_name) { - if(name[0] != '/'){ - new_name = '/'; + if(name[0] != shared_dir_constants::dir_separator()){ + new_name = shared_dir_constants::dir_separator(); } new_name += name; } diff --git a/include/boost/interprocess/detail/win32_api.hpp b/include/boost/interprocess/detail/win32_api.hpp index 897b440..8cdb33f 100644 --- a/include/boost/interprocess/detail/win32_api.hpp +++ b/include/boost/interprocess/detail/win32_api.hpp @@ -333,15 +333,23 @@ BOOST_WINAPI_DETAIL_DECLARE_HANDLE(HKEY); BOOST_SYMBOL_IMPORT boost::ipwinapiext::LSTATUS BOOST_WINAPI_WINAPI_CC RegOpenKeyExA (::HKEY hKey, const char *lpSubKey, boost::winapi::DWORD_ ulOptions, boost::winapi::DWORD_ samDesired, ::HKEY *phkResult); +BOOST_SYMBOL_IMPORT boost::ipwinapiext::LSTATUS BOOST_WINAPI_WINAPI_CC RegOpenKeyExW + (::HKEY hKey, const wchar_t *lpSubKey, boost::winapi::DWORD_ ulOptions, boost::winapi::DWORD_ samDesired, ::HKEY *phkResult); BOOST_SYMBOL_IMPORT boost::ipwinapiext::LSTATUS BOOST_WINAPI_WINAPI_CC RegQueryValueExA (::HKEY hKey, const char *lpValueName, boost::winapi::DWORD_ *lpReserved, boost::winapi::DWORD_ *lpType, boost::winapi::BYTE_ *lpData, boost::winapi::DWORD_ *lpcbData); +BOOST_SYMBOL_IMPORT boost::ipwinapiext::LSTATUS BOOST_WINAPI_WINAPI_CC RegQueryValueExW + (::HKEY hKey, const wchar_t *lpValueName, boost::winapi::DWORD_ *lpReserved, boost::winapi::DWORD_ *lpType, boost::winapi::BYTE_ *lpData, boost::winapi::DWORD_ *lpcbData); BOOST_SYMBOL_IMPORT boost::ipwinapiext::LSTATUS BOOST_WINAPI_WINAPI_CC RegCloseKey(::HKEY hKey); //Event Log BOOST_SYMBOL_IMPORT boost::winapi::HANDLE_ BOOST_WINAPI_WINAPI_CC OpenEventLogA(const char* lpUNCServerName, const char* lpSourceName); +BOOST_SYMBOL_IMPORT boost::winapi::HANDLE_ BOOST_WINAPI_WINAPI_CC OpenEventLogW(const wchar_t* lpUNCServerName, const wchar_t* lpSourceName); BOOST_SYMBOL_IMPORT boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC CloseEventLog(boost::winapi::HANDLE_ hEventLog); BOOST_SYMBOL_IMPORT boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC ReadEventLogA + ( boost::winapi::HANDLE_ hEventLog, boost::winapi::DWORD_ dwReadFlags, boost::winapi::DWORD_ dwRecordOffset, void* lpBuffer + , boost::winapi::DWORD_ nNumberOfBytesToRead, boost::winapi::DWORD_ *pnBytesRead, boost::winapi::DWORD_ *pnMinNumberOfBytesNeeded); +BOOST_SYMBOL_IMPORT boost::winapi::BOOL_ BOOST_WINAPI_WINAPI_CC ReadEventLogW ( boost::winapi::HANDLE_ hEventLog, boost::winapi::DWORD_ dwReadFlags, boost::winapi::DWORD_ dwRecordOffset, void* lpBuffer , boost::winapi::DWORD_ nNumberOfBytesToRead, boost::winapi::DWORD_ *pnBytesRead, boost::winapi::DWORD_ *pnMinNumberOfBytesNeeded); @@ -385,12 +393,24 @@ BOOST_FORCEINLINE boost::ipwinapiext::LSTATUS RegOpenKeyExA return ::RegOpenKeyExA(reinterpret_cast< ::HKEY >(hKey), lpSubKey, ulOptions, samDesired, reinterpret_cast< ::HKEY* >(phkResult)); } +BOOST_FORCEINLINE boost::ipwinapiext::LSTATUS RegOpenKeyExW + (boost::ipwinapiext::HKEY_ hKey, const wchar_t *lpSubKey, boost::winapi::DWORD_ ulOptions, boost::winapi::DWORD_ samDesired, boost::ipwinapiext::HKEY_ *phkResult) +{ + return ::RegOpenKeyExW(reinterpret_cast< ::HKEY >(hKey), lpSubKey, ulOptions, samDesired, reinterpret_cast< ::HKEY* >(phkResult)); +} + BOOST_FORCEINLINE boost::ipwinapiext::LSTATUS RegQueryValueExA (boost::ipwinapiext::HKEY_ hKey, const char *lpValueName, boost::winapi::DWORD_ *lpReserved, boost::winapi::DWORD_ *lpType, boost::winapi::BYTE_ *lpData, boost::winapi::DWORD_ *lpcbData) { return ::RegQueryValueExA(reinterpret_cast< ::HKEY >(hKey), lpValueName, lpReserved, lpType, lpData, lpcbData); } +BOOST_FORCEINLINE boost::ipwinapiext::LSTATUS RegQueryValueExW + (boost::ipwinapiext::HKEY_ hKey, const wchar_t *lpValueName, boost::winapi::DWORD_ *lpReserved, boost::winapi::DWORD_ *lpType, boost::winapi::BYTE_ *lpData, boost::winapi::DWORD_ *lpcbData) +{ + return ::RegQueryValueExW(reinterpret_cast< ::HKEY >(hKey), lpValueName, lpReserved, lpType, lpData, lpcbData); +} + BOOST_FORCEINLINE boost::ipwinapiext::LSTATUS RegCloseKey(boost::ipwinapiext::HKEY_ hKey) { return ::RegCloseKey(reinterpret_cast< ::HKEY >(hKey)); @@ -411,7 +431,8 @@ namespace winapi { typedef boost::winapi::SYSTEM_INFO_ interprocess_system_info; typedef boost::winapi::OVERLAPPED_ interprocess_overlapped; typedef boost::winapi::FILETIME_ interprocess_filetime; -typedef boost::winapi::WIN32_FIND_DATAA_ win32_find_data; +typedef boost::winapi::WIN32_FIND_DATAA_ win32_find_data_a; +typedef boost::winapi::WIN32_FIND_DATAW_ win32_find_data_w; typedef boost::winapi::SECURITY_ATTRIBUTES_ interprocess_security_attributes; typedef boost::winapi::SECURITY_DESCRIPTOR_ interprocess_security_descriptor; typedef boost::winapi::BY_HANDLE_FILE_INFORMATION_ interprocess_by_handle_file_information; @@ -654,12 +675,18 @@ 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 *lpFindFileData) +inline void * find_first_file(const char *lpFileName, win32_find_data_a *lpFindFileData) { return FindFirstFileA(lpFileName, lpFindFileData); } -inline bool find_next_file(void *hFindFile, win32_find_data *lpFindFileData) +inline void * find_first_file(const wchar_t *lpFileName, win32_find_data_w *lpFindFileData) +{ return FindFirstFileW(lpFileName, lpFindFileData); } + +inline bool find_next_file(void *hFindFile, win32_find_data_a *lpFindFileData) { return FindNextFileA(hFindFile, lpFindFileData) != 0; } +inline bool find_next_file(void *hFindFile, win32_find_data_w *lpFindFileData) +{ return FindNextFileW(hFindFile, lpFindFileData) != 0; } + inline bool find_close(void *handle) { return FindClose(handle) != 0; } @@ -736,9 +763,18 @@ inline void * create_file_mapping (void * handle, unsigned long access, ::boost: return CreateFileMappingA (handle, psec, access, high_size, low_size, name); } +inline void * create_file_mapping (void * handle, unsigned long access, ::boost::ulong_long_type file_offset, const wchar_t * name, interprocess_security_attributes *psec) +{ + const boost::winapi::DWORD_ high_size(file_offset >> 32), low_size((boost::winapi::DWORD_)file_offset); + return CreateFileMappingW (handle, psec, access, high_size, low_size, name); +} + inline void * open_file_mapping (unsigned long access, const char *name) { return OpenFileMappingA (access, 0, name); } +inline void * open_file_mapping (unsigned long access, const wchar_t *name) +{ return OpenFileMappingW (access, 0, name); } + inline void *map_view_of_file_ex(void *handle, unsigned long file_access, ::boost::ulong_long_type offset, std::size_t numbytes, void *base_addr) { const unsigned long offset_low = (unsigned long)(offset & ((::boost::ulong_long_type)0xFFFFFFFF)); @@ -746,10 +782,11 @@ inline void *map_view_of_file_ex(void *handle, unsigned long file_access, ::boos return MapViewOfFileEx(handle, file_access, offset_high, offset_low, numbytes, base_addr); } -inline void *create_file(const char *name, unsigned long access, unsigned long creation_flags, unsigned long attributes, interprocess_security_attributes *psec) +template +inline void *create_file(const CharT *name, unsigned long access, unsigned long creation_flags, unsigned long attributes, interprocess_security_attributes *psec) { for (unsigned int attempt(0); attempt < error_sharing_violation_tries; ++attempt){ - void * const handle = CreateFileA(name, access, + void * const handle = boost::winapi::create_file(name, access, file_share_read | file_share_write | file_share_delete, psec, creation_flags, attributes, 0); bool const invalid(invalid_handle_value == handle); @@ -782,17 +819,20 @@ inline bool flush_file_buffers(void *handle) inline bool get_file_size(void *handle, __int64 &size) { return 0 != boost::winapi::GetFileSizeEx(handle, (boost::winapi::LARGE_INTEGER_*)&size); } -inline bool create_directory(const char *name) +template +inline bool create_directory(const CharT *name) { interprocess_all_access_security sec; - return 0 != boost::winapi::CreateDirectoryA(name, sec.get_attributes()); + return 0 != boost::winapi::create_directory(name, sec.get_attributes()); } -inline bool remove_directory(const char *lpPathName) -{ return 0 != boost::winapi::RemoveDirectoryA(lpPathName); } +template +inline bool remove_directory(const CharT *lpPathName) +{ return 0 != boost::winapi::remove_directory(lpPathName); } -inline unsigned long get_temp_path(unsigned long length, char *buffer) -{ return boost::winapi::GetTempPathA(length, buffer); } +template +inline unsigned long get_temp_path(unsigned long length, CharT *buffer) +{ return boost::winapi::get_temp_path(length, buffer); } inline int set_end_of_file(void *handle) { return 0 != boost::winapi::SetEndOfFile(handle); } @@ -858,9 +898,16 @@ inline hmodule get_module_handle(const char *name) inline long reg_open_key_ex(hkey hKey, const char *lpSubKey, unsigned long ulOptions, unsigned long samDesired, hkey *phkResult) { return boost::ipwinapiext::RegOpenKeyExA(hKey, lpSubKey, ulOptions, samDesired, phkResult); } +inline long reg_open_key_ex(hkey hKey, const wchar_t *lpSubKey, unsigned long ulOptions, unsigned long samDesired, hkey *phkResult) +{ return boost::ipwinapiext::RegOpenKeyExW(hKey, lpSubKey, ulOptions, samDesired, phkResult); } + + inline long reg_query_value_ex(hkey hKey, const char *lpValueName, unsigned long*lpReserved, unsigned long*lpType, unsigned char *lpData, unsigned long*lpcbData) { return boost::ipwinapiext::RegQueryValueExA(hKey, lpValueName, lpReserved, lpType, lpData, lpcbData); } +inline long reg_query_value_ex(hkey hKey, const wchar_t *lpValueName, unsigned long*lpReserved, unsigned long*lpType, unsigned char *lpData, unsigned long*lpcbData) +{ return boost::ipwinapiext::RegQueryValueExW(hKey, lpValueName, lpReserved, lpType, lpData, lpcbData); } + inline long reg_close_key(hkey hKey) { return boost::ipwinapiext::RegCloseKey(hKey); } @@ -1213,7 +1260,8 @@ class c_heap_deleter void *m_buf; }; -inline bool unlink_file(const char *filename) +template +inline bool unlink_file(const CharT *filename) { //Don't try to optimize doing a DeleteFile first //as there are interactions with permissions and @@ -1337,7 +1385,8 @@ struct reg_closer ~reg_closer(){ reg_close_key(key_); } }; -inline bool get_registry_value_buffer(hkey key_type, const char *subkey_name, const char *value_name, void *buf, std::size_t &buflen) +template +inline bool get_registry_value_buffer(hkey key_type, const CharT *subkey_name, const CharT *value_name, void *buf, std::size_t &buflen) { bool bret = false; hkey key; @@ -1359,7 +1408,8 @@ inline bool get_registry_value_buffer(hkey key_type, const char *subkey_name, co return bret; } -inline bool get_registry_value_string(hkey key_type, const char *subkey_name, const char *value_name, std::string &s) +template +inline bool get_registry_value_string(hkey key_type, const CharT *subkey_name, const CharT *value_name, std::basic_string &s) { bool bret = false; s.clear(); @@ -1377,7 +1427,7 @@ inline bool get_registry_value_string(hkey key_type, const char *subkey_name, co 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); + s.resize(size/sizeof(CharT)); err = reg_query_value_ex( key, value_name, 0, &type, (unsigned char*)(&s[0]), &size); if(!err){ s.erase(s.end()-1); @@ -1389,7 +1439,8 @@ inline bool get_registry_value_string(hkey key_type, const char *subkey_name, co return bret; } -inline void get_shared_documents_folder(std::string &s) +template +inline void get_shared_documents_folder(std::basic_string &s) { get_registry_value_string( hkey_local_machine , "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders" @@ -1397,7 +1448,16 @@ inline void get_shared_documents_folder(std::string &s) , s); } -inline void get_registry_value(const char *folder, const char *value_key, std::vector &s) +inline void get_shared_documents_folder(std::wstring &s) +{ + get_registry_value_string( hkey_local_machine + , L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders" + , L"Common AppData" + , s); +} + +template +inline void get_registry_value(const CharT *folder, const CharT *value_key, std::vector &s) { s.clear(); hkey key; @@ -1479,6 +1539,22 @@ inline unsigned long get_tick_count() { return GetTickCount(); } +template +struct winapi_traits; + +template<> +struct winapi_traits +{ + static int cmp(const char *a, const char *b) + { return std::strcmp(a, b); } +}; + +template<> +struct winapi_traits +{ + static int cmp(const wchar_t *a, const wchar_t *b) + { return std::wcscmp(a, b); } +}; #if defined(BOOST_INTERPROCESS_BOOTSTAMP_IS_SESSION_MANAGER_BASED) @@ -1514,6 +1590,36 @@ inline bool get_last_bootup_time(std::string &stamp) return b_ret; } +inline bool get_last_bootup_time(std::wstring &stamp) +{ + unsigned dword_val = 0; + std::size_t dword_size = sizeof(dword_val); + bool b_ret = get_registry_value_buffer( hkey_local_machine + , L"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management\\PrefetchParameters" + , L"BootId", &dword_val, dword_size); + if (b_ret) + { + wchar_t dword_str[sizeof(dword_val)*2u+1]; + buffer_to_wide_str(&dword_val, dword_size, dword_str); + dword_str[sizeof(dword_val)*2] = L'\0'; + stamp = dword_str; + + b_ret = get_registry_value_buffer( hkey_local_machine + , L"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Power" + , L"HybridBootAnimationTime", &dword_val, dword_size); + //Old Windows versions have no HybridBootAnimationTime + if(b_ret) + { + buffer_to_wide_str(&dword_val, dword_size, dword_str); + dword_str[sizeof(dword_val)*2] = L'\0'; + stamp += L"_"; + stamp += dword_str; + } + b_ret = true; + } + return b_ret; +} + #elif defined(BOOST_INTERPROCESS_BOOTSTAMP_IS_EVENTLOG_BASED) static const unsigned long eventlog_sequential_read = 0x0001; @@ -1563,7 +1669,8 @@ class eventlog_handle_closer // 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 +template +inline bool find_record_in_buffer( const void* pBuffer, unsigned long dwBytesRead, const CharT *provider_name , unsigned int id_to_find, interprocess_eventlogrecord *&pevent_log_record) { const unsigned char * pRecord = static_cast(pBuffer); @@ -1572,7 +1679,8 @@ inline bool find_record_in_buffer( const void* pBuffer, unsigned long dwBytesRea 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)))) + + if (0 == winapi_traits::cmp(provider_name, (CharT*)(pRecord + sizeof(interprocess_eventlogrecord)))) { // Check event id if(id_to_find == (pTypedRecord->EventID & 0xFFFF)){ @@ -1655,6 +1763,72 @@ inline bool get_last_bootup_time(std::string &stamp) return true; } + +inline bool get_last_bootup_time(std::wstring &stamp) +{ + const wchar_t *source_name = L"System"; + const wchar_t *provider_name = L"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 = OpenEventLogW(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 (!ReadEventLogW(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)){ + wchar_t stamp_str[sizeof(unsigned long)*3+1]; + std::swprintf(&stamp_str[0], L"%u", ((unsigned int)pTypedRecord->TimeGenerated)); + stamp = stamp_str; + break; + } + } + } + } + } + return true; +} + #endif //BOOST_INTERPROCESS_BOOTSTAMP_IS_EVENTLOG_BASED diff --git a/include/boost/interprocess/detail/workaround.hpp b/include/boost/interprocess/detail/workaround.hpp index 75b6f67..aad6c39 100644 --- a/include/boost/interprocess/detail/workaround.hpp +++ b/include/boost/interprocess/detail/workaround.hpp @@ -198,4 +198,11 @@ #define BOOST_INTERPROCESS_FORCEINLINE BOOST_FORCEINLINE #endif +#ifdef BOOST_WINDOWS + +#define BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES + +#endif + + #endif //#ifndef BOOST_INTERPROCESS_DETAIL_WORKAROUND_HPP diff --git a/include/boost/interprocess/file_mapping.hpp b/include/boost/interprocess/file_mapping.hpp index 0d1cf1f..282420b 100644 --- a/include/boost/interprocess/file_mapping.hpp +++ b/include/boost/interprocess/file_mapping.hpp @@ -32,8 +32,8 @@ #include #include #include +#include #include -#include //std::string //!\file //!Describes file_mapping and mapped region classes @@ -60,6 +60,17 @@ class file_mapping //!modes. Throws interprocess_exception on error. file_mapping(const char *filename, mode_t mode); + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + //!Opens a file mapping of file "filename", starting in offset + //!"file_offset", and the mapping's size will be "size". The mapping + //!can be opened for read-only "read_only" or read-write "read_write" + //!modes. Throws interprocess_exception on error. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + file_mapping(const wchar_t *filename, mode_t mode); + #endif + //!Moves the ownership of "moved"'s file mapping object to *this. //!After the call, "moved" does not represent any file mapping object. //!Does not throw @@ -104,13 +115,24 @@ class file_mapping //!being used other processes and no deletion permission was shared. static bool remove(const char *filename); + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + //!Removes the file named "filename" even if it's been memory mapped. + //!Returns true on success. + //!The function might fail in some operating systems if the file is + //!being used other processes and no deletion permission was shared. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + static bool remove(const wchar_t *filename); + #endif + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: //!Closes a previously opened file mapping. Never throws. void priv_close(); file_handle_t m_handle; mode_t m_mode; - std::string m_filename; + char_wchar_holder m_filename; #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }; @@ -123,7 +145,7 @@ inline file_mapping::~file_mapping() { this->priv_close(); } inline const char *file_mapping::get_name() const -{ return m_filename.c_str(); } +{ return m_filename.getn(); } inline void file_mapping::swap(file_mapping &other) { @@ -163,6 +185,35 @@ inline file_mapping::file_mapping inline bool file_mapping::remove(const char *filename) { return ipcdetail::delete_file(filename); } +#ifdef BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES +inline file_mapping::file_mapping + (const wchar_t *filename, mode_t mode) + : m_filename(filename) +{ + //Check accesses + if (mode != read_write && mode != read_only){ + error_info err = other_error; + throw interprocess_exception(err); + } + + //Open file + m_handle = ipcdetail::open_existing_file(filename, mode); + + //Check for error + if(m_handle == ipcdetail::invalid_file()){ + error_info err = system_error_code(); + this->priv_close(); + throw interprocess_exception(err); + } + m_mode = mode; +} + +inline bool file_mapping::remove(const wchar_t *filename) +{ return ipcdetail::delete_file(filename); } + +#endif + + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) inline void file_mapping::priv_close() diff --git a/include/boost/interprocess/ipc/message_queue.hpp b/include/boost/interprocess/ipc/message_queue.hpp index 6b17665..bc6c5b9 100644 --- a/include/boost/interprocess/ipc/message_queue.hpp +++ b/include/boost/interprocess/ipc/message_queue.hpp @@ -99,8 +99,45 @@ class message_queue_t //!Opens a previously created process shared message queue with name "name". //!If the queue was not previously created or there are no free resources, //!throws an error. - message_queue_t(open_only_t open_only, - const char *name); + message_queue_t(open_only_t open_only, const char *name); + + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Creates a process shared message queue with name "name". For this message queue, + //!the maximum number of messages will be "max_num_msg" and the maximum message size + //!will be "max_msg_size". Throws on error and if the queue was previously created. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + message_queue_t(create_only_t create_only, + const wchar_t *name, + size_type max_num_msg, + size_type max_msg_size, + const permissions &perm = permissions()); + + //!Opens or creates a process shared message queue with name "name". + //!If the queue is created, the maximum number of messages will be "max_num_msg" + //!and the maximum message size will be "max_msg_size". If queue was previously + //!created the queue will be opened and "max_num_msg" and "max_msg_size" parameters + //!are ignored. Throws on error. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + message_queue_t(open_or_create_t open_or_create, + const wchar_t *name, + size_type max_num_msg, + size_type max_msg_size, + const permissions &perm = permissions()); + + //!Opens a previously created process shared message queue with name "name". + //!If the queue was not previously created or there are no free resources, + //!throws an error. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + message_queue_t(open_only_t open_only, const wchar_t *name); + + #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) //!Destroys *this and indicates that the calling process is finished using //!the resource. All opened message queues are still @@ -175,6 +212,17 @@ class message_queue_t //!Returns false on error. Never throws static bool remove(const char *name); + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Removes the message queue from the system. + //!Returns false on error. Never throws + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + static bool remove(const wchar_t *name); + + #endif + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: typedef boost::posix_time::ptime ptime; @@ -694,6 +742,55 @@ inline message_queue_t::message_queue_t(open_only_t, const char *na ipcdetail::msg_queue_initialization_func_t ()) {} +#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +template +inline message_queue_t::message_queue_t(create_only_t, + const wchar_t *name, + size_type max_num_msg, + size_type max_msg_size, + const permissions &perm) + //Create shared memory and execute functor atomically + : m_shmem(create_only, + name, + get_mem_size(max_msg_size, max_num_msg), + read_write, + static_cast(0), + //Prepare initialization functor + ipcdetail::msg_queue_initialization_func_t (max_num_msg, max_msg_size), + perm) +{} + +template +inline message_queue_t::message_queue_t(open_or_create_t, + const wchar_t *name, + size_type max_num_msg, + size_type max_msg_size, + const permissions &perm) + //Create shared memory and execute functor atomically + : m_shmem(open_or_create, + name, + get_mem_size(max_msg_size, max_num_msg), + read_write, + static_cast(0), + //Prepare initialization functor + ipcdetail::msg_queue_initialization_func_t (max_num_msg, max_msg_size), + perm) +{} + +template +inline message_queue_t::message_queue_t(open_only_t, const wchar_t *name) + //Create shared memory and execute functor atomically + : m_shmem(open_only, + name, + read_write, + static_cast(0), + //Prepare initialization functor + ipcdetail::msg_queue_initialization_func_t ()) +{} + +#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + template inline void message_queue_t::send (const void *buffer, size_type buffer_size, unsigned int priority) @@ -981,6 +1078,14 @@ template inline bool message_queue_t::remove(const char *name) { return shared_memory_object::remove(name); } +#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +template +inline bool message_queue_t::remove(const wchar_t *name) +{ return shared_memory_object::remove(name); } + +#endif + #else //!Typedef for a default message queue diff --git a/include/boost/interprocess/managed_mapped_file.hpp b/include/boost/interprocess/managed_mapped_file.hpp index 14ec160..49b127c 100644 --- a/include/boost/interprocess/managed_mapped_file.hpp +++ b/include/boost/interprocess/managed_mapped_file.hpp @@ -142,6 +142,74 @@ class basic_managed_mapped_file ipcdetail::DoOpen)) {} + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Creates mapped file and creates and places the segment manager. + //!This can throw. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + basic_managed_mapped_file(create_only_t, const wchar_t *name, + size_type size, const void *addr = 0, const permissions &perm = permissions()) + : m_mfile(create_only, name, size, read_write, addr, + create_open_func_t(get_this_pointer(), ipcdetail::DoCreate), perm) + {} + + //!Creates mapped file and creates and places the segment manager if + //!segment was not created. If segment was created it connects to the + //!segment. + //!This can throw. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + basic_managed_mapped_file (open_or_create_t, + const wchar_t *name, size_type size, + const void *addr = 0, const permissions &perm = permissions()) + : m_mfile(open_or_create, name, size, read_write, addr, + create_open_func_t(get_this_pointer(), + ipcdetail::DoOpenOrCreate), perm) + {} + + //!Connects to a created mapped file and its segment manager. + //!This can throw. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + basic_managed_mapped_file (open_only_t, const wchar_t* name, + const void *addr = 0) + : m_mfile(open_only, name, read_write, addr, + create_open_func_t(get_this_pointer(), + ipcdetail::DoOpen)) + {} + + //!Connects to a created mapped file and its segment manager + //!in copy_on_write mode. + //!This can throw. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + basic_managed_mapped_file (open_copy_on_write_t, const wchar_t* name, + const void *addr = 0) + : m_mfile(open_only, name, copy_on_write, addr, + create_open_func_t(get_this_pointer(), + ipcdetail::DoOpen)) + {} + + //!Connects to a created mapped file and its segment manager + //!in read-only mode. + //!This can throw. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + basic_managed_mapped_file (open_read_only_t, const wchar_t* name, + const void *addr = 0) + : m_mfile(open_only, name, read_only, addr, + create_open_func_t(get_this_pointer(), + ipcdetail::DoOpen)) + {} + + #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + //!Moves the ownership of "moved"'s managed memory to *this. //!Does not throw basic_managed_mapped_file(BOOST_RV_REF(basic_managed_mapped_file) moved) @@ -201,6 +269,37 @@ class basic_managed_mapped_file (filename); } + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Tries to resize mapped file so that we have room for + //!more objects. + //! + //!This function is not synchronized so no other thread or process should + //!be reading or writing the file + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + static bool grow(const wchar_t *filename, size_type extra_bytes) + { + return base_t::template grow + (filename, extra_bytes); + } + + //!Tries to resize mapped file to minimized the size of the file. + //! + //!This function is not synchronized so no other thread or process should + //!be reading or writing the file + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + static bool shrink_to_fit(const wchar_t *filename) + { + return base_t::template shrink_to_fit + (filename); + } + + #endif + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) //!Tries to find a previous named allocation address. Returns a memory diff --git a/include/boost/interprocess/managed_shared_memory.hpp b/include/boost/interprocess/managed_shared_memory.hpp index fadc19a..fc1eab0 100644 --- a/include/boost/interprocess/managed_shared_memory.hpp +++ b/include/boost/interprocess/managed_shared_memory.hpp @@ -151,6 +151,79 @@ class basic_managed_shared_memory ipcdetail::DoOpen)) {} + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Creates shared memory and creates and places the segment manager. + //!This can throw. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + basic_managed_shared_memory(create_only_t, const wchar_t *name, + size_type size, const void *addr = 0, const permissions& perm = permissions()) + : base_t() + , base2_t(create_only, name, size, read_write, addr, + create_open_func_t(get_this_pointer(), ipcdetail::DoCreate), perm) + {} + + //!Creates shared memory and creates and places the segment manager if + //!segment was not created. If segment was created it connects to the + //!segment. + //!This can throw. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + basic_managed_shared_memory (open_or_create_t, + const wchar_t *name, size_type size, + const void *addr = 0, const permissions& perm = permissions()) + : base_t() + , base2_t(open_or_create, name, size, read_write, addr, + create_open_func_t(get_this_pointer(), + ipcdetail::DoOpenOrCreate), perm) + {} + + //!Connects to a created shared memory and its segment manager. + //!in copy_on_write mode. + //!This can throw. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + basic_managed_shared_memory (open_copy_on_write_t, const wchar_t* name, + const void *addr = 0) + : base_t() + , base2_t(open_only, name, copy_on_write, addr, + create_open_func_t(get_this_pointer(), + ipcdetail::DoOpen)) + {} + + //!Connects to a created shared memory and its segment manager. + //!in read-only mode. + //!This can throw. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + basic_managed_shared_memory (open_read_only_t, const wchar_t* name, + const void *addr = 0) + : base_t() + , base2_t(open_only, name, read_only, addr, + create_open_func_t(get_this_pointer(), + ipcdetail::DoOpen)) + {} + + //!Connects to a created shared memory and its segment manager. + //!This can throw. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + basic_managed_shared_memory (open_only_t, const wchar_t* name, + const void *addr = 0) + : base_t() + , base2_t(open_only, name, read_write, addr, + create_open_func_t(get_this_pointer(), + ipcdetail::DoOpen)) + {} + + #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + //!Moves the ownership of "moved"'s managed memory to *this. //!Does not throw basic_managed_shared_memory(BOOST_RV_REF(basic_managed_shared_memory) moved) @@ -197,6 +270,38 @@ class basic_managed_shared_memory return base_t::template shrink_to_fit (shmname); } + + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Tries to resize the managed shared memory object so that we have + //!room for more objects. + //! + //!This function is not synchronized so no other thread or process should + //!be reading or writing the file + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + static bool grow(const wchar_t *shmname, size_type extra_bytes) + { + return base_t::template grow + (shmname, extra_bytes); + } + + //!Tries to resize the managed shared memory to minimized the size of the file. + //! + //!This function is not synchronized so no other thread or process should + //!be reading or writing the file + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + static bool shrink_to_fit(const wchar_t *shmname) + { + return base_t::template shrink_to_fit + (shmname); + } + + #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) //!Tries to find a previous named allocation address. Returns a memory diff --git a/include/boost/interprocess/managed_windows_shared_memory.hpp b/include/boost/interprocess/managed_windows_shared_memory.hpp index 2ff30c9..99746ce 100644 --- a/include/boost/interprocess/managed_windows_shared_memory.hpp +++ b/include/boost/interprocess/managed_windows_shared_memory.hpp @@ -143,6 +143,48 @@ class basic_managed_windows_shared_memory create_open_func_t(get_this_pointer(), ipcdetail::DoOpen)) {} + //!Creates shared memory and creates and places the segment manager if + //!segment was not created. If segment was created it connects to the + //!segment. + //!This can throw. + basic_managed_windows_shared_memory + (open_or_create_t, + const wchar_t *name, size_type size, + const void *addr = 0, + const permissions &perm = permissions()) + : m_wshm(open_or_create, name, size, read_write, addr, + create_open_func_t(get_this_pointer(), + ipcdetail::DoOpenOrCreate), perm) + {} + + //!Connects to a created shared memory and its segment manager. + //!This can throw. + basic_managed_windows_shared_memory + (open_only_t, const wchar_t* name, const void *addr = 0) + : m_wshm(open_only, name, read_write, addr, + create_open_func_t(get_this_pointer(), + ipcdetail::DoOpen)) + {} + + //!Connects to a created shared memory and its segment manager + //!in copy_on_write mode. + //!This can throw. + basic_managed_windows_shared_memory + (open_copy_on_write_t, const wchar_t* name, const void *addr = 0) + : m_wshm(open_only, name, copy_on_write, addr, + create_open_func_t(get_this_pointer(), ipcdetail::DoOpen)) + {} + + //!Connects to a created shared memory and its segment manager + //!in read-only mode. + //!This can throw. + basic_managed_windows_shared_memory + (open_read_only_t, const wchar_t* name, const void *addr = 0) + : base_t() + , m_wshm(open_only, name, read_only, addr, + create_open_func_t(get_this_pointer(), ipcdetail::DoOpen)) + {} + //!Moves the ownership of "moved"'s managed memory to *this. //!Does not throw basic_managed_windows_shared_memory diff --git a/include/boost/interprocess/mapped_region.hpp b/include/boost/interprocess/mapped_region.hpp index 11ac456..407d9e2 100644 --- a/include/boost/interprocess/mapped_region.hpp +++ b/include/boost/interprocess/mapped_region.hpp @@ -442,7 +442,7 @@ inline mapped_region::mapped_region //Create mapping handle native_mapping_handle = winapi::create_file_mapping ( ipcdetail::file_handle_from_mapping_handle(mapping.get_mapping_handle()) - , protection, 0, 0, 0); + , protection, 0, (char*)0, 0); //Check if all is correct if(!native_mapping_handle){ diff --git a/include/boost/interprocess/segment_manager.hpp b/include/boost/interprocess/segment_manager.hpp index 0eb6265..14b11cb 100644 --- a/include/boost/interprocess/segment_manager.hpp +++ b/include/boost/interprocess/segment_manager.hpp @@ -839,8 +839,8 @@ class segment_manager size_type &length, ipcdetail::true_ is_intrusive, bool use_lock) { (void)is_intrusive; - typedef IndexType > index_type; - typedef typename index_type::iterator index_it; + typedef IndexType > index_type_t; + typedef typename index_type_t::iterator index_it; //------------------------------- scoped_lock guard(priv_get_lock(use_lock)); @@ -936,9 +936,9 @@ class segment_manager ipcdetail::in_place_interface &table, ipcdetail::true_ is_intrusive_index) { (void)is_intrusive_index; - typedef IndexType > index_type; - typedef typename index_type::iterator index_it; - typedef typename index_type::value_type intrusive_value_type; + typedef IndexType > index_type_t; + typedef typename index_type_t::iterator index_it; + typedef typename index_type_t::value_type intrusive_value_type; //------------------------------- scoped_lock guard(m_header); @@ -1070,8 +1070,8 @@ class segment_manager , sizeof(CharT) , namelen); - typedef IndexType > index_type; - typedef typename index_type::iterator index_it; + typedef IndexType > index_type_t; + typedef typename index_type_t::iterator index_it; typedef std::pair index_ib; //------------------------------- @@ -1090,8 +1090,8 @@ class segment_manager //the key (which is a smart pointer) to an equivalent one index_ib insert_ret; - typename index_type::insert_commit_data commit_data; - typedef typename index_type::value_type intrusive_value_type; + typename index_type_t::insert_commit_data commit_data; + typedef typename index_type_t::value_type intrusive_value_type; BOOST_TRY{ ipcdetail::intrusive_compare_key key(name, namelen); @@ -1167,7 +1167,7 @@ class segment_manager //if something goes wrong. This will be executed *before* //the memory allocation as the intrusive value is built in that //memory - value_eraser v_eraser(index, it); + value_eraser v_eraser(index, it); //Construct array, this can throw ipcdetail::array_construct(ptr, num, table); @@ -1195,11 +1195,11 @@ class segment_manager , sizeof(CharT) , namelen); - typedef IndexType > index_type; - typedef typename index_type::key_type key_type; - typedef typename index_type::mapped_type mapped_type; - typedef typename index_type::value_type value_type; - typedef typename index_type::iterator index_it; + typedef IndexType > index_type_t; + typedef typename index_type_t::key_type key_type; + typedef typename index_type_t::mapped_type mapped_type; + typedef typename index_type_t::value_type value_type; + typedef typename index_type_t::iterator index_it; typedef std::pair index_ib; //------------------------------- @@ -1242,7 +1242,7 @@ class segment_manager } //Initialize the node value_eraser to erase inserted node //if something goes wrong - value_eraser v_eraser(index, it); + value_eraser v_eraser(index, it); //Allocates buffer for name + data, this can throw (it hurts) void *buffer_ptr; diff --git a/include/boost/interprocess/shared_memory_object.hpp b/include/boost/interprocess/shared_memory_object.hpp index 271a571..1cd5fd0 100644 --- a/include/boost/interprocess/shared_memory_object.hpp +++ b/include/boost/interprocess/shared_memory_object.hpp @@ -28,12 +28,13 @@ #include #include #include +#include #include #include #include -#include #if defined(BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS) +# include # include //O_CREAT, O_*... # include //shm_xxx # include //ftruncate, close @@ -82,6 +83,35 @@ class shared_memory_object shared_memory_object(open_only_t, const char *name, mode_t mode) { this->priv_open_or_create(ipcdetail::DoOpen, name, mode, permissions()); } + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Creates a shared memory object with name "name" and mode "mode", with the access mode "mode" + //!If the file previously exists, throws an error. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + shared_memory_object(create_only_t, const wchar_t*name, mode_t mode, const permissions &perm = permissions()) + { this->priv_open_or_create(ipcdetail::DoCreate, name, mode, perm); } + + //!Tries to create a shared memory object with name "name" and mode "mode", with the + //!access mode "mode". If the file previously exists, it tries to open it with mode "mode". + //!Otherwise throws an error. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + shared_memory_object(open_or_create_t, const wchar_t*name, mode_t mode, const permissions &perm = permissions()) + { this->priv_open_or_create(ipcdetail::DoOpenOrCreate, name, mode, perm); } + + //!Tries to open a shared memory object with name "name", with the access mode "mode". + //!If the file does not previously exist, it throws an error. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + shared_memory_object(open_only_t, const wchar_t*name, mode_t mode) + { this->priv_open_or_create(ipcdetail::DoOpen, name, mode, permissions()); } + + #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + //!Moves the ownership of "moved"'s shared memory object to *this. //!After the call, "moved" does not represent any shared memory object. //!Does not throw @@ -107,6 +137,17 @@ class shared_memory_object //!Returns false on error. Never throws static bool remove(const char *name); + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Erases a shared memory object from the system. + //!Returns false on error. Never throws + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + static bool remove(const wchar_t *name); + + #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + //!Sets the size of the shared memory mapping void truncate(offset_t length); @@ -139,11 +180,12 @@ class shared_memory_object void priv_close(); //!Opens or creates a shared memory object. - bool priv_open_or_create(ipcdetail::create_enum_t type, const char *filename, mode_t mode, const permissions &perm); + template + bool priv_open_or_create(ipcdetail::create_enum_t type, const CharT *filename, mode_t mode, const permissions &perm); - file_handle_t m_handle; - mode_t m_mode; - std::string m_filename; + file_handle_t m_handle; + mode_t m_mode; + char_wchar_holder m_filename; #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }; @@ -159,7 +201,7 @@ inline shared_memory_object::~shared_memory_object() inline const char *shared_memory_object::get_name() const -{ return m_filename.c_str(); } +{ return m_filename.getn(); } inline bool shared_memory_object::get_size(offset_t &size) const { return ipcdetail::get_file_size((file_handle_t)m_handle, size); } @@ -181,11 +223,12 @@ inline mode_t shared_memory_object::get_mode() const #if !defined(BOOST_INTERPROCESS_POSIX_SHARED_MEMORY_OBJECTS) +template inline bool shared_memory_object::priv_open_or_create - (ipcdetail::create_enum_t type, const char *filename, mode_t mode, const permissions &perm) + (ipcdetail::create_enum_t type, const CharT *filename, mode_t mode, const permissions &perm) { m_filename = filename; - std::string shmfile; + std::basic_string shmfile; ipcdetail::create_shared_dir_cleaning_old_and_get_filepath(filename, shmfile); //Set accesses @@ -222,6 +265,23 @@ inline bool shared_memory_object::priv_open_or_create return true; } +#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) + +inline bool shared_memory_object::remove(const wchar_t *filename) +{ + try{ + //Make sure a temporary path is created for shared memory + std::wstring shmfile; + ipcdetail::shared_filepath(filename, shmfile); + return ipcdetail::delete_file(shmfile.c_str()); + } + catch(...){ + return false; + } +} + +#endif + inline bool shared_memory_object::remove(const char *filename) { try{ @@ -275,9 +335,10 @@ inline bool use_filesystem_based_posix() } //shared_memory_object_detail +template inline bool shared_memory_object::priv_open_or_create (ipcdetail::create_enum_t type, - const char *filename, + const CharT *filename, mode_t mode, const permissions &perm) { #if defined(BOOST_INTERPROCESS_FILESYSTEM_BASED_POSIX_SHARED_MEMORY) @@ -287,11 +348,12 @@ inline bool shared_memory_object::priv_open_or_create #else const bool add_leading_slash = true; #endif + std::basic_string fname; if(add_leading_slash){ - ipcdetail::add_leading_slash(filename, m_filename); + ipcdetail::add_leading_slash(filename, fname); } else{ - ipcdetail::create_shared_dir_cleaning_old_and_get_filepath(filename, m_filename); + ipcdetail::create_shared_dir_cleaning_old_and_get_filepath(filename, fname); } //Create new mapping @@ -312,13 +374,13 @@ inline bool shared_memory_object::priv_open_or_create case ipcdetail::DoOpen: { //No oflag addition - m_handle = shm_open(m_filename.c_str(), oflag, unix_perm); + m_handle = shm_open(fname.c_str(), oflag, unix_perm); } break; case ipcdetail::DoCreate: { oflag |= (O_CREAT | O_EXCL); - m_handle = shm_open(m_filename.c_str(), oflag, unix_perm); + m_handle = shm_open(fname.c_str(), oflag, unix_perm); if(m_handle >= 0){ ::fchmod(m_handle, unix_perm); } @@ -330,14 +392,14 @@ inline bool shared_memory_object::priv_open_or_create //with "O_CREAT" only we don't know if we've created or opened the shm. while(true){ //Try to create shared memory - m_handle = shm_open(m_filename.c_str(), oflag | (O_CREAT | O_EXCL), unix_perm); + m_handle = shm_open(fname.c_str(), oflag | (O_CREAT | O_EXCL), unix_perm); //If successful change real permissions if(m_handle >= 0){ ::fchmod(m_handle, unix_perm); } //If already exists, try to open else if(errno == EEXIST){ - m_handle = shm_open(m_filename.c_str(), oflag, unix_perm); + m_handle = shm_open(fname.c_str(), oflag, unix_perm); //If open fails and errno tells the file does not exist //(shm was removed between creation and opening tries), just retry if(m_handle < 0 && errno == ENOENT){ diff --git a/include/boost/interprocess/sync/file_lock.hpp b/include/boost/interprocess/sync/file_lock.hpp index a488b5b..6007f2a 100644 --- a/include/boost/interprocess/sync/file_lock.hpp +++ b/include/boost/interprocess/sync/file_lock.hpp @@ -59,6 +59,15 @@ class file_lock //!exist or there are no operating system resources. file_lock(const char *name); + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + //!Opens a file lock. Throws interprocess_exception if the file does not + //!exist or there are no operating system resources. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + file_lock(const wchar_t *name); + #endif + //!Moves the ownership of "moved"'s file mapping object to *this. //!After the call, "moved" does not represent any file mapping object. //!Does not throw @@ -160,6 +169,20 @@ inline file_lock::file_lock(const char *name) } } +#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline file_lock::file_lock(const wchar_t *name) +{ + m_file_hnd = ipcdetail::open_existing_file(name, read_write); + + if(m_file_hnd == ipcdetail::invalid_file()){ + error_info err(system_error_code()); + throw interprocess_exception(err); + } +} + +#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + inline file_lock::~file_lock() { if(m_file_hnd != ipcdetail::invalid_file()){ diff --git a/include/boost/interprocess/sync/named_condition.hpp b/include/boost/interprocess/sync/named_condition.hpp index 6d9b757..b448d37 100644 --- a/include/boost/interprocess/sync/named_condition.hpp +++ b/include/boost/interprocess/sync/named_condition.hpp @@ -56,6 +56,7 @@ class named_condition named_condition &operator=(const named_condition &); #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED public: + //!Creates a global condition with a name. //!If the condition can't be created throws interprocess_exception named_condition(create_only_t create_only, const char *name, const permissions &perm = permissions()); @@ -73,6 +74,39 @@ class named_condition //!interprocess_exception. named_condition(open_only_t open_only, const char *name); + //!Opens a global condition with a name if that condition is previously + //!created. If it is not previously created this function throws + //!interprocess_exception. + + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + //!Creates a global condition with a name. + //!If the condition can't be created throws interprocess_exception + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + named_condition(create_only_t create_only, const wchar_t *name, const permissions &perm = permissions()); + + //!Opens or creates a global condition with a name. + //!If the condition is created, this call is equivalent to + //!named_condition(create_only_t, ... ) + //!If the condition is already created, this call is equivalent + //!named_condition(open_only_t, ... ) + //!Does not throw + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + named_condition(open_or_create_t open_or_create, const wchar_t *name, const permissions &perm = permissions()); + + //!Opens a global condition with a name if that condition is previously + //!created. If it is not previously created this function throws + //!interprocess_exception. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + named_condition(open_only_t open_only, const wchar_t *name); + + #endif //#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + //!Destroys *this and indicates that the calling process is finished using //!the resource. The destructor function will deallocate //!any system resources allocated by the system for use by this process for @@ -118,6 +152,17 @@ class named_condition //!Returns false on error. Never throws. static bool remove(const char *name); + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Erases a named condition from the system. + //!Returns false on error. Never throws. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + static bool remove(const wchar_t *name); + + #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: #if defined(BOOST_INTERPROCESS_USE_WINDOWS) @@ -150,6 +195,23 @@ inline named_condition::named_condition(open_only_t, const char *name) : m_cond(open_only_t(), name) {} +#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline named_condition::named_condition(create_only_t, const wchar_t *name, const permissions &perm) + : m_cond(create_only_t(), name, perm) +{} + +inline named_condition::named_condition(open_or_create_t, const wchar_t *name, const permissions &perm) + : m_cond(open_or_create_t(), name, perm) +{} + +inline named_condition::named_condition(open_only_t, const wchar_t *name) + : m_cond(open_only_t(), name) +{} + +#endif //#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + inline void named_condition::notify_one() { m_cond.notify_one(); } @@ -191,6 +253,16 @@ inline bool named_condition::remove(const char *name) return condition_type::remove(name); } +#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline bool named_condition::remove(const wchar_t *name) +{ + return condition_type::remove(name); +} + +#endif + + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED } //namespace interprocess diff --git a/include/boost/interprocess/sync/named_condition_any.hpp b/include/boost/interprocess/sync/named_condition_any.hpp index a622470..b03086c 100644 --- a/include/boost/interprocess/sync/named_condition_any.hpp +++ b/include/boost/interprocess/sync/named_condition_any.hpp @@ -55,6 +55,7 @@ class named_condition_any named_condition_any(const named_condition_any &); named_condition_any &operator=(const named_condition_any &); #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + public: //!Creates a global condition with a name. //!If the condition can't be created throws interprocess_exception @@ -79,6 +80,42 @@ class named_condition_any : m_cond(open_only_t(), name) {} + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Creates a global condition with a name. + //!If the condition can't be created throws interprocess_exception + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + named_condition_any(create_only_t, const wchar_t *name, const permissions &perm = permissions()) + : m_cond(create_only_t(), name, perm) + {} + + //!Opens or creates a global condition with a name. + //!If the condition is created, this call is equivalent to + //!named_condition_any(create_only_t, ... ) + //!If the condition is already created, this call is equivalent + //!named_condition_any(open_only_t, ... ) + //!Does not throw + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + named_condition_any(open_or_create_t, const wchar_t *name, const permissions &perm = permissions()) + : m_cond(open_or_create_t(), name, perm) + {} + + //!Opens a global condition with a name if that condition is previously + //!created. If it is not previously created this function throws + //!interprocess_exception. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + named_condition_any(open_only_t, const wchar_t *name) + : m_cond(open_only_t(), name) + {} + + #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + //!Destroys *this and indicates that the calling process is finished using //!the resource. The destructor function will deallocate //!any system resources allocated by the system for use by this process for @@ -132,6 +169,18 @@ class named_condition_any static bool remove(const char *name) { return condition_any_type::remove(name); } + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Erases a named condition from the system. + //!Returns false on error. Never throws. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + static bool remove(const wchar_t *name) + { return condition_any_type::remove(name); } + + #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: #if defined(BOOST_INTERPROCESS_USE_WINDOWS) diff --git a/include/boost/interprocess/sync/named_mutex.hpp b/include/boost/interprocess/sync/named_mutex.hpp index 127e8d8..91a8c1a 100644 --- a/include/boost/interprocess/sync/named_mutex.hpp +++ b/include/boost/interprocess/sync/named_mutex.hpp @@ -77,6 +77,36 @@ class named_mutex //!interprocess_exception. named_mutex(open_only_t open_only, const char *name); + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Creates a global mutex with a name. + //!Throws interprocess_exception on error. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + named_mutex(create_only_t create_only, const wchar_t *name, const permissions &perm = permissions()); + + //!Opens or creates a global mutex with a name. + //!If the mutex is created, this call is equivalent to + //!named_mutex(create_only_t, ... ) + //!If the mutex is already created, this call is equivalent + //!named_mutex(open_only_t, ... ) + //!Does not throw + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + named_mutex(open_or_create_t open_or_create, const wchar_t *name, const permissions &perm = permissions()); + + //!Opens a global mutex with a name if that mutex is previously + //!created. If it is not previously created this function throws + //!interprocess_exception. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + named_mutex(open_only_t open_only, const wchar_t *name); + + #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + //!Destroys *this and indicates that the calling process is finished using //!the resource. The destructor function will deallocate //!any system resources allocated by the system for use by this process for @@ -107,6 +137,17 @@ class named_mutex //!Returns false on error. Never throws. static bool remove(const char *name); + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Erases a named mutex from the system. + //!Returns false on error. Never throws. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + static bool remove(const wchar_t *name); + + #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: friend class ipcdetail::interprocess_tester; @@ -144,6 +185,22 @@ inline named_mutex::named_mutex(open_only_t, const char *name) : m_mut(open_only_t(), name) {} +#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline named_mutex::named_mutex(create_only_t, const wchar_t *name, const permissions &perm) + : m_mut(create_only_t(), name, perm) +{} + +inline named_mutex::named_mutex(open_or_create_t, const wchar_t *name, const permissions &perm) + : m_mut(open_or_create_t(), name, perm) +{} + +inline named_mutex::named_mutex(open_only_t, const wchar_t *name) + : m_mut(open_only_t(), name) +{} + +#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + inline void named_mutex::dont_close_on_destruction() { ipcdetail::interprocess_tester::dont_close_on_destruction(m_mut); } @@ -165,6 +222,13 @@ inline bool named_mutex::timed_lock(const boost::posix_time::ptime &abs_time) inline bool named_mutex::remove(const char *name) { return internal_mutex_type::remove(name); } +#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline bool named_mutex::remove(const wchar_t *name) +{ return internal_mutex_type::remove(name); } + +#endif + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED } //namespace interprocess { diff --git a/include/boost/interprocess/sync/named_recursive_mutex.hpp b/include/boost/interprocess/sync/named_recursive_mutex.hpp index b2f1c20..e6c7ed1 100644 --- a/include/boost/interprocess/sync/named_recursive_mutex.hpp +++ b/include/boost/interprocess/sync/named_recursive_mutex.hpp @@ -71,6 +71,36 @@ class named_recursive_mutex //!interprocess_exception. named_recursive_mutex(open_only_t open_only, const char *name); + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Creates a global recursive_mutex with a name. + //!If the recursive_mutex can't be created throws interprocess_exception + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + named_recursive_mutex(create_only_t create_only, const wchar_t *name, const permissions &perm = permissions()); + + //!Opens or creates a global recursive_mutex with a name. + //!If the recursive_mutex is created, this call is equivalent to + //!named_recursive_mutex(create_only_t, ... ) + //!If the recursive_mutex is already created, this call is equivalent + //!named_recursive_mutex(open_only_t, ... ) + //!Does not throw + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + named_recursive_mutex(open_or_create_t open_or_create, const wchar_t *name, const permissions &perm = permissions()); + + //!Opens a global recursive_mutex with a name if that recursive_mutex is previously + //!created. If it is not previously created this function throws + //!interprocess_exception. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + named_recursive_mutex(open_only_t open_only, const wchar_t *name); + + #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + //!Destroys *this and indicates that the calling process is finished using //!the resource. The destructor function will deallocate //!any system resources allocated by the system for use by this process for @@ -101,6 +131,15 @@ class named_recursive_mutex //!from the system static bool remove(const char *name); + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + //!Erases a named recursive mutex + //!from the system + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + static bool remove(const wchar_t *name); + #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: friend class ipcdetail::interprocess_tester; @@ -137,6 +176,22 @@ inline named_recursive_mutex::named_recursive_mutex(open_only_t, const char *nam : m_mut (open_only, name) {} +#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline named_recursive_mutex::named_recursive_mutex(create_only_t, const wchar_t *name, const permissions &perm) + : m_mut (create_only, name, perm) +{} + +inline named_recursive_mutex::named_recursive_mutex(open_or_create_t, const wchar_t *name, const permissions &perm) + : m_mut (open_or_create, name, perm) +{} + +inline named_recursive_mutex::named_recursive_mutex(open_only_t, const wchar_t *name) + : m_mut (open_only, name) +{} + +#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + inline void named_recursive_mutex::lock() { m_mut.lock(); } @@ -152,6 +207,13 @@ inline bool named_recursive_mutex::timed_lock(const boost::posix_time::ptime &ab inline bool named_recursive_mutex::remove(const char *name) { return impl_t::remove(name); } +#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline bool named_recursive_mutex::remove(const wchar_t *name) +{ return impl_t::remove(name); } + +#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED } //namespace interprocess { diff --git a/include/boost/interprocess/sync/named_semaphore.hpp b/include/boost/interprocess/sync/named_semaphore.hpp index 1e56693..f549ebc 100644 --- a/include/boost/interprocess/sync/named_semaphore.hpp +++ b/include/boost/interprocess/sync/named_semaphore.hpp @@ -74,6 +74,36 @@ class named_semaphore //!interprocess_exception. named_semaphore(open_only_t, const char *name); + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Creates a global semaphore with a name, and an initial count. + //!If the semaphore can't be created throws interprocess_exception + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + named_semaphore(create_only_t, const wchar_t *name, unsigned int initialCount, const permissions &perm = permissions()); + + //!Opens or creates a global semaphore with a name, and an initial count. + //!If the semaphore is created, this call is equivalent to + //!named_semaphore(create_only_t, ...) + //!If the semaphore is already created, this call is equivalent to + //!named_semaphore(open_only_t, ... ) + //!and initialCount is ignored. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + named_semaphore(open_or_create_t, const wchar_t *name, unsigned int initialCount, const permissions &perm = permissions()); + + //!Opens a global semaphore with a name if that semaphore is previously. + //!created. If it is not previously created this function throws + //!interprocess_exception. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + named_semaphore(open_only_t, const wchar_t *name); + + #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + //!Destroys *this and indicates that the calling process is finished using //!the resource. The destructor function will deallocate //!any system resources allocated by the system for use by this process for @@ -108,6 +138,17 @@ class named_semaphore //!Returns false on error. Never throws. static bool remove(const char *name); + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Erases a named semaphore from the system. + //!Returns false on error. Never throws. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + static bool remove(const wchar_t *name); + + #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: friend class ipcdetail::interprocess_tester; @@ -141,6 +182,24 @@ inline named_semaphore::named_semaphore(open_only_t, const char *name) : m_sem(open_only, name) {} +#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline named_semaphore::named_semaphore + (create_only_t, const wchar_t *name, unsigned int initialCount, const permissions &perm) + : m_sem(create_only, name, initialCount, perm) +{} + +inline named_semaphore::named_semaphore + (open_or_create_t, const wchar_t *name, unsigned int initialCount, const permissions &perm) + : m_sem(open_or_create, name, initialCount, perm) +{} + +inline named_semaphore::named_semaphore(open_only_t, const wchar_t *name) + : m_sem(open_only, name) +{} + +#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + inline named_semaphore::~named_semaphore() {} @@ -162,6 +221,13 @@ inline bool named_semaphore::timed_wait(const boost::posix_time::ptime &abs_time inline bool named_semaphore::remove(const char *name) { return impl_t::remove(name); } +#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline bool named_semaphore::remove(const wchar_t *name) +{ return impl_t::remove(name); } + +#endif + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED } //namespace interprocess { diff --git a/include/boost/interprocess/sync/named_sharable_mutex.hpp b/include/boost/interprocess/sync/named_sharable_mutex.hpp index a2dca1c..919cc91 100644 --- a/include/boost/interprocess/sync/named_sharable_mutex.hpp +++ b/include/boost/interprocess/sync/named_sharable_mutex.hpp @@ -72,6 +72,36 @@ class named_sharable_mutex //!interprocess_exception. named_sharable_mutex(open_only_t open_only, const char *name); + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Creates a global sharable mutex with a name. + //!If the sharable mutex can't be created throws interprocess_exception + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + named_sharable_mutex(create_only_t create_only, const wchar_t *name, const permissions &perm = permissions()); + + //!Opens or creates a global sharable mutex with a name. + //!If the sharable mutex is created, this call is equivalent to + //!named_sharable_mutex(create_only_t, ...) + //!If the sharable mutex is already created, this call is equivalent to + //!named_sharable_mutex(open_only_t, ... ). + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + named_sharable_mutex(open_or_create_t open_or_create, const wchar_t *name, const permissions &perm = permissions()); + + //!Opens a global sharable mutex with a name if that sharable mutex + //!is previously. + //!created. If it is not previously created this function throws + //!interprocess_exception. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + named_sharable_mutex(open_only_t open_only, const wchar_t *name); + + #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + //!Destroys *this and indicates that the calling process is finished using //!the resource. The destructor function will deallocate //!any system resources allocated by the system for use by this process for @@ -140,6 +170,14 @@ class named_sharable_mutex //!Returns false on error. Never throws. static bool remove(const char *name); + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Erases a named sharable mutex from the system. + //!Returns false on error. Never throws. + static bool remove(const wchar_t *name); + + #endif + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: friend class ipcdetail::interprocess_tester; @@ -192,6 +230,43 @@ inline named_sharable_mutex::named_sharable_mutex ,construct_func_t(ipcdetail::DoOpen)) {} +#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline named_sharable_mutex::named_sharable_mutex + (create_only_t, const wchar_t *name, const permissions &perm) + : m_shmem (create_only + ,name + ,sizeof(interprocess_sharable_mutex) + + open_create_impl_t::ManagedOpenOrCreateUserOffset + ,read_write + ,0 + ,construct_func_t(ipcdetail::DoCreate) + ,perm) +{} + +inline named_sharable_mutex::named_sharable_mutex + (open_or_create_t, const wchar_t *name, const permissions &perm) + : m_shmem (open_or_create + ,name + ,sizeof(interprocess_sharable_mutex) + + open_create_impl_t::ManagedOpenOrCreateUserOffset + ,read_write + ,0 + ,construct_func_t(ipcdetail::DoOpenOrCreate) + ,perm) +{} + +inline named_sharable_mutex::named_sharable_mutex + (open_only_t, const wchar_t *name) + : m_shmem (open_only + ,name + ,read_write + ,0 + ,construct_func_t(ipcdetail::DoOpen)) +{} + +#endif + inline void named_sharable_mutex::dont_close_on_destruction() { ipcdetail::interprocess_tester::dont_close_on_destruction(m_shmem); } @@ -224,6 +299,13 @@ inline bool named_sharable_mutex::timed_lock_sharable inline bool named_sharable_mutex::remove(const char *name) { return shared_memory_object::remove(name); } +#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline bool named_sharable_mutex::remove(const wchar_t *name) +{ return shared_memory_object::remove(name); } + +#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED } //namespace interprocess { diff --git a/include/boost/interprocess/sync/named_upgradable_mutex.hpp b/include/boost/interprocess/sync/named_upgradable_mutex.hpp index b285d1a..3ba3faa 100644 --- a/include/boost/interprocess/sync/named_upgradable_mutex.hpp +++ b/include/boost/interprocess/sync/named_upgradable_mutex.hpp @@ -73,6 +73,36 @@ class named_upgradable_mutex //!interprocess_exception. named_upgradable_mutex(open_only_t open_only, const char *name); + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Creates a global upgradable mutex with a name. + //!If the upgradable mutex can't be created throws interprocess_exception + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + named_upgradable_mutex(create_only_t create_only, const wchar_t *name, const permissions &perm = permissions()); + + //!Opens or creates a global upgradable mutex with a name. + //!If the upgradable mutex is created, this call is equivalent to + //!named_upgradable_mutex(create_only_t, ...) + //!If the upgradable mutex is already created, this call is equivalent to + //!named_upgradable_mutex(open_only_t, ... ). + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + named_upgradable_mutex(open_or_create_t open_or_create, const wchar_t *name, const permissions &perm = permissions()); + + //!Opens a global upgradable mutex with a name if that upgradable mutex + //!is previously. + //!created. If it is not previously created this function throws + //!interprocess_exception. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + named_upgradable_mutex(open_only_t open_only, const wchar_t *name); + + #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + //!Destroys *this and indicates that the calling process is finished using //!the resource. The destructor function will deallocate //!any system resources allocated by the system for use by this process for @@ -231,6 +261,15 @@ class named_upgradable_mutex //!Returns false on error. Never throws. static bool remove(const char *name); + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + //!Erases a named upgradable mutex from the system. + //!Returns false on error. Never throws. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + static bool remove(const wchar_t *name); + #endif + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: friend class ipcdetail::interprocess_tester; @@ -283,6 +322,43 @@ inline named_upgradable_mutex::named_upgradable_mutex ,construct_func_t(ipcdetail::DoOpen)) {} +#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline named_upgradable_mutex::named_upgradable_mutex + (create_only_t, const wchar_t *name, const permissions &perm) + : m_shmem (create_only + ,name + ,sizeof(interprocess_upgradable_mutex) + + open_create_impl_t::ManagedOpenOrCreateUserOffset + ,read_write + ,0 + ,construct_func_t(ipcdetail::DoCreate) + ,perm) +{} + +inline named_upgradable_mutex::named_upgradable_mutex + (open_or_create_t, const wchar_t *name, const permissions &perm) + : m_shmem (open_or_create + ,name + ,sizeof(interprocess_upgradable_mutex) + + open_create_impl_t::ManagedOpenOrCreateUserOffset + ,read_write + ,0 + ,construct_func_t(ipcdetail::DoOpenOrCreate) + ,perm) +{} + +inline named_upgradable_mutex::named_upgradable_mutex + (open_only_t, const wchar_t *name) + : m_shmem (open_only + ,name + ,read_write + ,0 + ,construct_func_t(ipcdetail::DoOpen)) +{} + +#endif + inline void named_upgradable_mutex::dont_close_on_destruction() { ipcdetail::interprocess_tester::dont_close_on_destruction(m_shmem); } @@ -353,6 +429,14 @@ inline bool named_upgradable_mutex::try_unlock_sharable_and_lock_upgradable() inline bool named_upgradable_mutex::remove(const char *name) { return shared_memory_object::remove(name); } +#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline bool named_upgradable_mutex::remove(const wchar_t *name) +{ return shared_memory_object::remove(name); } + +#endif + + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED } //namespace interprocess { diff --git a/include/boost/interprocess/sync/shm/named_condition.hpp b/include/boost/interprocess/sync/shm/named_condition.hpp index e58f5de..b0fda91 100644 --- a/include/boost/interprocess/sync/shm/named_condition.hpp +++ b/include/boost/interprocess/sync/shm/named_condition.hpp @@ -81,6 +81,36 @@ class shm_named_condition //!interprocess_exception. shm_named_condition(open_only_t open_only, const char *name); + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Creates a global condition with a name. + //!If the condition can't be created throws interprocess_exception + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + shm_named_condition(create_only_t create_only, const wchar_t *name, const permissions &perm = permissions()); + + //!Opens or creates a global condition with a name. + //!If the condition is created, this call is equivalent to + //!shm_named_condition(create_only_t, ... ) + //!If the condition is already created, this call is equivalent + //!shm_named_condition(open_only_t, ... ) + //!Does not throw + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + shm_named_condition(open_or_create_t open_or_create, const wchar_t *name, const permissions &perm = permissions()); + + //!Opens a global condition with a name if that condition is previously + //!created. If it is not previously created this function throws + //!interprocess_exception. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + shm_named_condition(open_only_t open_only, const wchar_t *name); + + #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + //!Destroys *this and indicates that the calling process is finished using //!the resource. The destructor function will deallocate //!any system resources allocated by the system for use by this process for @@ -126,6 +156,17 @@ class shm_named_condition //!Returns false on error. Never throws. static bool remove(const char *name); + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Erases a named condition from the system. + //!Returns false on error. Never throws. + //! + //!Note: This function is only available on operating systems with + //! native wchar_t APIs (e.g. Windows). + static bool remove(const wchar_t *name); + + #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: @@ -198,6 +239,40 @@ inline shm_named_condition::shm_named_condition(open_only_t, const char *name) ,construct_func_t(DoOpen)) {} +#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline shm_named_condition::shm_named_condition(create_only_t, const wchar_t *name, const permissions &perm) + : m_shmem (create_only + ,name + ,sizeof(internal_condition) + + open_create_impl_t::ManagedOpenOrCreateUserOffset + ,read_write + ,0 + ,construct_func_t(DoCreate) + ,perm) +{} + +inline shm_named_condition::shm_named_condition(open_or_create_t, const wchar_t *name, const permissions &perm) + : m_shmem (open_or_create + ,name + ,sizeof(internal_condition) + + open_create_impl_t::ManagedOpenOrCreateUserOffset + ,read_write + ,0 + ,construct_func_t(DoOpenOrCreate) + ,perm) +{} + +inline shm_named_condition::shm_named_condition(open_only_t, const wchar_t *name) + : m_shmem (open_only + ,name + ,read_write + ,0 + ,construct_func_t(DoOpen)) +{} + +#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + inline void shm_named_condition::dont_close_on_destruction() { interprocess_tester::dont_close_on_destruction(m_shmem); } @@ -228,6 +303,14 @@ inline bool shm_named_condition::timed_wait inline bool shm_named_condition::remove(const char *name) { return shared_memory_object::remove(name); } +#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline bool shm_named_condition::remove(const wchar_t *name) +{ return shared_memory_object::remove(name); } + +#endif + + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED } //namespace ipcdetail diff --git a/include/boost/interprocess/sync/shm/named_condition_any.hpp b/include/boost/interprocess/sync/shm/named_condition_any.hpp index 38da427..905d8a1 100644 --- a/include/boost/interprocess/sync/shm/named_condition_any.hpp +++ b/include/boost/interprocess/sync/shm/named_condition_any.hpp @@ -61,7 +61,8 @@ class shm_named_condition_any public: //!Creates a global condition with a name. //!If the condition can't be created throws interprocess_exception - shm_named_condition_any(create_only_t create_only, const char *name, const permissions &perm = permissions()) + template + shm_named_condition_any(create_only_t create_only, const CharT *name, const permissions &perm = permissions()) : m_shmem (create_only ,name ,sizeof(internal_condition) + @@ -78,7 +79,8 @@ class shm_named_condition_any //!If the condition is already created, this call is equivalent //!shm_named_condition_any(open_only_t, ... ) //!Does not throw - shm_named_condition_any(open_or_create_t open_or_create, const char *name, const permissions &perm = permissions()) + template + shm_named_condition_any(open_or_create_t open_or_create, const CharT *name, const permissions &perm = permissions()) : m_shmem (open_or_create ,name ,sizeof(internal_condition) + @@ -92,7 +94,8 @@ class shm_named_condition_any //!Opens a global condition with a name if that condition is previously //!created. If it is not previously created this function throws //!interprocess_exception. - shm_named_condition_any(open_only_t open_only, const char *name) + template + shm_named_condition_any(open_only_t open_only, const CharT *name) : m_shmem (open_only ,name ,read_write @@ -150,7 +153,8 @@ class shm_named_condition_any //!Erases a named condition from the system. //!Returns false on error. Never throws. - static bool remove(const char *name) + template + static bool remove(const CharT *name) { return shared_memory_object::remove(name); } #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) diff --git a/include/boost/interprocess/sync/shm/named_mutex.hpp b/include/boost/interprocess/sync/shm/named_mutex.hpp index 8467274..0e60641 100644 --- a/include/boost/interprocess/sync/shm/named_mutex.hpp +++ b/include/boost/interprocess/sync/shm/named_mutex.hpp @@ -73,6 +73,27 @@ class shm_named_mutex //!interprocess_exception. shm_named_mutex(open_only_t open_only, const char *name); + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Creates a global interprocess_mutex with a name. + //!Throws interprocess_exception on error. + shm_named_mutex(create_only_t create_only, const wchar_t *name, const permissions &perm = permissions()); + + //!Opens or creates a global mutex with a name. + //!If the mutex is created, this call is equivalent to + //!shm_named_mutex(create_only_t, ... ) + //!If the mutex is already created, this call is equivalent + //!shm_named_mutex(open_only_t, ... ) + //!Does not throw + shm_named_mutex(open_or_create_t open_or_create, const wchar_t *name, const permissions &perm = permissions()); + + //!Opens a global mutex with a name if that mutex is previously + //!created. If it is not previously created this function throws + //!interprocess_exception. + shm_named_mutex(open_only_t open_only, const wchar_t *name); + + #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + //!Destroys *this and indicates that the calling process is finished using //!the resource. The destructor function will deallocate //!any system resources allocated by the system for use by this process for @@ -103,6 +124,14 @@ class shm_named_mutex //!Returns false on error. Never throws. static bool remove(const char *name); + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Erases a named mutex from the system. + //!Returns false on error. Never throws. + static bool remove(const wchar_t *name); + + #endif + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) typedef interprocess_mutex internal_mutex_type; interprocess_mutex &internal_mutex() @@ -155,6 +184,40 @@ inline shm_named_mutex::shm_named_mutex(open_only_t, const char *name) ,construct_func_t(ipcdetail::DoOpen)) {} +#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline shm_named_mutex::shm_named_mutex(create_only_t, const wchar_t *name, const permissions &perm) + : m_shmem (create_only + ,name + ,sizeof(interprocess_mutex) + + open_create_impl_t::ManagedOpenOrCreateUserOffset + ,read_write + ,0 + ,construct_func_t(ipcdetail::DoCreate) + ,perm) +{} + +inline shm_named_mutex::shm_named_mutex(open_or_create_t, const wchar_t *name, const permissions &perm) + : m_shmem (open_or_create + ,name + ,sizeof(interprocess_mutex) + + open_create_impl_t::ManagedOpenOrCreateUserOffset + ,read_write + ,0 + ,construct_func_t(ipcdetail::DoOpenOrCreate) + ,perm) +{} + +inline shm_named_mutex::shm_named_mutex(open_only_t, const wchar_t *name) + : m_shmem (open_only + ,name + ,read_write + ,0 + ,construct_func_t(ipcdetail::DoOpen)) +{} + +#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + inline void shm_named_mutex::lock() { this->internal_mutex().lock(); } @@ -170,6 +233,13 @@ inline bool shm_named_mutex::timed_lock(const boost::posix_time::ptime &abs_time inline bool shm_named_mutex::remove(const char *name) { return shared_memory_object::remove(name); } +#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline bool shm_named_mutex::remove(const wchar_t *name) +{ return shared_memory_object::remove(name); } + +#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED } //namespace ipcdetail { diff --git a/include/boost/interprocess/sync/shm/named_recursive_mutex.hpp b/include/boost/interprocess/sync/shm/named_recursive_mutex.hpp index 345eeda..5f2d951 100644 --- a/include/boost/interprocess/sync/shm/named_recursive_mutex.hpp +++ b/include/boost/interprocess/sync/shm/named_recursive_mutex.hpp @@ -68,6 +68,27 @@ class shm_named_recursive_mutex //!interprocess_exception. shm_named_recursive_mutex(open_only_t open_only, const char *name); + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Creates a global recursive_mutex with a name. + //!If the recursive_mutex can't be created throws interprocess_exception + shm_named_recursive_mutex(create_only_t create_only, const wchar_t *name, const permissions &perm = permissions()); + + //!Opens or creates a global recursive_mutex with a name. + //!If the recursive_mutex is created, this call is equivalent to + //!shm_named_recursive_mutex(create_only_t, ... ) + //!If the recursive_mutex is already created, this call is equivalent + //!shm_named_recursive_mutex(open_only_t, ... ) + //!Does not throw + shm_named_recursive_mutex(open_or_create_t open_or_create, const wchar_t *name, const permissions &perm = permissions()); + + //!Opens a global recursive_mutex with a name if that recursive_mutex is previously + //!created. If it is not previously created this function throws + //!interprocess_exception. + shm_named_recursive_mutex(open_only_t open_only, const wchar_t *name); + + #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + //!Destroys *this and indicates that the calling process is finished using //!the resource. The destructor function will deallocate //!any system resources allocated by the system for use by this process for @@ -98,6 +119,14 @@ class shm_named_recursive_mutex //!from the system static bool remove(const char *name); + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + //!Erases a named recursive mutex + //!from the system + static bool remove(const wchar_t *name); + + #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: friend class interprocess_tester; @@ -147,6 +176,40 @@ inline shm_named_recursive_mutex::shm_named_recursive_mutex(open_only_t, const c ,construct_func_t(DoOpen)) {} +#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline shm_named_recursive_mutex::shm_named_recursive_mutex(create_only_t, const wchar_t *name, const permissions &perm) + : m_shmem (create_only + ,name + ,sizeof(interprocess_recursive_mutex) + + open_create_impl_t::ManagedOpenOrCreateUserOffset + ,read_write + ,0 + ,construct_func_t(DoCreate) + ,perm) +{} + +inline shm_named_recursive_mutex::shm_named_recursive_mutex(open_or_create_t, const wchar_t *name, const permissions &perm) + : m_shmem (open_or_create + ,name + ,sizeof(interprocess_recursive_mutex) + + open_create_impl_t::ManagedOpenOrCreateUserOffset + ,read_write + ,0 + ,construct_func_t(DoOpenOrCreate) + ,perm) +{} + +inline shm_named_recursive_mutex::shm_named_recursive_mutex(open_only_t, const wchar_t *name) + : m_shmem (open_only + ,name + ,read_write + ,0 + ,construct_func_t(DoOpen)) +{} + +#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + inline void shm_named_recursive_mutex::lock() { this->mutex()->lock(); } @@ -162,6 +225,13 @@ inline bool shm_named_recursive_mutex::timed_lock(const boost::posix_time::ptime inline bool shm_named_recursive_mutex::remove(const char *name) { return shared_memory_object::remove(name); } +#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline bool shm_named_recursive_mutex::remove(const wchar_t *name) +{ return shared_memory_object::remove(name); } + +#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + } //namespace ipcdetail { } //namespace interprocess { } //namespace boost { diff --git a/include/boost/interprocess/sync/shm/named_semaphore.hpp b/include/boost/interprocess/sync/shm/named_semaphore.hpp index 4ac93e0..0a0204b 100644 --- a/include/boost/interprocess/sync/shm/named_semaphore.hpp +++ b/include/boost/interprocess/sync/shm/named_semaphore.hpp @@ -52,6 +52,16 @@ class shm_named_semaphore shm_named_semaphore(open_only_t, const char *name); + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + shm_named_semaphore(create_only_t, const wchar_t *name, unsigned int initialCount, const permissions &perm = permissions()); + + shm_named_semaphore(open_or_create_t, const wchar_t *name, unsigned int initialCount, const permissions &perm = permissions()); + + shm_named_semaphore(open_only_t, const wchar_t *name); + + #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + ~shm_named_semaphore(); void post(); @@ -61,6 +71,12 @@ class shm_named_semaphore static bool remove(const char *name); + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + static bool remove(const wchar_t *name); + + #endif + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: friend class interprocess_tester; @@ -114,6 +130,43 @@ inline shm_named_semaphore::shm_named_semaphore ,construct_func_t(DoOpen, 0)) {} +#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline shm_named_semaphore::shm_named_semaphore + (create_only_t, const wchar_t *name, unsigned int initialCount, const permissions &perm) + : m_shmem (create_only + ,name + ,sizeof(interprocess_semaphore) + + open_create_impl_t::ManagedOpenOrCreateUserOffset + ,read_write + ,0 + ,construct_func_t(DoCreate, initialCount) + ,perm) +{} + +inline shm_named_semaphore::shm_named_semaphore + (open_or_create_t, const wchar_t *name, unsigned int initialCount, const permissions &perm) + : m_shmem (open_or_create + ,name + ,sizeof(interprocess_semaphore) + + open_create_impl_t::ManagedOpenOrCreateUserOffset + ,read_write + ,0 + ,construct_func_t(DoOpenOrCreate, initialCount) + ,perm) +{} + +inline shm_named_semaphore::shm_named_semaphore + (open_only_t, const wchar_t *name) + : m_shmem (open_only + ,name + ,read_write + ,0 + ,construct_func_t(DoOpen, 0)) +{} + +#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + inline void shm_named_semaphore::post() { semaphore()->post(); } @@ -129,6 +182,13 @@ inline bool shm_named_semaphore::timed_wait(const boost::posix_time::ptime &abs_ inline bool shm_named_semaphore::remove(const char *name) { return shared_memory_object::remove(name); } +#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + +inline bool shm_named_semaphore::remove(const wchar_t *name) +{ return shared_memory_object::remove(name); } + +#endif + } //namespace ipcdetail { } //namespace interprocess { } //namespace boost { diff --git a/include/boost/interprocess/sync/windows/named_condition_any.hpp b/include/boost/interprocess/sync/windows/named_condition_any.hpp index 5dac8b7..d4c729b 100644 --- a/include/boost/interprocess/sync/windows/named_condition_any.hpp +++ b/include/boost/interprocess/sync/windows/named_condition_any.hpp @@ -67,6 +67,33 @@ class windows_named_condition_any m_named_sync.open_or_create(DoOpen, name, permissions(), callbacks); } + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + + windows_named_condition_any + (create_only_t, const wchar_t *name, const permissions &perm) + : m_condition_data() + { + named_cond_callbacks callbacks(m_condition_data.get_members()); + m_named_sync.open_or_create(DoCreate, name, perm, callbacks); + } + + windows_named_condition_any + (open_or_create_t, const wchar_t *name, const permissions &perm) + : m_condition_data() + { + named_cond_callbacks callbacks(m_condition_data.get_members()); + m_named_sync.open_or_create(DoOpenOrCreate, name, perm, callbacks); + } + + windows_named_condition_any(open_only_t, const wchar_t *name) + : m_condition_data() + { + named_cond_callbacks callbacks(m_condition_data.get_members()); + m_named_sync.open_or_create(DoOpen, name, permissions(), callbacks); + } + + #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) || defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) + ~windows_named_condition_any() { named_cond_callbacks callbacks(m_condition_data.get_members()); diff --git a/include/boost/interprocess/sync/windows/named_mutex.hpp b/include/boost/interprocess/sync/windows/named_mutex.hpp index 64a83c9..9885d75 100644 --- a/include/boost/interprocess/sync/windows/named_mutex.hpp +++ b/include/boost/interprocess/sync/windows/named_mutex.hpp @@ -54,6 +54,12 @@ class windows_named_mutex windows_named_mutex(open_only_t, const char *name); + windows_named_mutex(create_only_t, const wchar_t *name, const permissions &perm = permissions()); + + windows_named_mutex(open_or_create_t, const wchar_t *name, const permissions &perm = permissions()); + + windows_named_mutex(open_only_t, const wchar_t *name); + ~windows_named_mutex(); void unlock(); @@ -63,6 +69,8 @@ class windows_named_mutex static bool remove(const char *name); + static bool remove(const wchar_t *name); + #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) private: friend class interprocess_tester; @@ -145,6 +153,29 @@ inline windows_named_mutex::windows_named_mutex(open_only_t, const char *name) m_named_sync.open_or_create(DoOpen, name, permissions(), callbacks); } +inline windows_named_mutex::windows_named_mutex + (create_only_t, const wchar_t *name, const permissions &perm) + : m_mtx_wrapper() +{ + named_mut_callbacks callbacks(m_mtx_wrapper); + m_named_sync.open_or_create(DoCreate, name, perm, callbacks); +} + +inline windows_named_mutex::windows_named_mutex + (open_or_create_t, const wchar_t *name, const permissions &perm) + : m_mtx_wrapper() +{ + named_mut_callbacks callbacks(m_mtx_wrapper); + m_named_sync.open_or_create(DoOpenOrCreate, name, perm, callbacks); +} + +inline windows_named_mutex::windows_named_mutex(open_only_t, const wchar_t *name) + : m_mtx_wrapper() +{ + named_mut_callbacks callbacks(m_mtx_wrapper); + m_named_sync.open_or_create(DoOpen, name, permissions(), callbacks); +} + inline void windows_named_mutex::unlock() { m_mtx_wrapper.unlock(); @@ -170,6 +201,11 @@ inline bool windows_named_mutex::remove(const char *name) return windows_named_sync::remove(name); } +inline bool windows_named_mutex::remove(const wchar_t *name) +{ + return windows_named_sync::remove(name); +} + } //namespace ipcdetail { } //namespace interprocess { } //namespace boost { diff --git a/include/boost/interprocess/sync/windows/named_recursive_mutex.hpp b/include/boost/interprocess/sync/windows/named_recursive_mutex.hpp index 2e59137..75c09ee 100644 --- a/include/boost/interprocess/sync/windows/named_recursive_mutex.hpp +++ b/include/boost/interprocess/sync/windows/named_recursive_mutex.hpp @@ -51,6 +51,18 @@ class windows_named_recursive_mutex windows_named_recursive_mutex(open_only_t, const char *name) : windows_named_mutex(open_only_t(), name) {} + + windows_named_recursive_mutex(create_only_t, const wchar_t *name, const permissions &perm = permissions()) + : windows_named_mutex(create_only_t(), name, perm) + {} + + windows_named_recursive_mutex(open_or_create_t, const wchar_t *name, const permissions &perm = permissions()) + : windows_named_mutex(open_or_create_t(), name, perm) + {} + + windows_named_recursive_mutex(open_only_t, const wchar_t *name) + : windows_named_mutex(open_only_t(), name) + {} }; } //namespace ipcdetail { diff --git a/include/boost/interprocess/sync/windows/named_semaphore.hpp b/include/boost/interprocess/sync/windows/named_semaphore.hpp index e777a66..36396de 100644 --- a/include/boost/interprocess/sync/windows/named_semaphore.hpp +++ b/include/boost/interprocess/sync/windows/named_semaphore.hpp @@ -51,6 +51,12 @@ class windows_named_semaphore windows_named_semaphore(open_only_t, const char *name); + windows_named_semaphore(create_only_t, const wchar_t *name, unsigned int initialCount, const permissions &perm = permissions()); + + windows_named_semaphore(open_or_create_t, const wchar_t *name, unsigned int initialCount, const permissions &perm = permissions()); + + windows_named_semaphore(open_only_t, const wchar_t *name); + ~windows_named_semaphore(); void post(); @@ -148,6 +154,29 @@ inline windows_named_semaphore::windows_named_semaphore(open_only_t, const char m_named_sync.open_or_create(DoOpen, name, permissions(), callbacks); } +inline windows_named_semaphore::windows_named_semaphore + (create_only_t, const wchar_t *name, unsigned int initial_count, const permissions &perm) + : m_sem_wrapper() +{ + named_sem_callbacks callbacks(m_sem_wrapper, initial_count); + m_named_sync.open_or_create(DoCreate, name, perm, callbacks); +} + +inline windows_named_semaphore::windows_named_semaphore + (open_or_create_t, const wchar_t *name, unsigned int initial_count, const permissions &perm) + : m_sem_wrapper() +{ + named_sem_callbacks callbacks(m_sem_wrapper, initial_count); + m_named_sync.open_or_create(DoOpenOrCreate, name, perm, callbacks); +} + +inline windows_named_semaphore::windows_named_semaphore(open_only_t, const wchar_t *name) + : m_sem_wrapper() +{ + named_sem_callbacks callbacks(m_sem_wrapper, 0); + m_named_sync.open_or_create(DoOpen, name, permissions(), callbacks); +} + inline void windows_named_semaphore::post() { m_sem_wrapper.post(); diff --git a/include/boost/interprocess/sync/windows/named_sync.hpp b/include/boost/interprocess/sync/windows/named_sync.hpp index 1425b4d..8b774f8 100644 --- a/include/boost/interprocess/sync/windows/named_sync.hpp +++ b/include/boost/interprocess/sync/windows/named_sync.hpp @@ -60,7 +60,8 @@ class windows_named_sync public: windows_named_sync(); - void open_or_create(create_enum_t creation_type, const char *name, const permissions &perm, windows_named_sync_interface &sync_interface); + template + void open_or_create(create_enum_t creation_type, const CharT *name, const permissions &perm, windows_named_sync_interface &sync_interface); void close(windows_named_sync_interface &sync_interface); static bool remove(const char *name); @@ -99,13 +100,14 @@ inline void windows_named_sync::close(windows_named_sync_interface &sync_interfa } } +template inline void windows_named_sync::open_or_create ( create_enum_t creation_type - , const char *name + , const CharT *name , const permissions &perm , windows_named_sync_interface &sync_interface) { - std::string aux_str(name); + std::basic_string aux_str(name); m_file_hnd = winapi::invalid_handle_value; //Use a file to emulate POSIX lifetime semantics. After this logic //we'll obtain the ID of the native handle to open in aux_str @@ -162,7 +164,7 @@ inline void windows_named_sync::open_or_create } if(success){ //Now create a global semaphore name based on the unique id - char unique_id_name[sizeof(unique_id_val)*2+1]; + CharT unique_id_name[sizeof(unique_id_val)*2+1]; std::size_t name_suffix_length = sizeof(unique_id_name); bytes_to_str(&unique_id_val, sizeof(unique_id_val), &unique_id_name[0], name_suffix_length); success = sync_interface.open(creation_type, unique_id_name); diff --git a/include/boost/interprocess/windows_shared_memory.hpp b/include/boost/interprocess/windows_shared_memory.hpp index 341674a..cc98947 100644 --- a/include/boost/interprocess/windows_shared_memory.hpp +++ b/include/boost/interprocess/windows_shared_memory.hpp @@ -24,6 +24,7 @@ #include #include +#include #if !defined(BOOST_INTERPROCESS_WINDOWS) #error "This header can only be used in Windows operating systems" @@ -38,7 +39,7 @@ #include #include #include -#include + //!\file //!Describes a class representing a native windows shared memory. @@ -86,6 +87,23 @@ class windows_shared_memory windows_shared_memory(open_only_t, const char *name, mode_t mode) { this->priv_open_or_create(ipcdetail::DoOpen, name, mode, 0, permissions()); } + //!Creates a new native shared memory with name "name" and at least size "size", + //!with the access mode "mode". + //!If the file previously exists, throws an error. + windows_shared_memory(create_only_t, const wchar_t *name, mode_t mode, std::size_t size, const permissions& perm = permissions()) + { this->priv_open_or_create(ipcdetail::DoCreate, name, mode, size, perm); } + + //!Tries to create a shared memory object with name "name" and at least size "size", with the + //!access mode "mode". If the file previously exists, it tries to open it with mode "mode". + //!Otherwise throws an error. + windows_shared_memory(open_or_create_t, const wchar_t *name, mode_t mode, std::size_t size, const permissions& perm = permissions()) + { this->priv_open_or_create(ipcdetail::DoOpenOrCreate, name, mode, size, perm); } + + //!Tries to open a shared memory object with name "name", with the access mode "mode". + //!If the file does not previously exist, it throws an error. + windows_shared_memory(open_only_t, const wchar_t *name, mode_t mode) + { this->priv_open_or_create(ipcdetail::DoOpen, name, mode, 0, permissions()); } + //!Moves the ownership of "moved"'s shared memory object to *this. //!After the call, "moved" does not represent any shared memory object. //!Does not throw @@ -132,11 +150,12 @@ class windows_shared_memory void priv_close(); //!Closes a previously opened file mapping. Never throws. - bool priv_open_or_create(ipcdetail::create_enum_t type, const char *filename, mode_t mode, std::size_t size, const permissions& perm = permissions()); + template + bool priv_open_or_create(ipcdetail::create_enum_t type, const CharT *filename, mode_t mode, std::size_t size, const permissions& perm = permissions()); void * m_handle; mode_t m_mode; - std::string m_name; + char_wchar_holder m_name; #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED }; @@ -150,7 +169,7 @@ inline windows_shared_memory::~windows_shared_memory() { this->priv_close(); } inline const char *windows_shared_memory::get_name() const -{ return m_name.c_str(); } +{ return m_name.getn(); } inline void windows_shared_memory::swap(windows_shared_memory &other) { @@ -171,11 +190,10 @@ inline offset_t windows_shared_memory::get_size() const return (m_handle && winapi::get_file_mapping_size(m_handle, size)) ? size : 0; } +template inline bool windows_shared_memory::priv_open_or_create - (ipcdetail::create_enum_t type, const char *filename, mode_t mode, std::size_t size, const permissions& perm) + (ipcdetail::create_enum_t type, const CharT *filename, mode_t mode, std::size_t size, const permissions& perm) { - m_name = filename ? filename : ""; - unsigned long protection = 0; unsigned long map_access = 0; diff --git a/test/file_lock_test.cpp b/test/file_lock_test.cpp index 9bce20a..4e70adb 100644 --- a/test/file_lock_test.cpp +++ b/test/file_lock_test.cpp @@ -19,14 +19,6 @@ using namespace boost::interprocess; -inline std::string get_filename() -{ - std::string ret (ipcdetail::get_temporary_path()); - ret += "/"; - ret += test::get_process_id_name(); - return ret; -} - //This wrapper is necessary to have a default constructor //in generic mutex_test_template functions class file_lock_lock_test_wrapper @@ -47,16 +39,21 @@ int main () if(!file){ return 1; } - file_lock flock(get_filename().c_str()); { - scoped_lock sl(flock); - } - { - scoped_lock sl(flock, try_to_lock); - } - { - scoped_lock sl(flock, test::delay(1)); + file_lock flock(get_filename().c_str()); + { + scoped_lock sl(flock); + } + { + scoped_lock sl(flock, try_to_lock); + } + { + scoped_lock sl(flock, test::delay(1)); + } } + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) + file_lock flock(get_wfilename().c_str()); + #endif } { //Now test move semantics diff --git a/test/file_mapping_test.cpp b/test/file_mapping_test.cpp index 2b39195..73a8266 100644 --- a/test/file_mapping_test.cpp +++ b/test/file_mapping_test.cpp @@ -20,14 +20,6 @@ using namespace boost::interprocess; -inline std::string get_filename() -{ - std::string ret (ipcdetail::get_temporary_path()); - ret += "/"; - ret += test::get_process_id_name(); - return ret; -} - file_mapping get_file_mapping() { file_mapping f; @@ -141,6 +133,27 @@ int main () } } } + #ifdef BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES + { + //Create a file mapping + file_mapping mapping(get_wfilename().c_str(), read_only); + + //Create a single regions, mapping all the file + mapped_region region (mapping + ,read_only + ); + + //Check pattern + unsigned char *pattern = static_cast(region.get_address()); + for(std::size_t i = 0 + ;i < FileSize + ;++i, ++pattern){ + if(*pattern != static_cast(i)){ + return 1; + } + } + } + #endif //BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES { //Now test move semantics file_mapping mapping(get_filename().c_str(), read_only); diff --git a/test/get_process_id_name.hpp b/test/get_process_id_name.hpp index f79384a..b964f1c 100644 --- a/test/get_process_id_name.hpp +++ b/test/get_process_id_name.hpp @@ -15,6 +15,7 @@ #include //std::string #include //std::stringstream #include +#include namespace boost{ namespace interprocess{ @@ -65,6 +66,53 @@ inline const char *add_to_process_id_ptr_name(const char *name, void *ptr) } } //namespace test{ + +inline std::string get_filename() +{ + std::string ret (ipcdetail::get_temporary_path()); + ret += "/"; + ret += test::get_process_id_name(); + return ret; +} + +#ifdef BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES + +namespace test { + +inline void get_process_id_wname(std::wstring &str) +{ + std::wstringstream sstr; + sstr << L"process_" << boost::interprocess::ipcdetail::get_current_process_id() << std::ends; + str = sstr.str().c_str(); +} + +inline const wchar_t *get_process_id_wname() +{ + static std::wstring str; + get_process_id_wname(str); + return str.c_str(); +} + +inline const wchar_t *add_to_process_id_name(const wchar_t *name) +{ + static std::wstring str; + get_process_id_wname(str); + str += name; + return str.c_str(); +} + +} //namespace test { + +inline std::wstring get_wfilename() +{ + std::wstring ret (ipcdetail::get_temporary_wpath()); + ret += L"/"; + ret += test::get_process_id_wname(); + return ret; +} + +#endif + } //namespace interprocess{ } //namespace boost{ diff --git a/test/managed_mapped_file_test.cpp b/test/managed_mapped_file_test.cpp index cfc9d26..a853412 100644 --- a/test/managed_mapped_file_test.cpp +++ b/test/managed_mapped_file_test.cpp @@ -21,19 +21,43 @@ using namespace boost::interprocess; -inline std::string get_filename() -{ - std::string ret (ipcdetail::get_temporary_path()); - ret += "/"; - ret += test::get_process_id_name(); - return ret; -} +template +struct filename_traits; -int main () +template <> +struct filename_traits +{ + + static const char* get() + { return filename.c_str(); } + + static std::string filename; +}; + +std::string filename_traits::filename = get_filename(); + + +#ifdef BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES + +template <> +struct filename_traits +{ + + static const wchar_t* get() + { return filename.c_str(); } + + static std::wstring filename; +}; + +std::wstring filename_traits::filename = get_wfilename(); + +#endif //#ifdef BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES + +template +int test_managed_mapped_file() { const int FileSize = 65536*10; - std::string filename(get_filename()); - const char *FileName = filename.c_str(); + const CharT *FileName = filename_traits::get(); //STL compatible allocator object for memory-mapped file typedef allocator @@ -226,6 +250,19 @@ int main () return 0; } +int main () +{ + int r; + r = test_managed_mapped_file(); + if(r) return r; + #ifdef BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES + r = test_managed_mapped_file(); + if(r) return r; + #endif + return 0; +} + + #else //#if defined(BOOST_INTERPROCESS_MAPPED_FILES) int main() diff --git a/test/managed_shared_memory_test.cpp b/test/managed_shared_memory_test.cpp index b136413..3fc8a78 100644 --- a/test/managed_shared_memory_test.cpp +++ b/test/managed_shared_memory_test.cpp @@ -17,10 +17,39 @@ using namespace boost::interprocess; -int main () +template +struct filename_traits; + +template <> +struct filename_traits +{ + + static const char* get() + { return test::get_process_id_name(); } + + static std::string filename; +}; + +#ifdef BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES + +template <> +struct filename_traits +{ + + static const wchar_t* get() + { return test::get_process_id_wname(); } + + static std::wstring filename; +}; + +#endif //#ifdef BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES + + +template +int test_managed_shared_memory() { const int ShmemSize = 65536; - const char *const ShmemName = test::get_process_id_name(); + const CharT *const ShmemName = filename_traits::get(); //STL compatible allocator object for memory-mapped shmem typedef allocator @@ -211,3 +240,15 @@ int main () shared_memory_object::remove(ShmemName); return 0; } + +int main () +{ + int r; + r = test_managed_shared_memory(); + if(r) return r; + #ifdef BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES + r = test_managed_shared_memory(); + if(r) return r; + #endif + return 0; +} diff --git a/test/managed_xsi_shared_memory_test.cpp b/test/managed_xsi_shared_memory_test.cpp index f8e7ec0..214ae67 100644 --- a/test/managed_xsi_shared_memory_test.cpp +++ b/test/managed_xsi_shared_memory_test.cpp @@ -48,14 +48,6 @@ class xsi_shared_memory_remover xsi_shared_memory & xsi_shm_; }; -inline std::string get_filename() -{ - std::string ret (ipcdetail::get_temporary_path()); - ret += "/"; - ret += test::get_process_id_name(); - return ret; -} - int main () { const int ShmemSize = 65536; diff --git a/test/mapped_file_test.cpp b/test/mapped_file_test.cpp index 0d70dfb..8260c7c 100644 --- a/test/mapped_file_test.cpp +++ b/test/mapped_file_test.cpp @@ -26,13 +26,6 @@ using namespace boost::interprocess; static const std::size_t FileSize = 1000; -inline std::string get_filename() -{ - std::string ret (ipcdetail::get_temporary_path()); - ret += "/"; - ret += test::get_process_id_name(); - return ret; -} struct file_destroyer { @@ -43,15 +36,15 @@ struct file_destroyer } }; +typedef boost::interprocess::ipcdetail::managed_open_or_create_impl + mapped_file; + //This wrapper is necessary to have a common constructor //in generic named_creation_template functions class mapped_file_creation_test_wrapper : public file_destroyer - , public boost::interprocess::ipcdetail::managed_open_or_create_impl - + , public mapped_file { - typedef boost::interprocess::ipcdetail::managed_open_or_create_impl - mapped_file; public: mapped_file_creation_test_wrapper(boost::interprocess::create_only_t) : mapped_file(boost::interprocess::create_only, get_filename().c_str(), FileSize, read_write, 0, permissions()) @@ -66,12 +59,35 @@ class mapped_file_creation_test_wrapper {} }; +#ifdef BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES + +class mapped_file_creation_test_wrapper_w + : public file_destroyer + , public mapped_file +{ + public: + mapped_file_creation_test_wrapper_w(boost::interprocess::create_only_t) + : mapped_file(boost::interprocess::create_only, get_wfilename().c_str(), FileSize, read_write, 0, permissions()) + {} + + mapped_file_creation_test_wrapper_w(boost::interprocess::open_only_t) + : mapped_file(boost::interprocess::open_only, get_wfilename().c_str(), read_write, 0) + {} + + mapped_file_creation_test_wrapper_w(boost::interprocess::open_or_create_t) + : mapped_file(boost::interprocess::open_or_create, get_wfilename().c_str(), FileSize, read_write, 0, permissions()) + {} +}; + +#endif //BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES + int main () { - typedef boost::interprocess::ipcdetail::managed_open_or_create_impl - mapped_file; file_mapping::remove(get_filename().c_str()); test::test_named_creation(); + #ifdef BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES + test::test_named_creation(); + #endif //Create and get name, size and address { diff --git a/test/message_queue_test.cpp b/test/message_queue_test.cpp index bccf2bf..e9e4497 100644 --- a/test/message_queue_test.cpp +++ b/test/message_queue_test.cpp @@ -25,10 +25,11 @@ #include #include #include -#include +#include #include #include "get_process_id_name.hpp" +#include "named_creation_template.hpp" //////////////////////////////////////////////////////////////////////////////// // // @@ -350,25 +351,86 @@ bool test_multi_sender_receiver() return ret; } +class msg_queue_named_test_wrapper + : public test::named_sync_deleter, public message_queue +{ + public: + + msg_queue_named_test_wrapper(create_only_t) + : message_queue(create_only, test::get_process_id_name(), 10, 10) + {} + + msg_queue_named_test_wrapper(open_only_t) + : message_queue(open_only, test::get_process_id_name()) + {} + + msg_queue_named_test_wrapper(open_or_create_t) + : message_queue(open_or_create, test::get_process_id_name(), 10, 10) + {} + + ~msg_queue_named_test_wrapper() + {} +}; + +#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) + +class msg_queue_named_test_wrapper_w + : public test::named_sync_deleter_w, public message_queue +{ + public: + + template + msg_queue_named_test_wrapper_w(create_only_t) + : message_queue(create_only, test::get_process_id_wname(), 10, 10) + {} + + msg_queue_named_test_wrapper_w(open_only_t) + : message_queue(open_only, test::get_process_id_wname()) + {} + + msg_queue_named_test_wrapper_w(open_or_create_t) + : message_queue(open_or_create, test::get_process_id_wname(), 10, 10) + {} + + ~msg_queue_named_test_wrapper_w() + {} +}; + +#endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) + int main () { - if(!test_priority_order()){ - return 1; - } + int ret = 0; + try{ + message_queue::remove(test::get_process_id_name()); + test::test_named_creation(); + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) + test::test_named_creation(); + #endif - if(!test_serialize_db()){ - return 1; - } + if(!test_priority_order()){ + return 1; + } - if(!test_buffer_overflow()){ - return 1; - } + if(!test_serialize_db()){ + return 1; + } - if(!test_multi_sender_receiver()){ - return 1; - } + if(!test_buffer_overflow()){ + return 1; + } - return 0; + if(!test_multi_sender_receiver()){ + return 1; + } + } + catch (std::exception &ex) { + std::cout << ex.what() << std::endl; + ret = 1; + } + + message_queue::remove(test::get_process_id_name()); + return ret; } diff --git a/test/named_condition_any_test.cpp b/test/named_condition_any_test.cpp index 9033c4a..2a8f936 100644 --- a/test/named_condition_any_test.cpp +++ b/test/named_condition_any_test.cpp @@ -32,6 +32,23 @@ struct condition_deleter } }; +#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) + +struct condition_deleter_w +{ + std::wstring name; + + ~condition_deleter_w() + { + if(name.empty()) + named_condition_any::remove(test::add_to_process_id_name(L"named_condition_any")); + else + named_condition_any::remove(name.c_str()); + } +}; + +#endif //#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) + inline std::string num_to_string(int n) { std::stringstream s; s << n; return s.str(); } @@ -117,6 +134,40 @@ class named_condition_any_creation_test_wrapper int named_condition_any_creation_test_wrapper::count_ = 0; +#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) + +//This wrapper is necessary to have a common constructor +//in generic named_creation_template functions +class named_condition_any_creation_test_wrapper_w + : public condition_deleter_w, public named_condition_any +{ + public: + named_condition_any_creation_test_wrapper_w(create_only_t) + : named_condition_any(create_only, test::add_to_process_id_name(L"named_condition_any")) + { ++count_; } + + named_condition_any_creation_test_wrapper_w(open_only_t) + : named_condition_any(open_only, test::add_to_process_id_name(L"named_condition_any")) + { ++count_; } + + named_condition_any_creation_test_wrapper_w(open_or_create_t) + : named_condition_any(open_or_create, test::add_to_process_id_name(L"named_condition_any")) + { ++count_; } + + ~named_condition_any_creation_test_wrapper_w() { + if(--count_){ + ipcdetail::interprocess_tester:: + dont_close_on_destruction(static_cast(*this)); + } + } + static int count_; +}; + +int named_condition_any_creation_test_wrapper_w::count_ = 0; + +#endif //#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) + + struct mutex_deleter { std::string name; @@ -169,6 +220,9 @@ int main () named_mutex::remove(test::add_to_process_id_name("named_mutex")); test::test_named_creation(); + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) + test::test_named_creation(); + #endif test::do_test_condition(); } diff --git a/test/named_condition_test.cpp b/test/named_condition_test.cpp index 74e2da9..11ce052 100644 --- a/test/named_condition_test.cpp +++ b/test/named_condition_test.cpp @@ -32,6 +32,24 @@ struct condition_deleter } }; +#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) + +struct condition_deleter_w +{ + std::string name; + + ~condition_deleter_w() + { + if(name.empty()) + named_condition::remove(test::add_to_process_id_name(L"named_condition")); + else + named_condition::remove(name.c_str()); + } +}; + +#endif //#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) + + inline std::string num_to_string(int n) { std::stringstream s; s << n; return s.str(); } @@ -117,6 +135,39 @@ class named_condition_creation_test_wrapper int named_condition_creation_test_wrapper::count_ = 0; +#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) + +//This wrapper is necessary to have a common constructor +//in generic named_creation_template functions +class named_condition_creation_test_wrapper_w + : public condition_deleter_w, public named_condition +{ + public: + named_condition_creation_test_wrapper_w(create_only_t) + : named_condition(create_only, test::add_to_process_id_name(L"named_condition")) + { ++count_; } + + named_condition_creation_test_wrapper_w(open_only_t) + : named_condition(open_only, test::add_to_process_id_name(L"named_condition")) + { ++count_; } + + named_condition_creation_test_wrapper_w(open_or_create_t) + : named_condition(open_or_create, test::add_to_process_id_name(L"named_condition")) + { ++count_; } + + ~named_condition_creation_test_wrapper_w() { + if(--count_){ + ipcdetail::interprocess_tester:: + dont_close_on_destruction(static_cast(*this)); + } + } + static int count_; +}; + +int named_condition_creation_test_wrapper_w::count_ = 0; + +#endif //#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) + struct mutex_deleter { std::string name; @@ -169,6 +220,15 @@ int main () named_mutex::remove(test::add_to_process_id_name("named_mutex")); test::test_named_creation(); + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) + //Remove previous mutexes and conditions + named_mutex::remove(test::add_to_process_id_name("test_mutex0")); + named_condition::remove(test::add_to_process_id_name("test_cond0")); + named_condition::remove(test::add_to_process_id_name("test_cond1")); + named_condition::remove(test::add_to_process_id_name("named_condition")); + named_mutex::remove(test::add_to_process_id_name("named_mutex")); + test::test_named_creation(); + #endif test::do_test_condition(); } diff --git a/test/named_creation_template.hpp b/test/named_creation_template.hpp index 1e00299..5d699c8 100644 --- a/test/named_creation_template.hpp +++ b/test/named_creation_template.hpp @@ -100,6 +100,17 @@ struct named_sync_deleter { NamedSync::remove(test::get_process_id_name()); } }; +#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) + +template +struct named_sync_deleter_w +{ + ~named_sync_deleter_w() + { NamedSync::remove(test::get_process_id_wname()); } +}; + +#endif //#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) + //This wrapper is necessary to have a common constructor //in generic named_creation_template functions @@ -124,6 +135,32 @@ class named_sync_creation_test_wrapper {} }; +#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) + +//This wrapper is necessary to have a common constructor +//in generic named_creation_template functions +template +class named_sync_creation_test_wrapper_w + : public test::named_sync_deleter_w, public NamedSync +{ + public: + named_sync_creation_test_wrapper_w(create_only_t) + : NamedSync(create_only, test::get_process_id_wname()) + {} + + named_sync_creation_test_wrapper_w(open_only_t) + : NamedSync(open_only, test::get_process_id_wname()) + {} + + named_sync_creation_test_wrapper_w(open_or_create_t) + : NamedSync(open_or_create, test::get_process_id_wname()) + {} + + ~named_sync_creation_test_wrapper_w() + {} +}; + +#endif //#if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) }}} //namespace boost { namespace interprocess { namespace test { diff --git a/test/named_mutex_test.cpp b/test/named_mutex_test.cpp index 9b9fc19..cdaacec 100644 --- a/test/named_mutex_test.cpp +++ b/test/named_mutex_test.cpp @@ -12,24 +12,27 @@ #include #include "mutex_test_template.hpp" #include "named_creation_template.hpp" -#include #include +#include using namespace boost::interprocess; int main () { + int ret = 0; try{ named_mutex::remove(test::get_process_id_name()); test::test_named_creation< test::named_sync_creation_test_wrapper >(); + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) + test::test_named_creation< test::named_sync_creation_test_wrapper_w >(); + #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) test::test_all_lock< test::named_sync_wrapper >(); test::test_all_mutex >(); } catch(std::exception &ex){ - named_mutex::remove(test::get_process_id_name()); std::cout << ex.what() << std::endl; - return 1; + ret = 1; } named_mutex::remove(test::get_process_id_name()); - return 0; + return ret; } diff --git a/test/named_recursive_mutex_test.cpp b/test/named_recursive_mutex_test.cpp index fa53cd2..a93b492 100644 --- a/test/named_recursive_mutex_test.cpp +++ b/test/named_recursive_mutex_test.cpp @@ -13,26 +13,29 @@ #include #include "mutex_test_template.hpp" #include "named_creation_template.hpp" -#include #include "get_process_id_name.hpp" +#include using namespace boost::interprocess; int main () { + int ret = 0; try{ named_recursive_mutex::remove(test::get_process_id_name()); test::test_named_creation< test::named_sync_creation_test_wrapper >(); + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) + test::test_named_creation< test::named_sync_creation_test_wrapper_w >(); + #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) test::test_all_lock< test::named_sync_wrapper >(); test::test_all_mutex >(); test::test_all_recursive_lock >(); } catch(std::exception &ex){ - named_recursive_mutex::remove(test::get_process_id_name()); std::cout << ex.what() << std::endl; - return 1; + ret = 1; } named_recursive_mutex::remove(test::get_process_id_name()); - return 0; + return ret; } diff --git a/test/named_semaphore_test.cpp b/test/named_semaphore_test.cpp index dbad25e..4c99db3 100644 --- a/test/named_semaphore_test.cpp +++ b/test/named_semaphore_test.cpp @@ -14,13 +14,12 @@ #include #include "named_creation_template.hpp" #include "mutex_test_template.hpp" -#include #include "get_process_id_name.hpp" +#include using namespace boost::interprocess; static const std::size_t RecSemCount = 100; -static const char * SemName = test::get_process_id_name(); //This wrapper is necessary to plug this class //in lock tests @@ -29,15 +28,18 @@ class lock_test_wrapper { public: - lock_test_wrapper(create_only_t, const char *name, unsigned int count = 1) + template + lock_test_wrapper(create_only_t, const CharT *name, unsigned int count = 1) : named_semaphore(create_only, name, count) {} - lock_test_wrapper(open_only_t, const char *name) + template + lock_test_wrapper(open_only_t, const CharT *name) : named_semaphore(open_only, name) {} - lock_test_wrapper(open_or_create_t, const char *name, unsigned int count = 1) + template + lock_test_wrapper(open_or_create_t, const CharT *name, unsigned int count = 1) : named_semaphore(open_or_create, name, count) {} @@ -78,12 +80,13 @@ class recursive_test_wrapper bool test_named_semaphore_specific() { + named_semaphore::remove(test::get_process_id_name()); //Test persistance { - named_semaphore sem(create_only, SemName, 3); + named_semaphore sem(create_only, test::get_process_id_name(), 3); } { - named_semaphore sem(open_only, SemName); + named_semaphore sem(open_only, test::get_process_id_name()); BOOST_INTERPROCESS_CHECK(sem.try_wait() == true); BOOST_INTERPROCESS_CHECK(sem.try_wait() == true); BOOST_INTERPROCESS_CHECK(sem.try_wait() == true); @@ -91,31 +94,34 @@ bool test_named_semaphore_specific() sem.post(); } { - named_semaphore sem(open_only, SemName); + named_semaphore sem(open_only, test::get_process_id_name()); BOOST_INTERPROCESS_CHECK(sem.try_wait() == true); BOOST_INTERPROCESS_CHECK(sem.try_wait() == false); } - named_semaphore::remove(SemName); + named_semaphore::remove(test::get_process_id_name()); return true; } int main () { + int ret = 0; try{ - named_semaphore::remove(SemName); test::test_named_creation< test::named_sync_creation_test_wrapper >(); + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) + test::test_named_creation< test::named_sync_creation_test_wrapper_w >(); + #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) + test::test_all_lock< test::named_sync_wrapper >(); test::test_all_mutex >(); test::test_all_recursive_lock >(); test_named_semaphore_specific(); } catch(std::exception &ex){ - named_semaphore::remove(SemName); std::cout << ex.what() << std::endl; - return 1; + ret = 1; } - named_semaphore::remove(SemName); - return 0; + named_semaphore::remove(test::get_process_id_name()); + return ret; } diff --git a/test/named_sharable_mutex_test.cpp b/test/named_sharable_mutex_test.cpp index a1f0aaf..72d5878 100644 --- a/test/named_sharable_mutex_test.cpp +++ b/test/named_sharable_mutex_test.cpp @@ -17,84 +17,23 @@ using namespace boost::interprocess; -struct mutex_deleter -{ - ~mutex_deleter() - { named_sharable_mutex::remove(test::get_process_id_name()); } -}; - -//This wrapper is necessary to have a default constructor -//in generic mutex_test_template functions -class named_sharable_mutex_lock_test_wrapper - : public named_sharable_mutex -{ - public: - named_sharable_mutex_lock_test_wrapper() - : named_sharable_mutex(open_or_create, test::get_process_id_name()) - { ++count_; } - - ~named_sharable_mutex_lock_test_wrapper() - { - if(--count_){ - ipcdetail::interprocess_tester:: - dont_close_on_destruction(static_cast(*this)); - } - } - - static int count_; -}; - -int named_sharable_mutex_lock_test_wrapper::count_ = 0; - - -//This wrapper is necessary to have a common constructor -//in generic named_creation_template functions -class named_sharable_mutex_creation_test_wrapper - : public mutex_deleter, public named_sharable_mutex -{ - public: - named_sharable_mutex_creation_test_wrapper - (create_only_t) - : named_sharable_mutex(create_only, test::get_process_id_name()) - { ++count_; } - - named_sharable_mutex_creation_test_wrapper - (open_only_t) - : named_sharable_mutex(open_only, test::get_process_id_name()) - { ++count_; } - - named_sharable_mutex_creation_test_wrapper - (open_or_create_t) - : named_sharable_mutex(open_or_create, test::get_process_id_name()) - { ++count_; } - - ~named_sharable_mutex_creation_test_wrapper() - { - if(--count_){ - ipcdetail::interprocess_tester:: - dont_close_on_destruction(static_cast(*this)); - } - } - - static int count_; -}; - -int named_sharable_mutex_creation_test_wrapper::count_ = 0; - int main () { + int ret = 0; try{ named_sharable_mutex::remove(test::get_process_id_name()); test::test_named_creation< test::named_sync_creation_test_wrapper >(); + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) + test::test_named_creation< test::named_sync_creation_test_wrapper_w >(); + #endif //defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) test::test_all_lock< test::named_sync_wrapper >(); test::test_all_mutex >(); test::test_all_sharable_mutex >(); } catch(std::exception &ex){ - named_sharable_mutex::remove(test::get_process_id_name()); std::cout << ex.what() << std::endl; - return 1; + ret = 1; } named_sharable_mutex::remove(test::get_process_id_name()); - return 0; + return ret; } diff --git a/test/named_upgradable_mutex_test.cpp b/test/named_upgradable_mutex_test.cpp index e24d3f8..f7c40cd 100644 --- a/test/named_upgradable_mutex_test.cpp +++ b/test/named_upgradable_mutex_test.cpp @@ -17,84 +17,23 @@ using namespace boost::interprocess; -struct mutex_deleter -{ - ~mutex_deleter() - { named_upgradable_mutex::remove(test::get_process_id_name()); } -}; - -//This wrapper is necessary to have a default constructor -//in generic mutex_test_template functions -class named_upgradable_mutex_lock_test_wrapper - : public named_upgradable_mutex -{ - public: - named_upgradable_mutex_lock_test_wrapper() - : named_upgradable_mutex(open_or_create, test::get_process_id_name()) - { ++count_; } - - ~named_upgradable_mutex_lock_test_wrapper() - { - if(--count_){ - ipcdetail::interprocess_tester:: - dont_close_on_destruction(static_cast(*this)); - } - } - - static int count_; -}; - -int named_upgradable_mutex_lock_test_wrapper::count_ = 0; - - -//This wrapper is necessary to have a common constructor -//in generic named_creation_template functions -class named_upgradable_mutex_creation_test_wrapper - : public mutex_deleter, public named_upgradable_mutex -{ - public: - named_upgradable_mutex_creation_test_wrapper - (create_only_t) - : named_upgradable_mutex(create_only, test::get_process_id_name()) - { ++count_; } - - named_upgradable_mutex_creation_test_wrapper - (open_only_t) - : named_upgradable_mutex(open_only, test::get_process_id_name()) - { ++count_; } - - named_upgradable_mutex_creation_test_wrapper - (open_or_create_t) - : named_upgradable_mutex(open_or_create, test::get_process_id_name()) - { ++count_; } - - ~named_upgradable_mutex_creation_test_wrapper() - { - if(--count_){ - ipcdetail::interprocess_tester:: - dont_close_on_destruction(static_cast(*this)); - } - } - - static int count_; -}; - -int named_upgradable_mutex_creation_test_wrapper::count_ = 0; - int main () { + int ret = 0; try{ named_upgradable_mutex::remove(test::get_process_id_name()); test::test_named_creation< test::named_sync_creation_test_wrapper >(); + #if defined(BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES) + test::test_named_creation< test::named_sync_creation_test_wrapper_w >(); + #endif test::test_all_lock< test::named_sync_wrapper >(); test::test_all_mutex >(); test::test_all_sharable_mutex >(); } catch(std::exception &ex){ - named_upgradable_mutex::remove(test::get_process_id_name()); std::cout << ex.what() << std::endl; - return 1; + ret = 1; } named_upgradable_mutex::remove(test::get_process_id_name()); - return 0; + return ret; } diff --git a/test/shared_memory_mapping_test.cpp b/test/shared_memory_mapping_test.cpp index dcf7922..3be83ce 100644 --- a/test/shared_memory_mapping_test.cpp +++ b/test/shared_memory_mapping_test.cpp @@ -110,7 +110,26 @@ int main () } } } + #ifdef BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES + //Now check the pattern mapping a single read only mapped_region + { + //Create a file mapping + shared_memory_object mapping(open_only, test::get_process_id_wname(), read_only); + //Create a single regions, mapping all the file + mapped_region region (mapping, read_only); + + //Check pattern + unsigned char *pattern = static_cast(region.get_address()); + for(std::size_t i = 0 + ;i < FileSize + ;++i, ++pattern){ + if(*pattern != static_cast(i)){ + return 1; + } + } + } + #endif //BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES //Now check the pattern mapping a single read only mapped_region { //Create a file mapping diff --git a/test/shared_memory_test.cpp b/test/shared_memory_test.cpp index f01cfd1..2aafc4c 100644 --- a/test/shared_memory_test.cpp +++ b/test/shared_memory_test.cpp @@ -21,6 +21,9 @@ using namespace boost::interprocess; static const std::size_t ShmSize = 1000; static const char * ShmName = test::get_process_id_name(); +#ifdef BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES +static const wchar_t * ShmNameW = test::get_process_id_wname(); +#endif struct eraser { @@ -53,12 +56,37 @@ class shared_memory_creation_test_wrapper {} }; +#ifdef BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES + +class shared_memory_creation_test_wrapper_w + : public eraser + , public shared_memory +{ + + public: + shared_memory_creation_test_wrapper_w(create_only_t) + : shared_memory(create_only, ShmNameW, ShmSize, read_write, 0, permissions()) + {} + + shared_memory_creation_test_wrapper_w(open_only_t) + : shared_memory(open_only, ShmNameW, read_write, 0) + {} + + shared_memory_creation_test_wrapper_w(open_or_create_t) + : shared_memory(open_or_create, ShmNameW, ShmSize, read_write, 0, permissions()) + {} +}; + +#endif int main () { try{ shared_memory_object::remove(ShmName); test::test_named_creation(); + #ifdef BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES + test::test_named_creation(); + #endif //Create and get name, size and address { diff --git a/test/windows_eventlog_stamp_shared_memory_test.cpp b/test/windows_eventlog_stamp_shared_memory_test.cpp index f877463..d5a8eef 100644 --- a/test/windows_eventlog_stamp_shared_memory_test.cpp +++ b/test/windows_eventlog_stamp_shared_memory_test.cpp @@ -7,6 +7,17 @@ // See http://www.boost.org/libs/interprocess for documentation. // ////////////////////////////////////////////////////////////////////////////// + +#include + +#ifndef BOOST_WINDOWS +int main() +{ + return 0; +} + +#else //BOOST_WINDOWS + #define BOOST_INTERPROCESS_BOOTSTAMP_IS_EVENTLOG_BASED #include #include @@ -21,6 +32,7 @@ using namespace boost::interprocess; static const std::size_t ShmSize = 1000; static const char * ShmName = test::get_process_id_name(); +static const wchar_t * ShmNameW = test::get_process_id_wname(); struct eraser { @@ -53,12 +65,37 @@ class shared_memory_creation_test_wrapper {} }; +//This wrapper is necessary to have a common constructor +//in generic named_creation_template functions +class shared_memory_creation_test_wrapper_w + : public eraser + , public shared_memory +{ + + public: + shared_memory_creation_test_wrapper_w(create_only_t) + : shared_memory(create_only, ShmNameW, ShmSize, read_write, 0, permissions()) + {} + + shared_memory_creation_test_wrapper_w(open_only_t) + : shared_memory(open_only, ShmNameW, read_write, 0) + {} + + shared_memory_creation_test_wrapper_w(open_or_create_t) + : shared_memory(open_or_create, ShmNameW, ShmSize, read_write, 0, permissions()) + {} +}; + int main () { + int ret = 0; try{ shared_memory_object::remove(ShmName); test::test_named_creation(); + #ifdef BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES + test::test_named_creation(); + #endif //Create and get name, size and address { @@ -75,10 +112,11 @@ int main () } } catch(std::exception &ex){ - shared_memory_object::remove(ShmName); std::cout << ex.what() << std::endl; - return 1; + ret = 1; } shared_memory_object::remove(ShmName); - return 0; + return ret; } + +#endif //BOOST_WINDOWS diff --git a/test/windows_shared_dir_func.cpp b/test/windows_shared_dir_func.cpp index 081d558..d0d8a84 100644 --- a/test/windows_shared_dir_func.cpp +++ b/test/windows_shared_dir_func.cpp @@ -35,6 +35,16 @@ inline void get_shared_dir(std::string &shared_dir) dir_created = true; } +inline void get_shared_dir(std::wstring &shared_dir) +{ + shared_dir = boost::interprocess::ipcdetail::get_temporary_wpath(); + shared_dir += L"/boostipctest_"; + shared_dir += boost::interprocess::test::get_process_id_wname(); + if(!dir_created) + ipcdetail::create_directory(shared_dir.c_str()); + dir_created = true; +} + }}} //namespace boost::interprocess::ipcdetail #include diff --git a/test/windows_shared_memory_test.cpp b/test/windows_shared_memory_test.cpp index 172f2d3..2aeeb4e 100644 --- a/test/windows_shared_memory_test.cpp +++ b/test/windows_shared_memory_test.cpp @@ -53,11 +53,42 @@ class shared_memory_creation_test_wrapper {} }; +#ifdef BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES + +static const wchar_t *wname_initialization_routine() +{ + static std::wstring process_name; + test::get_process_id_wname(process_name); + return process_name.c_str(); +} + +class shared_memory_creation_test_wrapper_w + : public windows_shared_memory_t +{ + public: + shared_memory_creation_test_wrapper_w(create_only_t) + : windows_shared_memory_t(create_only, wname_initialization_routine(), ShmSize, read_write, 0, permissions()) + {} + + shared_memory_creation_test_wrapper_w(open_only_t) + : windows_shared_memory_t(open_only, wname_initialization_routine(), read_write, 0) + {} + + shared_memory_creation_test_wrapper_w(open_or_create_t) + : windows_shared_memory_t(open_or_create, wname_initialization_routine(), ShmSize, read_write, 0, permissions()) + {} +}; + +#endif //BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES + int main () { try{ test::test_named_creation(); + #ifdef BOOST_INTERPROCESS_WCHAR_NAMED_RESOURCES + test::test_named_creation(); + #endif } catch(std::exception &ex){ std::cout << ex.what() << std::endl; diff --git a/test/xsi_shared_memory_mapping_test.cpp b/test/xsi_shared_memory_mapping_test.cpp index 8ae1623..b526bc5 100644 --- a/test/xsi_shared_memory_mapping_test.cpp +++ b/test/xsi_shared_memory_mapping_test.cpp @@ -49,14 +49,6 @@ class xsi_shared_memory_remover xsi_shared_memory & xsi_shm_; }; -inline std::string get_filename() -{ - std::string ret (ipcdetail::get_temporary_path()); - ret += "/"; - ret += test::get_process_id_name(); - return ret; -} - int main () { std::string filename(get_filename());