|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r64333 - trunk/boost/interprocess/detail
From: igaztanaga_at_[hidden]
Date: 2010-07-25 12:39:27
Author: igaztanaga
Date: 2010-07-25 12:39:26 EDT (Sun, 25 Jul 2010)
New Revision: 64333
URL: http://svn.boost.org/trac/boost/changeset/64333
Log:
Changes for Boost 1.45
Added:
trunk/boost/interprocess/detail/robust_emulation.hpp (contents, props changed)
Text files modified:
trunk/boost/interprocess/detail/os_file_functions.hpp | 124 ++++++
trunk/boost/interprocess/detail/os_thread_functions.hpp | 30 +
trunk/boost/interprocess/detail/posix_time_types_wrk.hpp | 3
trunk/boost/interprocess/detail/preprocessor.hpp | 52 ++
trunk/boost/interprocess/detail/tmp_dir_helpers.hpp | 14
trunk/boost/interprocess/detail/transform_iterator.hpp | 21 +
trunk/boost/interprocess/detail/win32_api.hpp | 642 ++++++++++++++++++++++++++++++++++++++-
trunk/boost/interprocess/detail/workaround.hpp | 2
trunk/boost/interprocess/detail/xsi_shared_memory_device.hpp | 6
9 files changed, 833 insertions(+), 61 deletions(-)
Modified: trunk/boost/interprocess/detail/os_file_functions.hpp
==============================================================================
--- trunk/boost/interprocess/detail/os_file_functions.hpp (original)
+++ trunk/boost/interprocess/detail/os_file_functions.hpp 2010-07-25 12:39:26 EDT (Sun, 25 Jul 2010)
@@ -14,6 +14,8 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/errors.hpp>
+#include <boost/interprocess/permissions.hpp>
+
#include <string>
#if (defined BOOST_INTERPROCESS_WINDOWS)
@@ -53,6 +55,7 @@
typedef enum { read_only = winapi::generic_read
, read_write = winapi::generic_read | winapi::generic_write
, copy_on_write
+ , read_private
, invalid_mode = 0xffff
} mode_t;
@@ -83,34 +86,36 @@
{ return hnd.handle; }
inline bool create_directory(const char *path)
-{ return winapi::create_directory(path, 0); }
+{ return winapi::create_directory(path); }
inline const char *get_temporary_path()
{ return std::getenv("TMP"); }
inline file_handle_t create_new_file
- (const char *name, mode_t mode = read_write, bool temporary = false)
+ (const char *name, mode_t mode, const permissions & perm, bool temporary = false)
{
unsigned long attr = temporary ? winapi::file_attribute_temporary : 0;
return winapi::create_file
- (name, (unsigned int)mode, winapi::create_new, attr);
+ ( name, (unsigned int)mode, winapi::create_new, attr
+ , (winapi::interprocess_security_attributes*)perm.get_permissions());
}
inline file_handle_t create_or_open_file
- (const char *name, mode_t mode = read_write, bool temporary = false)
+ (const char *name, mode_t mode, const permissions & perm, bool temporary = false)
{
unsigned long attr = temporary ? winapi::file_attribute_temporary : 0;
return winapi::create_file
- (name, (unsigned int)mode, winapi::open_always, attr);
+ ( name, (unsigned int)mode, winapi::open_always, attr
+ , (winapi::interprocess_security_attributes*)perm.get_permissions());
}
inline file_handle_t open_existing_file
- (const char *name, mode_t mode = read_write, bool temporary = false)
+ (const char *name, mode_t mode, bool temporary = false)
{
unsigned long attr = temporary ? winapi::file_attribute_temporary : 0;
return winapi::create_file
- (name, (unsigned int)mode, winapi::open_existing, attr);
+ (name, (unsigned int)mode, winapi::open_existing, attr, 0);
}
inline bool delete_file(const char *name)
@@ -299,6 +304,44 @@
return delete_subdirectories_recursive(refcstrRootDirectory, dont_delete_this, 0u);
}
+
+template<class Function>
+inline bool for_each_file_in_dir(const char *dir, Function f)
+{
+ void * hFile; // Handle to directory
+ winapi::win32_find_data_t FileInformation; // File information
+
+ //Get base directory
+ std::string str(dir);
+ const std::size_t base_root_dir_len = str.size();
+
+ //Find all files and directories
+ str += "\\*.*";
+ hFile = winapi::find_first_file(str.c_str(), &FileInformation);
+ if(hFile != winapi::invalid_handle_value){
+ do{ //Now loop every file
+ str.erase(base_root_dir_len);
+ //If it's not "." or ".." skip it
+ if(FileInformation.cFileName[0] != '.'){
+ str += "\\"; str += FileInformation.cFileName;
+ //If it's a file, apply erase logic
+ if(!(FileInformation.dwFileAttributes & winapi::file_attribute_directory)){
+ f(str.c_str(), FileInformation.cFileName);
+ }
+ }
+ //Go to the next file
+ } while(winapi::find_next_file(hFile, &FileInformation) == 1);
+
+ // Close handle and see if the loop has ended with an error
+ winapi::find_close(hFile);
+ if(winapi::get_last_error() != winapi::error_no_more_files){
+ return false;
+ }
+ }
+ return true;
+}
+
+
#else //#if (defined BOOST_INTERPROCESS_WINDOWS)
typedef int file_handle_t;
@@ -313,6 +356,7 @@
typedef enum { read_only = O_RDONLY
, read_write = O_RDWR
, copy_on_write
+ , read_private
, invalid_mode = 0xffff
} mode_t;
@@ -335,7 +379,7 @@
{ return hnd.handle; }
inline bool create_directory(const char *path)
-{ return ::mkdir(path, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == 0; }
+{ return ::mkdir(path, 0777) == 0 && ::chmod(path, 0777) == 0; }
inline const char *get_temporary_path()
{
@@ -351,24 +395,32 @@
}
inline file_handle_t create_new_file
- (const char *name, mode_t mode = read_write, bool temporary = false)
+ (const char *name, mode_t mode, const permissions & perm, bool temporary = false)
{
(void)temporary;
- return ::open(name, ((int)mode) | O_EXCL | O_CREAT, S_IRWXG | S_IRWXO | S_IRWXU);
+ int ret = ::open(name, ((int)mode) | O_EXCL | O_CREAT, perm.get_permissions());
+ if(ret >= 0){
+ ::fchmod(ret, perm.get_permissions());
+ }
+ return ret;
}
inline file_handle_t create_or_open_file
- (const char *name, mode_t mode = read_write, bool temporary = false)
+ (const char *name, mode_t mode, const permissions & perm, bool temporary = false)
{
(void)temporary;
- return ::open(name, ((int)mode) | O_CREAT, S_IRWXG | S_IRWXO | S_IRWXU);
+ int ret = ::open(name, ((int)mode) | O_CREAT, perm.get_permissions());
+ if(ret >= 0){
+ ::fchmod(ret, perm.get_permissions());
+ }
+ return ret;
}
inline file_handle_t open_existing_file
- (const char *name, mode_t mode = read_write, bool temporary = false)
+ (const char *name, mode_t mode, bool temporary = false)
{
(void)temporary;
- return ::open(name, (int)mode, S_IRWXG | S_IRWXO | S_IRWXU);
+ return ::open(name, (int)mode, 0666);
}
inline bool delete_file(const char *name)
@@ -388,7 +440,7 @@
}
inline bool set_file_pointer(file_handle_t hnd, offset_t off, file_pos_t pos)
-{ return off == ::lseek(hnd, off, (int)pos); }
+{ return ((off_t)(-1)) != ::lseek(hnd, off, (int)pos); }
inline bool get_file_pointer(file_handle_t hnd, offset_t &off)
{
@@ -543,6 +595,48 @@
return std::remove(refcstrRootDirectory.c_str()) ? false : true;
}
+template<class Function>
+inline bool for_each_file_in_dir(const char *dir, Function f)
+{
+ std::string refcstrRootDirectory(dir);
+
+ DIR *d = opendir(refcstrRootDirectory.c_str());
+ if(!d) {
+ return false;
+ }
+
+ struct dir_close
+ {
+ DIR *d_;
+ dir_close(DIR *d) : d_(d) {}
+ ~dir_close() { ::closedir(d_); }
+ } dc(d); (void)dc;
+
+ struct ::dirent *de;
+ struct ::stat st;
+ std::string fn;
+
+ while((de=::readdir(d))) {
+ if( de->d_name[0] == '.' && ( de->d_name[1] == '\0'
+ || (de->d_name[1] == '.' && de->d_name[2] == '\0' )) ){
+ continue;
+ }
+ fn = refcstrRootDirectory;
+ fn += '/';
+ fn += de->d_name;
+
+ if(::stat(fn.c_str(), & st)) {
+ return false;
+ }
+ //If it's a file, apply erase logic
+ if(!S_ISDIR(st.st_mode)) {
+ f(fn.c_str(), de->d_name);
+ }
+ }
+ return true;
+}
+
+
//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)
{
Modified: trunk/boost/interprocess/detail/os_thread_functions.hpp
==============================================================================
--- trunk/boost/interprocess/detail/os_thread_functions.hpp (original)
+++ trunk/boost/interprocess/detail/os_thread_functions.hpp 2010-07-25 12:39:26 EDT (Sun, 25 Jul 2010)
@@ -13,6 +13,8 @@
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/streams/bufferstream.hpp>
+#include <boost/interprocess/detail/posix_time_types_wrk.hpp>
#if (defined BOOST_INTERPROCESS_WINDOWS)
# include <boost/interprocess/detail/win32_api.hpp>
@@ -78,6 +80,20 @@
return get_invalid_thread_id();
}
+inline long double get_current_process_creation_time()
+{
+ winapi::interprocess_filetime CreationTime, ExitTime, KernelTime, UserTime;
+
+ get_process_times
+ ( winapi::get_current_process(), &CreationTime, &ExitTime, &KernelTime, &UserTime);
+
+ typedef long double ldouble_t;
+ const ldouble_t resolution = (100.0l/1000000000.0l);
+ return CreationTime.dwHighDateTime*(ldouble_t(1u<<31u)*2.0l*resolution) +
+ CreationTime.dwLowDateTime*resolution;
+}
+
+
#else //#if (defined BOOST_INTERPROCESS_WINDOWS)
typedef pthread_t OS_thread_id_t;
@@ -160,8 +176,22 @@
return OS_systemwide_thread_id_t(get_invalid_process_id(), get_invalid_thread_id());
}
+inline long double get_current_process_creation_time()
+{ return 0.0L; }
+
#endif //#if (defined BOOST_INTERPROCESS_WINDOWS)
+typedef char pid_str_t[sizeof(OS_process_id_t)*3+1];
+
+inline void get_pid_str(pid_str_t &pid_str, OS_process_id_t pid)
+{
+ bufferstream bstream(pid_str, sizeof(pid_str));
+ bstream << pid << std::ends;
+}
+
+inline void get_pid_str(pid_str_t &pid_str)
+{ get_pid_str(pid_str, get_current_process_id()); }
+
} //namespace detail{
} //namespace interprocess {
} //namespace boost {
Modified: trunk/boost/interprocess/detail/posix_time_types_wrk.hpp
==============================================================================
--- trunk/boost/interprocess/detail/posix_time_types_wrk.hpp (original)
+++ trunk/boost/interprocess/detail/posix_time_types_wrk.hpp 2010-07-25 12:39:26 EDT (Sun, 25 Jul 2010)
@@ -20,9 +20,8 @@
#endif //#ifndef WIN32_LEAN_AND_MEAN
#endif //#ifdef _WIN32
-//#include <boost/date_time/posix_time/ptime.hpp>
-//#include <boost/date_time/microsec_time_clock.hpp>
#include <boost/date_time/posix_time/posix_time_types.hpp>
+#include <boost/date_time/posix_time/conversion.hpp>
namespace boost {
namespace interprocess {
Modified: trunk/boost/interprocess/detail/preprocessor.hpp
==============================================================================
--- trunk/boost/interprocess/detail/preprocessor.hpp (original)
+++ trunk/boost/interprocess/detail/preprocessor.hpp 2010-07-25 12:39:26 EDT (Sun, 25 Jul 2010)
@@ -15,8 +15,7 @@
# pragma once
#endif
-#include <boost/interprocess/detail/config_begin.hpp>
-#include <boost/interprocess/detail/workaround.hpp>
+#include "config_begin.hpp"
#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
#error "This file is not needed when perfect forwarding is available"
@@ -36,7 +35,7 @@
//This cast is ugly but it is necessary until "perfect forwarding"
//is achieved in C++0x. Meanwhile, if we want to be able to
//bind rvalues with non-const references, we have to be ugly
-#ifdef BOOST_HAS_RVALUE_REFS
+#ifndef BOOST_NO_RVALUE_REFERENCES
#define BOOST_INTERPROCESS_PP_PARAM_LIST(z, n, data) \
BOOST_PP_CAT(P, n) && BOOST_PP_CAT(p, n) \
//!
@@ -46,7 +45,7 @@
//!
#endif
-#ifdef BOOST_HAS_RVALUE_REFS
+#ifndef BOOST_NO_RVALUE_REFERENCES
#define BOOST_INTERPROCESS_PARAM(U, u) \
U && u \
//!
@@ -56,10 +55,22 @@
//!
#endif
-#ifdef BOOST_HAS_RVALUE_REFS
+#ifndef BOOST_NO_RVALUE_REFERENCES
+
+#ifdef BOOST_MOVE_OLD_RVALUE_REF_BINDING_RULES
+
+#define BOOST_INTERPROCESS_AUX_PARAM_INIT(z, n, data) \
+ BOOST_PP_CAT(m_p, n) (BOOST_INTERPROCESS_MOVE_NAMESPACE::forward< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(p, n) )) \
+//!
+
+#else
+
#define BOOST_INTERPROCESS_AUX_PARAM_INIT(z, n, data) \
BOOST_PP_CAT(m_p, n) (BOOST_PP_CAT(p, n)) \
//!
+
+#endif
+
#else
#define BOOST_INTERPROCESS_AUX_PARAM_INIT(z, n, data) \
BOOST_PP_CAT(m_p, n) (const_cast<BOOST_PP_CAT(P, n) &>(BOOST_PP_CAT(p, n))) \
@@ -70,10 +81,23 @@
BOOST_PP_CAT(++m_p, n) \
//!
-#ifdef BOOST_HAS_RVALUE_REFS
+#ifndef BOOST_NO_RVALUE_REFERENCES
+
+#if defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
+
+#define BOOST_INTERPROCESS_AUX_PARAM_DEFINE(z, n, data) \
+ BOOST_PP_CAT(P, n) & BOOST_PP_CAT(m_p, n); \
+//!
+
+#else
+
#define BOOST_INTERPROCESS_AUX_PARAM_DEFINE(z, n, data) \
BOOST_PP_CAT(P, n) && BOOST_PP_CAT(m_p, n); \
//!
+
+#endif //defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
+
+
#else
#define BOOST_INTERPROCESS_AUX_PARAM_DEFINE(z, n, data) \
BOOST_PP_CAT(P, n) & BOOST_PP_CAT(m_p, n); \
@@ -81,13 +105,25 @@
#endif
#define BOOST_INTERPROCESS_PP_PARAM_FORWARD(z, n, data) \
-boost::interprocess::forward< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(p, n) ) \
+::boost::interprocess::forward< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(p, n) ) \
+//!
+
+#if !defined(BOOST_NO_RVALUE_REFERENCES) && defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
+
+#include <boost/interprocess/containers/container/detail/stored_ref.hpp>
+
+#define BOOST_INTERPROCESS_PP_MEMBER_FORWARD(z, n, data) \
+::boost::container::containers_detail::stored_ref< BOOST_PP_CAT(P, n) >::forward( BOOST_PP_CAT(m_p, n) ) \
//!
+#else
+
#define BOOST_INTERPROCESS_PP_MEMBER_FORWARD(z, n, data) \
-boost::interprocess::forward< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(m_p, n) ) \
+::boost::interprocess::forward< BOOST_PP_CAT(P, n) >( BOOST_PP_CAT(m_p, n) ) \
//!
+#endif //!defined(BOOST_NO_RVALUE_REFERENCES) && defined(BOOST_MOVE_MSVC_10_MEMBER_RVALUE_REF_BUG)
+
#define BOOST_INTERPROCESS_PP_MEMBER_IT_FORWARD(z, n, data) \
BOOST_PP_CAT(*m_p, n) \
//!
Added: trunk/boost/interprocess/detail/robust_emulation.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/interprocess/detail/robust_emulation.hpp 2010-07-25 12:39:26 EDT (Sun, 25 Jul 2010)
@@ -0,0 +1,439 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2010-2010. Distributed under the 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_ROBUST_EMULATION_HPP
+#define BOOST_INTERPROCESS_ROBUST_EMULATION_HPP
+
+#if defined(_MSC_VER)&&(_MSC_VER>=1200)
+#pragma once
+#endif
+
+#include <boost/interprocess/detail/config_begin.hpp>
+#include <boost/interprocess/detail/workaround.hpp>
+#include <boost/interprocess/sync/interprocess_mutex.hpp>
+#include <boost/interprocess/sync/interprocess_recursive_mutex.hpp>
+#include <boost/interprocess/detail/atomic.hpp>
+#include <boost/interprocess/detail/os_file_functions.hpp>
+#include <boost/interprocess/detail/tmp_dir_helpers.hpp>
+#include <boost/interprocess/detail/intermodule_singleton.hpp>
+#include <boost/interprocess/exceptions.hpp>
+#include <string>
+
+namespace boost{
+namespace interprocess{
+namespace detail{
+
+namespace robust_emulation_helpers {
+
+template<class T>
+class mutex_traits
+{
+ public:
+ static void take_ownership(T &t)
+ { t.take_ownership(); }
+};
+
+inline void remove_if_can_lock_file(const char *file_path)
+{
+ file_handle_t fhnd = open_existing_file(file_path, read_write);
+
+ if(fhnd != invalid_file()){
+ bool acquired;
+ if(try_acquire_file_lock(fhnd, acquired) && acquired){
+ delete_file(file_path);
+ }
+ close_file(fhnd);
+ }
+}
+
+inline const char *robust_lock_subdir_path()
+{ return "robust"; }
+
+inline const char *robust_lock_prefix()
+{ return "lck"; }
+
+inline void robust_lock_path(std::string &s)
+{
+ tmp_folder(s);
+ s += "/";
+ s += robust_lock_subdir_path();
+}
+
+inline void create_and_get_robust_lock_file_path(std::string &s, OS_process_id_t pid)
+{
+ file_locking_helpers::create_tmp_subdir_and_get_pid_based_filepath
+ (robust_lock_subdir_path(), robust_lock_prefix(), pid, s);
+}
+
+//This class will be a intermodule_singleton. The constructor will create
+//a lock file, the destructor will erase it.
+//
+//We should take in care that another process might be erasing unlocked
+//files while creating this one, so there are some race conditions we must
+//take in care to guarantee some robustness.
+class robust_mutex_lock_file
+{
+ file_handle_t fd;
+ std::string fname;
+ public:
+ robust_mutex_lock_file()
+ {
+ permissions p;
+ p.set_unrestricted();
+ //Remove old lock files of other processes
+ remove_old_robust_lock_files();
+ //Create path and obtain lock file path for this process
+ create_and_get_robust_lock_file_path(fname, get_current_process_id());
+
+ //Now try to open or create the lock file
+ fd = create_or_open_file(fname.c_str(), read_write, p);
+ //If we can't open or create it, then something unrecoverable has happened
+ if(fd == invalid_file()){
+ throw interprocess_exception(other_error, "Robust emulation robust_mutex_lock_file constructor failed: could not open or create file");
+ }
+
+ //Now we must take in care a race condition with another process
+ //calling "remove_old_robust_lock_files()". No other threads from this
+ //process will be creating the lock file because intermodule_singleton
+ //guarantees this. So let's loop acquiring the lock and checking if we
+ //can't exclusively create the file (if the file is erased by another process
+ //then this exclusive open would fail). If the file can't be exclusively created
+ //then we have correctly open/create and lock the file. If the file can
+ //be exclusively created, then close previous locked file and try again.
+ while(1){
+ bool acquired;
+ if(!try_acquire_file_lock(fd, acquired) || !acquired ){
+ throw interprocess_exception(other_error, "Robust emulation robust_mutex_lock_file constructor failed: try_acquire_file_lock");
+ }
+ //Creating exclusively must fail with already_exists_error
+ //to make sure we've locked the file and no one has
+ //deleted it between creation and locking
+ file_handle_t fd2 = create_new_file(fname.c_str(), read_write, p);
+ if(fd2 != invalid_file()){
+ close_file(fd);
+ fd = fd2;
+ continue;
+ }
+ //If exclusive creation fails with expected error go ahead
+ else if(error_info(system_error_code()).get_error_code() == already_exists_error){ //must already exist
+ //Leak descriptor to mantain the file locked until the process dies
+ break;
+ }
+ //If exclusive creation fails with unexpected error throw an unrecoverable error
+ else{
+ close_file(fd);
+ throw interprocess_exception(other_error, "Robust emulation robust_mutex_lock_file constructor failed: create_file filed with unexpected error");
+ }
+ }
+ }
+
+ ~robust_mutex_lock_file()
+ {
+ //The destructor is guaranteed by intermodule_singleton to be
+ //executed serialized between all threads from current process,
+ //so we just need to close and unlink the file.
+ close_file(fd);
+ //If some other process deletes the file before us after
+ //closing it there should not be any problem.
+ delete_file(fname.c_str());
+ }
+
+ private:
+ //This functor is execute for all files in the lock file directory
+ class other_process_lock_remover
+ {
+ public:
+ void operator()(const char *filepath, const char *filename)
+ {
+ std::string pid_str;
+ //If the lock file is not our own lock file, then try to do the cleanup
+ if(!file_locking_helpers::check_if_filename_complies_with_pid
+ (filename, robust_lock_prefix(), get_current_process_id(), pid_str)){
+ remove_if_can_lock_file(filepath);
+ }
+ }
+ };
+
+ bool remove_old_robust_lock_files()
+ {
+ std::string refcstrRootDirectory;
+ robust_lock_path(refcstrRootDirectory);
+ return for_each_file_in_dir(refcstrRootDirectory.c_str(), other_process_lock_remover());
+ }
+};
+
+} //namespace robust_emulation_helpers {
+
+//This is the mutex class. Mutex should follow mutex concept
+//with an additonal "take_ownership()" function to take ownership of the
+//mutex when robust_emulation_mutex determines the previous owner was dead.
+template<class Mutex>
+class robust_emulation_mutex
+{
+ public:
+ static const boost::uint32_t correct_state = 0;
+ static const boost::uint32_t fixing_state = 1;
+ static const boost::uint32_t broken_state = 2;
+
+ typedef robust_emulation_helpers::mutex_traits<Mutex> mutex_traits_t;
+
+ robust_emulation_mutex();
+ void lock();
+ bool try_lock();
+ bool timed_lock(const boost::posix_time::ptime &abs_time);
+ void unlock();
+ void consistent();
+ bool previous_owner_dead();
+
+ private:
+ static const unsigned int spin_threshold = 100u;
+ bool lock_own_unique_file();
+ bool robust_check();
+ bool check_if_owner_dead_and_take_ownership_atomically();
+ bool is_owner_dead(boost::uint32_t owner);
+ void owner_to_filename(boost::uint32_t owner, std::string &s);
+ //The real mutex
+ Mutex mtx;
+ //The pid of the owner
+ volatile boost::uint32_t owner;
+ //The state of the mutex (correct, fixing, broken)
+ volatile boost::uint32_t state;
+};
+
+template<class Mutex>
+inline robust_emulation_mutex<Mutex>::robust_emulation_mutex()
+ : mtx(), owner(get_invalid_process_id()), state(correct_state)
+{}
+
+template<class Mutex>
+inline void robust_emulation_mutex<Mutex>::lock()
+{
+ //If the mutex is broken (recovery didn't call consistent()),
+ //then throw an exception
+ if(atomic_read32(&this->state) == broken_state){
+ throw interprocess_exception(lock_error, "Broken id");
+ }
+
+ //This function provokes intermodule_singleton instantiation
+ if(!this->lock_own_unique_file()){
+ throw interprocess_exception(lock_error, "Broken id");
+ }
+
+ //Now the logic. Try to lock, if successful mark the owner
+ //if it fails, start recovery logic
+ unsigned int spin_count = 0;
+ while(1){
+ if (mtx.try_lock()){
+ atomic_write32(&this->owner, get_current_process_id());
+ break;
+ }
+ else{
+ //Do the dead owner checking each spin_threshold lock tries
+ detail::thread_yield();
+ ++spin_count;
+ if(spin_count > spin_threshold){
+ //Check if owner dead and take ownership if possible
+ if(!this->robust_check()){
+ spin_count = 0;
+ }
+ else{
+ break;
+ }
+ }
+ }
+ }
+}
+
+template<class Mutex>
+inline bool robust_emulation_mutex<Mutex>::try_lock()
+{
+ //Same as lock() but without spinning
+ if(atomic_read32(&this->state) == broken_state){
+ throw interprocess_exception(lock_error, "Broken id");
+ }
+
+ if(!this->lock_own_unique_file()){
+ throw interprocess_exception(lock_error, "Broken id");
+ }
+
+ if (mtx.try_lock()){
+ atomic_write32(&this->owner, get_current_process_id());
+ return true;
+ }
+ else{
+ if(!this->robust_check()){
+ return false;
+ }
+ else{
+ return true;
+ }
+ }
+}
+
+template<class Mutex>
+inline bool robust_emulation_mutex<Mutex>::timed_lock
+ (const boost::posix_time::ptime &abs_time)
+{
+ //Same as lock() but with an additional timeout
+ if(abs_time == boost::posix_time::pos_infin){
+ this->lock();
+ return true;
+ }
+ //Obtain current count and target time
+ boost::posix_time::ptime now = microsec_clock::universal_time();
+
+ if(now >= abs_time)
+ return this->try_lock();
+
+ do{
+ if(this->try_lock()){
+ break;
+ }
+ now = microsec_clock::universal_time();
+
+ if(now >= abs_time){
+ return this->try_lock();
+ }
+ // relinquish current time slice
+ detail::thread_yield();
+ }while (true);
+
+ return true;
+}
+
+template<class Mutex>
+inline void robust_emulation_mutex<Mutex>::owner_to_filename(boost::uint32_t owner, std::string &s)
+{
+ robust_emulation_helpers::create_and_get_robust_lock_file_path(s, owner);
+}
+
+template<class Mutex>
+inline bool robust_emulation_mutex<Mutex>::robust_check()
+{
+ //If the old owner was dead, and we've acquired ownership, mark
+ //the mutex as 'fixing'. This means that a "consistent()" is needed
+ //to avoid marking the mutex as "broken" when the mutex is unlocked.
+ if(!this->check_if_owner_dead_and_take_ownership_atomically()){
+ return false;
+ }
+ atomic_write32(&this->state, fixing_state);
+ return true;
+}
+
+template<class Mutex>
+inline bool robust_emulation_mutex<Mutex>::check_if_owner_dead_and_take_ownership_atomically()
+{
+ boost::uint32_t cur_owner = get_current_process_id();
+ boost::uint32_t old_owner = atomic_read32(&this->owner), old_owner2;
+ //The cas loop guarantees that only one thread from this or another process
+ //will succeed taking ownership
+ do{
+ //Check if owner is dead
+ if(!this->is_owner_dead(old_owner)){
+ return false;
+ }
+ //If it's dead, try to mark this process as the owner in the owner field
+ old_owner2 = old_owner;
+ old_owner = atomic_cas32(&this->owner, cur_owner, old_owner);
+ }while(old_owner2 != old_owner);
+ //If success, we fix mutex internals to assure our ownership
+ mutex_traits_t::take_ownership(mtx);
+ return true;
+}
+
+template<class Mutex>
+inline bool robust_emulation_mutex<Mutex>::is_owner_dead(boost::uint32_t owner)
+{
+ //If owner is an invalid id, then it's clear it's dead
+ if(owner == (boost::uint32_t)get_invalid_process_id()){
+ return true;
+ }
+
+ //Obtain the lock filename of the owner field
+ std::string file;
+ this->owner_to_filename(owner, file);
+
+ //Now the logic is to open and lock it
+ file_handle_t fhnd = open_existing_file(file.c_str(), read_write);
+
+ if(fhnd != invalid_file()){
+ //If we can open the file, lock it.
+ bool acquired;
+ if(try_acquire_file_lock(fhnd, acquired) && acquired){
+ //If locked, just delete the file
+ delete_file(file.c_str());
+ close_file(fhnd);
+ return true;
+ }
+ //If not locked, the owner is suppossed to be still alive
+ close_file(fhnd);
+ }
+ else{
+ //If the lock file does not exist then the owner is dead (a previous cleanup)
+ //function has deleted the file. If there is another reason, then this is
+ //an unrecoverable error
+ if(error_info(system_error_code()).get_error_code() == not_found_error){
+ return true;
+ }
+ }
+ return false;
+}
+
+template<class Mutex>
+inline void robust_emulation_mutex<Mutex>::consistent()
+{
+ //This function supposes the previous state was "fixing"
+ //and the current process holds the mutex
+ if(atomic_read32(&this->state) != fixing_state &&
+ atomic_read32(&this->owner) != (boost::uint32_t)get_current_process_id()){
+ throw interprocess_exception(lock_error, "Broken id");
+ }
+ //If that's the case, just update mutex state
+ atomic_write32(&this->state, correct_state);
+}
+
+template<class Mutex>
+inline bool robust_emulation_mutex<Mutex>::previous_owner_dead()
+{
+ //Notifies if a owner recovery has been performed in the last lock()
+ return atomic_read32(&this->state) == fixing_state;
+};
+
+template<class Mutex>
+inline void robust_emulation_mutex<Mutex>::unlock()
+{
+ //If in "fixing" state, unlock and mark the mutex as unrecoverable
+ //so next locks will fail and all threads will be notified that the
+ //data protected by the mutex was not recoverable.
+ if(atomic_read32(&this->state) == fixing_state){
+ atomic_write32(&this->state, broken_state);
+ }
+ //Write an invalid owner to minimize pid reuse possibility
+ atomic_write32(&this->owner, get_invalid_process_id());
+ mtx.unlock();
+}
+
+template<class Mutex>
+inline bool robust_emulation_mutex<Mutex>::lock_own_unique_file()
+{
+ //This function forces instantiation of the singleton
+ robust_emulation_helpers::robust_mutex_lock_file* dummy =
+ &detail::intermodule_singleton
+ <robust_emulation_helpers::robust_mutex_lock_file>::get();
+ return dummy != 0;
+}
+
+} //namespace detail{
+} //namespace interprocess{
+} //namespace boost{
+
+#include <boost/interprocess/detail/config_end.hpp>
+
+#endif
Modified: trunk/boost/interprocess/detail/tmp_dir_helpers.hpp
==============================================================================
--- trunk/boost/interprocess/detail/tmp_dir_helpers.hpp (original)
+++ trunk/boost/interprocess/detail/tmp_dir_helpers.hpp 2010-07-25 12:39:26 EDT (Sun, 25 Jul 2010)
@@ -37,10 +37,8 @@
#if defined (BOOST_INTERPROCESS_HAS_WINDOWS_KERNEL_BOOTTIME)
inline void get_bootstamp(std::string &s, bool add = false)
{
- char bootstamp[winapi::BootstampLength*2+1];
- std::size_t bootstamp_length = winapi::BootstampLength*2;
- winapi::get_boot_time_str(bootstamp, bootstamp_length);
- bootstamp[winapi::BootstampLength*2] = 0;
+ std::string bootstamp;
+ winapi::get_last_bootup_time(bootstamp);
if(add){
s += bootstamp;
}
@@ -118,7 +116,7 @@
tmp_name += filename;
}
-inline void create_tmp_dir(std::string &tmp_name)
+inline void create_tmp_and_clean_old(std::string &tmp_name)
{
//First get the temp directory
std::string root_tmp_name;
@@ -146,12 +144,14 @@
std::string subdir = tmp_name;
subdir.erase(0, root_tmp_name.size()+1);
delete_subdirectories(root_tmp_name, subdir.c_str());
+ #else
+ tmp_name = root_tmp_name;
#endif
}
-inline void create_tmp_dir_and_get_filename(const char *filename, std::string &tmp_name)
+inline void create_tmp_and_clean_old_and_get_filename(const char *filename, std::string &tmp_name)
{
- create_tmp_dir(tmp_name);
+ create_tmp_and_clean_old(tmp_name);
tmp_filename(filename, tmp_name);
}
Modified: trunk/boost/interprocess/detail/transform_iterator.hpp
==============================================================================
--- trunk/boost/interprocess/detail/transform_iterator.hpp (original)
+++ trunk/boost/interprocess/detail/transform_iterator.hpp 2010-07-25 12:39:26 EDT (Sun, 25 Jul 2010)
@@ -50,7 +50,7 @@
: m_value(px)
{}
- T* operator->() const { return &m_value; }
+ T* operator->() const { return const_cast<T*>(&m_value); }
// This function is needed for MWCW and BCC, which won't call operator->
// again automatically per 13.3.1.2 para 8
// operator T*() const { return &m_value; }
@@ -87,13 +87,25 @@
return result;
}
+ transform_iterator& operator--()
+ { decrement(); return *this; }
+
+ transform_iterator operator--(int)
+ {
+ transform_iterator result (*this);
+ decrement();
+ return result;
+ }
+
friend bool operator== (const transform_iterator& i, const transform_iterator& i2)
{ return i.equal(i2); }
friend bool operator!= (const transform_iterator& i, const transform_iterator& i2)
{ return !(i == i2); }
-/*
+ friend bool operator< (const transform_iterator& i, const transform_iterator& i2)
+ { return i < i2; }
+
friend bool operator> (const transform_iterator& i, const transform_iterator& i2)
{ return i2 < i; }
@@ -102,7 +114,7 @@
friend bool operator>= (const transform_iterator& i, const transform_iterator& i2)
{ return !(i < i2); }
-*/
+
friend typename Iterator::difference_type operator- (const transform_iterator& i, const transform_iterator& i2)
{ return i2.distance_to(i); }
@@ -129,6 +141,9 @@
typename UnaryFunction::result_type operator*() const
{ return dereference(); }
+ typename UnaryFunction::result_type operator[](typename Iterator::difference_type off) const
+ { return UnaryFunction::operator()(m_it[off]); }
+
operator_arrow_proxy<typename UnaryFunction::result_type>
operator->() const
{ return operator_arrow_proxy<typename UnaryFunction::result_type>(dereference()); }
Modified: trunk/boost/interprocess/detail/win32_api.hpp
==============================================================================
--- trunk/boost/interprocess/detail/win32_api.hpp (original)
+++ trunk/boost/interprocess/detail/win32_api.hpp 2010-07-25 12:39:26 EDT (Sun, 25 Jul 2010)
@@ -16,11 +16,14 @@
#include <cstddef>
#include <cstring>
#include <string>
+#include <vector>
#include <memory>
#if (defined _MSC_VER) && (_MSC_VER >= 1200)
# pragma once
# pragma comment( lib, "advapi32.lib" )
+# pragma comment( lib, "oleaut32.lib" )
+# pragma comment( lib, "Ole32.lib" )
#endif
#if (defined BOOST_INTERPROCESS_WINDOWS)
@@ -30,6 +33,7 @@
# error "This file can only be included in Windows OS"
#endif
+
//The structures used in Interprocess with the
//same binary interface as windows ones
namespace boost {
@@ -154,16 +158,394 @@
static void * const hkey_local_machine = (void*)(unsigned long*)(long)(0x80000002);
static unsigned long key_query_value = 0x0001;
+//COM API
+const long RPC_C_AUTHN_LEVEL_PKT_IG = 4;
+const long RPC_C_IMP_LEVEL_IMPERSONATE_IG = 3;
+const long EOAC_NONE_IG = 0;
+const long CLSCTX_INPROC_SERVER_IG = 0x1;
+const long CLSCTX_LOCAL_SERVER_IG = 0x4;
+const long WBEM_FLAG_RETURN_IMMEDIATELY_IG = 0x10;
+const long WBEM_INFINITE_IG = 0xffffffff;
+
} //namespace winapi {
} //namespace interprocess {
} //namespace boost {
-#if !defined( BOOST_USE_WINDOWS_H )
namespace boost {
namespace interprocess {
namespace winapi {
+struct GUID_IG
+{
+ unsigned long Data1;
+ unsigned short Data2;
+ unsigned short Data3;
+ unsigned char Data4[8];
+};
+
+const GUID_IG CLSID_WbemAdministrativeLocator =
+ { 0xcb8555cc, 0x9128, 0x11d1, {0xad, 0x9b, 0x00, 0xc0, 0x4f, 0xd8, 0xfd, 0xff}};
+
+const GUID_IG IID_IUnknown = { 0x00000000, 0x0000, 0x0000, {0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}};
+
+struct wchar_variant
+{
+ unsigned long long dummy;
+ union value_t{
+ wchar_t *pbstrVal;
+ unsigned long long dummy;
+ } value;
+};
+
+ struct IUnknown_IG
+ {
+ public:
+ virtual long __stdcall QueryInterface(
+ /* [in] */ const GUID_IG &riid,
+ /* [iid_is][out] */ void **ppvObject) = 0;
+
+ virtual unsigned long __stdcall AddRef( void) = 0;
+
+ virtual unsigned long __stdcall Release( void) = 0;
+ };
+
+struct IWbemClassObject_IG : public IUnknown_IG
+{
+ public:
+ virtual long __stdcall GetQualifierSet(
+ /* [out] */ void **ppQualSet) = 0;
+
+ virtual long __stdcall Get(
+ /* [string][in] */ const wchar_t * wszName,
+ /* [in] */ long lFlags,
+ /* [unique][in][out] */ wchar_variant *pVal,
+ /* [unique][in][out] */ long *pType,
+ /* [unique][in][out] */ long *plFlavor) = 0;
+
+ virtual long __stdcall Put(
+ /* [string][in] */ const wchar_t * wszName,
+ /* [in] */ long lFlags,
+ /* [in] */ wchar_variant *pVal,
+ /* [in] */ long Type) = 0;
+
+ virtual long __stdcall Delete(
+ /* [string][in] */ const wchar_t * wszName) = 0;
+
+ virtual long __stdcall GetNames(
+ /* [string][in] */ const wchar_t * wszQualifierName,
+ /* [in] */ long lFlags,
+ /* [in] */ wchar_variant *pQualifierVal,
+ /* [out] */ void * *pNames) = 0;
+
+ virtual long __stdcall BeginEnumeration(
+ /* [in] */ long lEnumFlags) = 0;
+
+ virtual long __stdcall Next(
+ /* [in] */ long lFlags,
+ /* [unique][in][out] */ wchar_t * *strName,
+ /* [unique][in][out] */ wchar_variant *pVal,
+ /* [unique][in][out] */ long *pType,
+ /* [unique][in][out] */ long *plFlavor) = 0;
+
+ virtual long __stdcall EndEnumeration( void) = 0;
+
+ virtual long __stdcall GetPropertyQualifierSet(
+ /* [string][in] */ const wchar_t * wszProperty,
+ /* [out] */ void **ppQualSet) = 0;
+
+ virtual long __stdcall Clone(
+ /* [out] */ IWbemClassObject_IG **ppCopy) = 0;
+
+ virtual long __stdcall GetObjectText(
+ /* [in] */ long lFlags,
+ /* [out] */ wchar_t * *pstrObjectText) = 0;
+
+ virtual long __stdcall SpawnDerivedClass(
+ /* [in] */ long lFlags,
+ /* [out] */ IWbemClassObject_IG **ppNewClass) = 0;
+
+ virtual long __stdcall SpawnInstance(
+ /* [in] */ long lFlags,
+ /* [out] */ IWbemClassObject_IG **ppNewInstance) = 0;
+
+ virtual long __stdcall CompareTo(
+ /* [in] */ long lFlags,
+ /* [in] */ IWbemClassObject_IG *pCompareTo) = 0;
+
+ virtual long __stdcall GetPropertyOrigin(
+ /* [string][in] */ const wchar_t * wszName,
+ /* [out] */ wchar_t * *pstrClassName) = 0;
+
+ virtual long __stdcall InheritsFrom(
+ /* [in] */ const wchar_t * strAncestor) = 0;
+
+ virtual long __stdcall GetMethod(
+ /* [string][in] */ const wchar_t * wszName,
+ /* [in] */ long lFlags,
+ /* [out] */ IWbemClassObject_IG **ppInSignature,
+ /* [out] */ IWbemClassObject_IG **ppOutSignature) = 0;
+
+ virtual long __stdcall PutMethod(
+ /* [string][in] */ const wchar_t * wszName,
+ /* [in] */ long lFlags,
+ /* [in] */ IWbemClassObject_IG *pInSignature,
+ /* [in] */ IWbemClassObject_IG *pOutSignature) = 0;
+
+ virtual long __stdcall DeleteMethod(
+ /* [string][in] */ const wchar_t * wszName) = 0;
+
+ virtual long __stdcall BeginMethodEnumeration(
+ /* [in] */ long lEnumFlags) = 0;
+
+ virtual long __stdcall NextMethod(
+ /* [in] */ long lFlags,
+ /* [unique][in][out] */ wchar_t * *pstrName,
+ /* [unique][in][out] */ IWbemClassObject_IG **ppInSignature,
+ /* [unique][in][out] */ IWbemClassObject_IG **ppOutSignature) = 0;
+
+ virtual long __stdcall EndMethodEnumeration( void) = 0;
+
+ virtual long __stdcall GetMethodQualifierSet(
+ /* [string][in] */ const wchar_t * wszMethod,
+ /* [out] */ void **ppQualSet) = 0;
+
+ virtual long __stdcall GetMethodOrigin(
+ /* [string][in] */ const wchar_t * wszMethodName,
+ /* [out] */ wchar_t * *pstrClassName) = 0;
+
+};
+
+
+struct IWbemContext_IG : public IUnknown_IG
+{
+public:
+ virtual long __stdcall Clone(
+ /* [out] */ IWbemContext_IG **ppNewCopy) = 0;
+
+ virtual long __stdcall GetNames(
+ /* [in] */ long lFlags,
+ /* [out] */ void * *pNames) = 0;
+
+ virtual long __stdcall BeginEnumeration(
+ /* [in] */ long lFlags) = 0;
+
+ virtual long __stdcall Next(
+ /* [in] */ long lFlags,
+ /* [out] */ wchar_t * *pstrName,
+ /* [out] */ wchar_variant *pValue) = 0;
+
+ virtual long __stdcall EndEnumeration( void) = 0;
+
+ virtual long __stdcall SetValue(
+ /* [string][in] */ const wchar_t * wszName,
+ /* [in] */ long lFlags,
+ /* [in] */ wchar_variant *pValue) = 0;
+
+ virtual long __stdcall GetValue(
+ /* [string][in] */ const wchar_t * wszName,
+ /* [in] */ long lFlags,
+ /* [out] */ wchar_variant *pValue) = 0;
+
+ virtual long __stdcall DeleteValue(
+ /* [string][in] */ const wchar_t * wszName,
+ /* [in] */ long lFlags) = 0;
+
+ virtual long __stdcall DeleteAll( void) = 0;
+
+};
+
+
+struct IEnumWbemClassObject_IG : public IUnknown_IG
+{
+public:
+ virtual long __stdcall Reset( void) = 0;
+
+ virtual long __stdcall Next(
+ /* [in] */ long lTimeout,
+ /* [in] */ unsigned long uCount,
+ /* [length_is][size_is][out] */ IWbemClassObject_IG **apObjects,
+ /* [out] */ unsigned long *puReturned) = 0;
+
+ virtual long __stdcall NextAsync(
+ /* [in] */ unsigned long uCount,
+ /* [in] */ void *pSink) = 0;
+
+ virtual long __stdcall Clone(
+ /* [out] */ void **ppEnum) = 0;
+
+ virtual long __stdcall Skip(
+ /* [in] */ long lTimeout,
+ /* [in] */ unsigned long nCount) = 0;
+
+};
+
+struct IWbemServices_IG : public IUnknown_IG
+{
+public:
+ virtual long __stdcall OpenNamespace(
+ /* [in] */ const wchar_t * strNamespace,
+ /* [in] */ long lFlags,
+ /* [in] */ void *pCtx,
+ /* [unique][in][out] */ void **ppWorkingNamespace,
+ /* [unique][in][out] */ void **ppResult) = 0;
+
+ virtual long __stdcall CancelAsyncCall(
+ /* [in] */ void *pSink) = 0;
+
+ virtual long __stdcall QueryObjectSink(
+ /* [in] */ long lFlags,
+ /* [out] */ void **ppResponseHandler) = 0;
+
+ virtual long __stdcall GetObject(
+ /* [in] */ const wchar_t * strObjectPath,
+ /* [in] */ long lFlags,
+ /* [in] */ void *pCtx,
+ /* [unique][in][out] */ void **ppObject,
+ /* [unique][in][out] */ void **ppCallResult) = 0;
+
+ virtual long __stdcall GetObjectAsync(
+ /* [in] */ const wchar_t * strObjectPath,
+ /* [in] */ long lFlags,
+ /* [in] */ void *pCtx,
+ /* [in] */ void *pResponseHandler) = 0;
+
+ virtual long __stdcall PutClass(
+ /* [in] */ IWbemClassObject_IG *pObject,
+ /* [in] */ long lFlags,
+ /* [in] */ void *pCtx,
+ /* [unique][in][out] */ void **ppCallResult) = 0;
+
+ virtual long __stdcall PutClassAsync(
+ /* [in] */ IWbemClassObject_IG *pObject,
+ /* [in] */ long lFlags,
+ /* [in] */ void *pCtx,
+ /* [in] */ void *pResponseHandler) = 0;
+
+ virtual long __stdcall DeleteClass(
+ /* [in] */ const wchar_t * strClass,
+ /* [in] */ long lFlags,
+ /* [in] */ void *pCtx,
+ /* [unique][in][out] */ void **ppCallResult) = 0;
+
+ virtual long __stdcall DeleteClassAsync(
+ /* [in] */ const wchar_t * strClass,
+ /* [in] */ long lFlags,
+ /* [in] */ void *pCtx,
+ /* [in] */ void *pResponseHandler) = 0;
+
+ virtual long __stdcall CreateClassEnum(
+ /* [in] */ const wchar_t * strSuperclass,
+ /* [in] */ long lFlags,
+ /* [in] */ void *pCtx,
+ /* [out] */ void **ppEnum) = 0;
+
+ virtual long __stdcall CreateClassEnumAsync(
+ /* [in] */ const wchar_t * strSuperclass,
+ /* [in] */ long lFlags,
+ /* [in] */ void *pCtx,
+ /* [in] */ void *pResponseHandler) = 0;
+
+ virtual long __stdcall PutInstance(
+ /* [in] */ void *pInst,
+ /* [in] */ long lFlags,
+ /* [in] */ void *pCtx,
+ /* [unique][in][out] */ void **ppCallResult) = 0;
+
+ virtual long __stdcall PutInstanceAsync(
+ /* [in] */ void *pInst,
+ /* [in] */ long lFlags,
+ /* [in] */ void *pCtx,
+ /* [in] */ void *pResponseHandler) = 0;
+
+ virtual long __stdcall DeleteInstance(
+ /* [in] */ const wchar_t * strObjectPath,
+ /* [in] */ long lFlags,
+ /* [in] */ void *pCtx,
+ /* [unique][in][out] */ void **ppCallResult) = 0;
+
+ virtual long __stdcall DeleteInstanceAsync(
+ /* [in] */ const wchar_t * strObjectPath,
+ /* [in] */ long lFlags,
+ /* [in] */ void *pCtx,
+ /* [in] */ void *pResponseHandler) = 0;
+
+ virtual long __stdcall CreateInstanceEnum(
+ /* [in] */ const wchar_t * strFilter,
+ /* [in] */ long lFlags,
+ /* [in] */ void *pCtx,
+ /* [out] */ void **ppEnum) = 0;
+
+ virtual long __stdcall CreateInstanceEnumAsync(
+ /* [in] */ const wchar_t * strFilter,
+ /* [in] */ long lFlags,
+ /* [in] */ void *pCtx,
+ /* [in] */ void *pResponseHandler) = 0;
+
+ virtual long __stdcall ExecQuery(
+ /* [in] */ const wchar_t * strQueryLanguage,
+ /* [in] */ const wchar_t * strQuery,
+ /* [in] */ long lFlags,
+ /* [in] */ IWbemContext_IG *pCtx,
+ /* [out] */ IEnumWbemClassObject_IG **ppEnum) = 0;
+
+ virtual long __stdcall ExecQueryAsync(
+ /* [in] */ const wchar_t * strQueryLanguage,
+ /* [in] */ const wchar_t * strQuery,
+ /* [in] */ long lFlags,
+ /* [in] */ IWbemContext_IG *pCtx,
+ /* [in] */ void *pResponseHandler) = 0;
+
+ virtual long __stdcall ExecNotificationQuery(
+ /* [in] */ const wchar_t * strQueryLanguage,
+ /* [in] */ const wchar_t * strQuery,
+ /* [in] */ long lFlags,
+ /* [in] */ IWbemContext_IG *pCtx,
+ /* [out] */ void **ppEnum) = 0;
+
+ virtual long __stdcall ExecNotificationQueryAsync(
+ /* [in] */ const wchar_t * strQueryLanguage,
+ /* [in] */ const wchar_t * strQuery,
+ /* [in] */ long lFlags,
+ /* [in] */ IWbemContext_IG *pCtx,
+ /* [in] */ void *pResponseHandler) = 0;
+
+ virtual long __stdcall ExecMethod(
+ /* [in] */ const wchar_t * strObjectPath,
+ /* [in] */ const wchar_t * strMethodName,
+ /* [in] */ long lFlags,
+ /* [in] */ IWbemContext_IG *pCtx,
+ /* [in] */ IWbemClassObject_IG *pInParams,
+ /* [unique][in][out] */ IWbemClassObject_IG **ppOutParams,
+ /* [unique][in][out] */ void **ppCallResult) = 0;
+
+ virtual long __stdcall ExecMethodAsync(
+ /* [in] */ const wchar_t * strObjectPath,
+ /* [in] */ const wchar_t * strMethodName,
+ /* [in] */ long lFlags,
+ /* [in] */ IWbemContext_IG *pCtx,
+ /* [in] */ IWbemClassObject_IG *pInParams,
+ /* [in] */ void *pResponseHandler) = 0;
+
+};
+
+struct IWbemLocator_IG : public IUnknown_IG
+{
+public:
+ virtual long __stdcall ConnectServer(
+ /* [in] */ const wchar_t * strNetworkResource,
+ /* [in] */ const wchar_t * strUser,
+ /* [in] */ const wchar_t * strPassword,
+ /* [in] */ const wchar_t * strLocale,
+ /* [in] */ long lSecurityFlags,
+ /* [in] */ const wchar_t * strAuthority,
+ /* [in] */ void *pCtx,
+ /* [out] */ IWbemServices_IG **ppNamespace) = 0;
+
+};
+
+
+
struct interprocess_overlapped
{
unsigned long *internal;
@@ -393,6 +775,10 @@
//Some windows API declarations
extern "C" __declspec(dllimport) unsigned long __stdcall GetCurrentProcessId();
extern "C" __declspec(dllimport) unsigned long __stdcall GetCurrentThreadId();
+extern "C" __declspec(dllimport) int __stdcall GetProcessTimes
+ ( void *hProcess, interprocess_filetime* lpCreationTime
+ , interprocess_filetime *lpExitTime,interprocess_filetime *lpKernelTime
+ , interprocess_filetime *lpUserTime );
extern "C" __declspec(dllimport) void __stdcall Sleep(unsigned long);
extern "C" __declspec(dllimport) unsigned long __stdcall GetLastError();
extern "C" __declspec(dllimport) void * __stdcall GetCurrentProcess();
@@ -423,6 +809,7 @@
extern "C" __declspec(dllimport) int __stdcall MoveFileExA (const char *, const char *, unsigned long);
extern "C" __declspec(dllimport) void __stdcall GetSystemInfo (struct system_info *);
extern "C" __declspec(dllimport) int __stdcall FlushViewOfFile (void *, std::size_t);
+extern "C" __declspec(dllimport) int __stdcall FlushFileBuffers (void *);
extern "C" __declspec(dllimport) int __stdcall GetFileSizeEx (void *, __int64 *size);
extern "C" __declspec(dllimport) unsigned long __stdcall FormatMessageA
(unsigned long dwFlags, const void *lpSource, unsigned long dwMessageId,
@@ -450,6 +837,26 @@
extern "C" __declspec(dllimport) void *__stdcall GetFileInformationByHandle(void *, interprocess_by_handle_file_information*);
+//COM API
+extern "C" __declspec(dllimport) long __stdcall CoInitialize(void *pvReserved);
+extern "C" __declspec(dllimport) long __stdcall CoInitializeSecurity(
+ void* pSecDesc,
+ long cAuthSvc,
+ void *asAuthSvc,
+ void *pReserved1,
+ unsigned long dwAuthnLevel,
+ unsigned long dwImpLevel,
+ void *pAuthList,
+ unsigned long dwCapabilities,
+ void *pReserved3 );
+
+extern "C" __declspec(dllimport) long __stdcall VariantClear(wchar_variant * pvarg);
+extern "C" __declspec(dllimport) long __stdcall CoCreateInstance(const GUID_IG & rclsid, IUnknown_IG *pUnkOuter,
+ unsigned long dwClsContext, const GUID_IG & riid, void** ppv);
+extern "C" __declspec(dllimport) void __stdcall CoUninitialize(void);
+
+
+
//API function typedefs
//Pointer to functions
typedef long (__stdcall *NtDeleteFile_t)(object_attributes_t *ObjectAttributes);
@@ -475,10 +882,6 @@
} //namespace interprocess {
} //namespace boost {
-#else
-# include <windows.h>
-#endif //#if !defined( BOOST_USE_WINDOWS_H )
-
namespace boost {
namespace interprocess {
namespace winapi {
@@ -508,6 +911,12 @@
inline unsigned long get_current_thread_id()
{ return GetCurrentThreadId(); }
+inline bool get_process_times
+ ( void *hProcess, interprocess_filetime* lpCreationTime
+ , interprocess_filetime *lpExitTime, interprocess_filetime *lpKernelTime
+ , interprocess_filetime *lpUserTime )
+{ return 0 != GetProcessTimes(hProcess, lpCreationTime, lpExitTime, lpKernelTime, lpUserTime); }
+
inline unsigned long get_current_process_id()
{ return GetCurrentProcessId(); }
@@ -563,20 +972,33 @@
inline void *open_semaphore(const char *name)
{ return OpenSemaphoreA(semaphore_all_access, 1, name); }
-inline void * create_file_mapping (void * handle, unsigned long access, unsigned long high_size, unsigned long low_size, const char * name)
+class interprocess_all_access_security
{
interprocess_security_attributes sa;
interprocess_security_descriptor sd;
+ bool initialized;
- if(!InitializeSecurityDescriptor(&sd, security_descriptor_revision))
- return 0;
- if(!SetSecurityDescriptorDacl(&sd, true, 0, false))
- return 0;
- sa.lpSecurityDescriptor = &sd;
- sa.nLength = sizeof(interprocess_security_attributes);
- sa.bInheritHandle = false;
- return CreateFileMappingA (handle, &sa, access, high_size, low_size, name);
- //return CreateFileMappingA (handle, 0, access, high_size, low_size, name);
+ public:
+ interprocess_all_access_security()
+ : initialized(false)
+ {
+ if(!InitializeSecurityDescriptor(&sd, security_descriptor_revision))
+ return;
+ if(!SetSecurityDescriptorDacl(&sd, true, 0, false))
+ return;
+ sa.lpSecurityDescriptor = &sd;
+ sa.nLength = sizeof(interprocess_security_attributes);
+ sa.bInheritHandle = false;
+ initialized = false;
+ }
+
+ interprocess_security_attributes *get_attributes()
+ { return &sa; }
+};
+
+inline void * create_file_mapping (void * handle, unsigned long access, unsigned long high_size, unsigned long low_size, const char * name, interprocess_security_attributes *psec)
+{
+ return CreateFileMappingA (handle, psec, access, high_size, low_size, name);
}
inline void * open_file_mapping (unsigned long access, const char *name)
@@ -585,12 +1007,12 @@
inline void *map_view_of_file_ex(void *handle, unsigned long file_access, unsigned long highoffset, unsigned long lowoffset, std::size_t numbytes, void *base_addr)
{ return MapViewOfFileEx(handle, file_access, highoffset, lowoffset, numbytes, base_addr); }
-inline void *create_file(const char *name, unsigned long access, unsigned long creation_flags, unsigned long attributes = 0)
+inline void *create_file(const char *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,
file_share_read | file_share_write | file_share_delete,
- 0, creation_flags, attributes, 0);
+ psec, creation_flags, attributes, 0);
bool const invalid(invalid_handle_value == handle);
if (!invalid){
return handle;
@@ -612,14 +1034,20 @@
inline void get_system_info(system_info *info)
{ GetSystemInfo(info); }
-inline int flush_view_of_file(void *base_addr, std::size_t numbytes)
-{ return FlushViewOfFile(base_addr, numbytes); }
+inline bool flush_view_of_file(void *base_addr, std::size_t numbytes)
+{ return 0 != FlushViewOfFile(base_addr, numbytes); }
+
+inline bool flush_file_buffers(void *handle)
+{ return 0 != FlushFileBuffers(handle); }
inline bool get_file_size(void *handle, __int64 &size)
{ return 0 != GetFileSizeEx(handle, &size); }
-inline bool create_directory(const char *name, interprocess_security_attributes* security)
-{ return 0 != CreateDirectoryA(name, security); }
+inline bool create_directory(const char *name)
+{
+ interprocess_all_access_security sec;
+ return 0 != CreateDirectoryA(name, sec.get_attributes());
+}
inline bool remove_directory(const char *lpPathName)
{ return 0 != RemoveDirectoryA(lpPathName); }
@@ -728,7 +1156,7 @@
bool bSuccess = false;
// Create a file mapping object.
- void * hFileMap = create_file_mapping(hFile, page_readonly, 0, 1, 0);
+ void * hFileMap = create_file_mapping(hFile, page_readonly, 0, 1, 0, 0);
if(hFileMap)
{
// Create a file mapping to get the file name.
@@ -855,7 +1283,7 @@
//First step: Obtain a handle to the file using Win32 rules. This resolves relative paths
void *fh = create_file(filename, generic_read | delete_access, open_existing,
- file_flag_backup_semantics | file_flag_delete_on_close);
+ file_flag_backup_semantics | file_flag_delete_on_close, 0);
if(fh == invalid_handle_value){
return false;
}
@@ -972,6 +1400,174 @@
}
}
+
+inline void get_registry_value(const char *folder, const char *value_key, std::vector<unsigned char> &s)
+{
+ s.clear();
+ void *hAdvapi = load_library("Advapi32.dll");
+ if (hAdvapi){
+ library_unloader unloader(hAdvapi);
+ // Pointer to function RegOpenKeyA
+ RegOpenKeyEx_t pRegOpenKey =
+ (RegOpenKeyEx_t)get_proc_address(hAdvapi, "RegOpenKeyExA");
+ if (pRegOpenKey){
+ // Pointer to function RegCloseKey
+ RegCloseKey_t pRegCloseKey =
+ (RegCloseKey_t)get_proc_address(hAdvapi, "RegCloseKey");
+ if (pRegCloseKey){
+ // Pointer to function RegQueryValueA
+ RegQueryValueEx_t pRegQueryValue =
+ (RegQueryValueEx_t)get_proc_address(hAdvapi, "RegQueryValueExA");
+ if (pRegQueryValue){
+ //Open the key
+ void *key;
+ if ((*pRegOpenKey)( hkey_local_machine
+ , folder
+ , 0
+ , key_query_value
+ , &key) == 0){
+ reg_closer key_closer(pRegCloseKey, key);
+
+ //Obtain the value
+ unsigned long size;
+ unsigned long type;
+ const char *const reg_value = value_key;
+ long err = (*pRegQueryValue)( key, reg_value, 0, &type, 0, &size);
+ if(!err){
+ //Size includes terminating NULL
+ s.resize(size);
+ err = (*pRegQueryValue)( key, reg_value, 0, &type, (unsigned char*)(&s[0]), &size);
+ if(!err)
+ s.erase(s.end()-1);
+ (void)err;
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+inline bool get_wmi_class_attribute( std::wstring& strValue, const wchar_t *wmi_class, const wchar_t *wmi_class_var)
+{
+ CoInitialize(0);
+
+ bool bRet = false;
+
+ if( 0 == CoInitializeSecurity( 0, -1, 0, 0, RPC_C_AUTHN_LEVEL_PKT_IG, RPC_C_IMP_LEVEL_IMPERSONATE_IG, 0, EOAC_NONE_IG, 0 ) )
+ {
+ IWbemLocator_IG * pIWbemLocator = 0;
+
+ IWbemServices_IG * pWbemServices = 0;
+ IEnumWbemClassObject_IG * pEnumObject = 0;
+
+ const wchar_t * bstrNamespace = L"root\\cimv2";
+
+ if( 0 != CoCreateInstance(
+ CLSID_WbemAdministrativeLocator,
+ 0,
+ CLSCTX_INPROC_SERVER_IG | CLSCTX_LOCAL_SERVER_IG,
+ IID_IUnknown,
+ ( void ** )&pIWbemLocator
+ )
+ )
+ {
+ return false;
+ }
+
+ if( 0 != pIWbemLocator->ConnectServer(
+ bstrNamespace, // Namespace
+ 0, // Userid
+ 0, // PW
+ 0, // Locale
+ 0, // flags
+ 0, // Authority
+ 0, // Context
+ &pWbemServices
+ )
+ )
+ {
+ pIWbemLocator->Release();
+
+ return false;
+ }
+
+ strValue.clear();
+ strValue += L"Select ";
+ strValue += wmi_class_var;
+ strValue += L" from ";
+ strValue += wmi_class;
+
+ if ( 0 != pWbemServices->ExecQuery(
+ L"WQL",
+ strValue.c_str(),
+ WBEM_FLAG_RETURN_IMMEDIATELY_IG,
+ 0,
+ &pEnumObject
+ )
+ )
+ {
+ pIWbemLocator->Release();
+ pWbemServices->Release();
+
+ return false;
+ }
+
+ unsigned long uCount = 1, uReturned;
+ IWbemClassObject_IG * pClassObject = 0;
+
+ if ( 0 != pEnumObject->Reset() )
+ {
+ pIWbemLocator->Release();
+ pWbemServices->Release();
+ pEnumObject->Release();
+
+ return false;
+ }
+
+ wchar_variant vwchar;
+
+ while( 0 == pEnumObject->Next( WBEM_INFINITE_IG, uCount, &pClassObject, &uReturned ) )
+ {
+ if ( 0 == pClassObject->Get( L"LastBootUpTime", 0, &vwchar, 0, 0 ) )
+ {
+ bRet = true;
+ strValue = vwchar.value.pbstrVal;
+ VariantClear(&vwchar );
+ break;
+ }
+ }
+
+ pIWbemLocator->Release();
+ pWbemServices->Release();
+ pEnumObject->Release();
+ pClassObject->Release();
+ }
+
+ CoUninitialize();
+
+ return bRet;
+}
+
+inline bool get_last_bootup_time( std::wstring& strValue )
+{
+ bool ret = get_wmi_class_attribute(strValue, L"Win32_OperatingSystem", L"LastBootUpTime");
+ strValue.erase(strValue.find(L'+'));
+ return ret;
+}
+
+inline bool get_last_bootup_time( std::string& str )
+{
+ std::wstring wstr;
+ bool ret = get_last_bootup_time(wstr);
+ str.resize(wstr.size());
+ for(std::size_t i = 0, max = str.size(); i != max; ++i){
+ str[i] = '0' + (wstr[i]-L'0');
+ }
+ return ret;
+}
+
+
} //namespace winapi
} //namespace interprocess
} //namespace boost
Modified: trunk/boost/interprocess/detail/workaround.hpp
==============================================================================
--- trunk/boost/interprocess/detail/workaround.hpp (original)
+++ trunk/boost/interprocess/detail/workaround.hpp 2010-07-25 12:39:26 EDT (Sun, 25 Jul 2010)
@@ -115,7 +115,7 @@
#endif
-#if defined(BOOST_HAS_RVALUE_REFS) && defined(BOOST_HAS_VARIADIC_TMPL)\
+#if !defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_NO_VARIADIC_TEMPLATES)\
&& !defined(BOOST_INTERPROCESS_DISABLE_VARIADIC_TMPL)
#define BOOST_INTERPROCESS_PERFECT_FORWARDING
#endif
Modified: trunk/boost/interprocess/detail/xsi_shared_memory_device.hpp
==============================================================================
--- trunk/boost/interprocess/detail/xsi_shared_memory_device.hpp (original)
+++ trunk/boost/interprocess/detail/xsi_shared_memory_device.hpp 2010-07-25 12:39:26 EDT (Sun, 25 Jul 2010)
@@ -197,9 +197,11 @@
(mapped_region ®, xsi_named_mutex &mut, std::string &path)
{
const char *const filename = "xsi_shm_emulation_file";
+ permissions p;
+ p.set_unrestricted();
std::string xsi_shm_emulation_file_path;
- detail::create_tmp_dir_and_get_filename(filename, xsi_shm_emulation_file_path);
- detail::create_or_open_file(xsi_shm_emulation_file_path.c_str());
+ detail::create_tmp_and_clean_old_and_get_filename(filename, xsi_shm_emulation_file_path);
+ detail::create_or_open_file(xsi_shm_emulation_file_path.c_str(), read_write, p);
const std::size_t MemSize = sizeof(info_t);
xsi_shared_memory index_shm(open_or_create, xsi_shm_emulation_file_path.c_str(), 1, MemSize, 0666);
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk