////////////////////////////////////////////////////////////////////////////// | |
// | |
// (C) Copyright Ion Gaztanaga 2009. Distributed under the 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_XSI_XSI_NAMED_MUTEX_HPP | |
#define BOOST_INTERPROCESS_XSI_XSI_NAMED_MUTEX_HPP | |
#include <boost/interprocess/detail/config_begin.hpp> | |
#include <boost/interprocess/detail/workaround.hpp> | |
#if defined(BOOST_INTERPROCESS_WINDOWS) | |
#error "This header can't be used in Windows operating systems" | |
#endif | |
#include <boost/interprocess/detail/move.hpp> | |
#include <boost/interprocess/creation_tags.hpp> | |
#include <boost/interprocess/exceptions.hpp> | |
#include <boost/interprocess/detail/utilities.hpp> | |
#include <boost/interprocess/detail/os_file_functions.hpp> | |
#include <boost/interprocess/interprocess_fwd.hpp> | |
#include <boost/interprocess/exceptions.hpp> | |
#include <boost/interprocess/sync/xsi/basic_xsi_semaphore.hpp> | |
#include <cstddef> | |
#include <boost/assert.hpp> | |
#include <boost/cstdint.hpp> | |
#include <string> | |
#include <boost/assert.hpp> | |
//!\file | |
//!Describes a class representing a xsi-based named_mutex. | |
namespace boost { | |
namespace interprocess { | |
//!A class that wraps a XSI (System V)-based named semaphore | |
//!that undoes the operation if the process crashes. | |
class xsi_named_mutex | |
{ | |
/// @cond | |
//Non-copyable and non-assignable | |
xsi_named_mutex(xsi_named_mutex &); | |
xsi_named_mutex &operator=(xsi_named_mutex &); | |
/// @endcond | |
public: | |
BOOST_INTERPROCESS_MOVABLE_BUT_NOT_COPYABLE(xsi_named_mutex) | |
//!Default constructor. | |
//!Represents an empty xsi_named_mutex. | |
xsi_named_mutex(); | |
//!Tries to create a new XSI-based named mutex with a key obtained from a call to ftok (with path | |
//!"path" and id "id"), and permissions "perm". | |
//!If the named mutex previously exists, it tries to open it. | |
//!Otherwise throws an error. | |
xsi_named_mutex(open_or_create_t, const char *path, boost::uint8_t id, int perm = 0666) | |
{ this->priv_open_or_create(detail::DoOpenOrCreate, path, id, perm); } | |
//!Moves the ownership of "moved"'s named mutex to *this. | |
//!After the call, "moved" does not represent any named mutex | |
//!Does not throw | |
xsi_named_mutex(BOOST_INTERPROCESS_RV_REF(xsi_named_mutex) moved) | |
{ this->swap(moved); } | |
//!Moves the ownership of "moved"'s named mutex to *this. | |
//!After the call, "moved" does not represent any named mutex. | |
//!Does not throw | |
xsi_named_mutex &operator=(BOOST_INTERPROCESS_RV_REF(xsi_named_mutex) moved) | |
{ | |
xsi_named_mutex tmp(boost::interprocess::move(moved)); | |
this->swap(tmp); | |
return *this; | |
} | |
//!Swaps two xsi_named_mutex. Does not throw | |
void swap(xsi_named_mutex &other); | |
//!Destroys *this. The named mutex is still valid after | |
//!destruction. use remove() to destroy the named mutex. | |
~xsi_named_mutex(); | |
//!Returns the path used to construct the | |
//!named mutex. | |
const char *get_path() const; | |
//!Returns access | |
//!permissions | |
int get_permissions() const; | |
//!Returns the mapping handle. | |
//!Never throws | |
mapping_handle_t get_mapping_handle() const; | |
//!Erases a XSI-based named mutex from the system. | |
//!Returns false on error. Never throws | |
bool remove(); | |
void lock(); | |
void unlock(); | |
/// @cond | |
private: | |
//!Closes a previously opened file mapping. Never throws. | |
void priv_close(); | |
//!Closes a previously opened file mapping. Never throws. | |
bool priv_open_or_create( detail::create_enum_t type | |
, const char *path | |
, boost::uint8_t id | |
, int perm); | |
int m_semid; | |
key_t m_key; | |
boost::uint8_t m_id; | |
int m_perm; | |
std::string m_path; | |
/// @endcond | |
}; | |
/// @cond | |
inline xsi_named_mutex::xsi_named_mutex() | |
: m_semid(-1), m_key(-1), m_id(0), m_perm(0), m_path() | |
{} | |
inline xsi_named_mutex::~xsi_named_mutex() | |
{ this->priv_close(); } | |
inline const char *xsi_named_mutex::get_path() const | |
{ return m_path.c_str(); } | |
inline void xsi_named_mutex::swap(xsi_named_mutex &other) | |
{ | |
std::swap(m_key, other.m_key); | |
std::swap(m_id, other.m_id); | |
std::swap(m_semid, other.m_semid); | |
std::swap(m_perm, other.m_perm); | |
m_path.swap(other.m_path); | |
} | |
inline mapping_handle_t xsi_named_mutex::get_mapping_handle() const | |
{ mapping_handle_t mhnd = { m_semid, true}; return mhnd; } | |
inline int xsi_named_mutex::get_permissions() const | |
{ return m_perm; } | |
inline bool xsi_named_mutex::priv_open_or_create | |
(detail::create_enum_t type, const char *path, boost::uint8_t id, int perm) | |
{ | |
key_t key; | |
if(path){ | |
key = ::ftok(path, id); | |
if(((key_t)-1) == key){ | |
error_info err = system_error_code(); | |
throw interprocess_exception(err); | |
} | |
} | |
else{ | |
key = IPC_PRIVATE; | |
} | |
perm &= 0x01FF; | |
int semid; | |
if(!xsi::simple_sem_open_or_create(key, 1, semid, perm)){ | |
error_info err = system_error_code(); | |
throw interprocess_exception(err); | |
} | |
m_perm = perm; | |
m_semid = semid; | |
m_path = path ? path : ""; | |
m_id = id; | |
m_key = key; | |
return true; | |
} | |
inline void xsi_named_mutex::priv_close() | |
{ | |
} | |
inline void xsi_named_mutex::lock() | |
{ | |
if(!xsi::simple_sem_op(m_semid, -1)){ | |
error_info err = system_error_code(); | |
throw interprocess_exception(err); | |
} | |
} | |
inline void xsi_named_mutex::unlock() | |
{ | |
bool success = xsi::simple_sem_op(m_semid, 1); | |
(void)success; | |
BOOST_ASSERT(success); | |
} | |
inline bool xsi_named_mutex::remove() | |
{ | |
if(m_semid != -1){ | |
int ret = ::semctl(m_semid, IPC_RMID, 0); | |
if(-1 == ret) | |
return false; | |
//Now put it in default-constructed state | |
m_semid = -1; | |
m_key = -1; | |
m_id = 0; | |
m_perm = 0; | |
m_path.clear(); | |
} | |
return false; | |
} | |
///@endcond | |
} //namespace interprocess { | |
} //namespace boost { | |
#include <boost/interprocess/detail/config_end.hpp> | |
#endif //BOOST_INTERPROCESS_XSI_XSI_NAMED_MUTEX_HPP |