Chris@16: ////////////////////////////////////////////////////////////////////////////// Chris@16: // Chris@16: // (C) Copyright Ion Gaztanaga 2009-2012. Distributed under the Boost Chris@16: // Software License, Version 1.0. (See accompanying file Chris@16: // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: // Chris@16: // See http://www.boost.org/libs/interprocess for documentation. Chris@16: // Chris@16: ////////////////////////////////////////////////////////////////////////////// Chris@16: Chris@16: #ifndef BOOST_INTERPROCESS_XSI_XSI_NAMED_MUTEX_HPP Chris@16: #define BOOST_INTERPROCESS_XSI_XSI_NAMED_MUTEX_HPP Chris@16: Chris@101: #ifndef BOOST_CONFIG_HPP Chris@101: # include Chris@101: #endif Chris@101: # Chris@101: #if defined(BOOST_HAS_PRAGMA_ONCE) Chris@101: # pragma once Chris@101: #endif Chris@101: Chris@16: #include Chris@16: #include Chris@16: Chris@16: #if defined(BOOST_INTERPROCESS_WINDOWS) Chris@16: #error "This header can't be used in Windows operating systems" Chris@16: #endif Chris@16: Chris@101: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@101: #include Chris@101: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@101: Chris@16: Chris@16: //!\file Chris@16: //!Describes a class representing a xsi-based named_mutex. Chris@16: Chris@16: namespace boost { Chris@16: namespace interprocess { Chris@16: Chris@16: //!A class that wraps a XSI (System V)-based named semaphore Chris@16: //!that undoes the operation if the process crashes. Chris@16: class xsi_named_mutex Chris@16: { Chris@101: #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) Chris@16: //Non-copyable and non-assignable Chris@16: xsi_named_mutex(xsi_named_mutex &); Chris@16: xsi_named_mutex &operator=(xsi_named_mutex &); Chris@101: #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED Chris@16: Chris@16: public: Chris@16: BOOST_MOVABLE_BUT_NOT_COPYABLE(xsi_named_mutex) Chris@16: Chris@16: //!Default constructor. Chris@16: //!Represents an empty xsi_named_mutex. Chris@16: xsi_named_mutex(); Chris@16: Chris@16: //!Tries to create a new XSI-based named mutex with a key obtained from a call to ftok (with path Chris@16: //!"path" and id "id"), and permissions "perm". Chris@16: //!If the named mutex previously exists, it tries to open it. Chris@16: //!Otherwise throws an error. Chris@16: xsi_named_mutex(open_or_create_t, const char *path, boost::uint8_t id, int perm = 0666) Chris@16: { this->priv_open_or_create(ipcdetail::DoOpenOrCreate, path, id, perm); } Chris@16: Chris@16: //!Moves the ownership of "moved"'s named mutex to *this. Chris@16: //!After the call, "moved" does not represent any named mutex Chris@16: //!Does not throw Chris@16: xsi_named_mutex(BOOST_RV_REF(xsi_named_mutex) moved) Chris@16: { this->swap(moved); } Chris@16: Chris@16: //!Moves the ownership of "moved"'s named mutex to *this. Chris@16: //!After the call, "moved" does not represent any named mutex. Chris@16: //!Does not throw Chris@16: xsi_named_mutex &operator=(BOOST_RV_REF(xsi_named_mutex) moved) Chris@16: { Chris@16: xsi_named_mutex tmp(boost::move(moved)); Chris@16: this->swap(tmp); Chris@16: return *this; Chris@16: } Chris@16: Chris@16: //!Swaps two xsi_named_mutex. Does not throw Chris@16: void swap(xsi_named_mutex &other); Chris@16: Chris@16: //!Destroys *this. The named mutex is still valid after Chris@16: //!destruction. use remove() to destroy the named mutex. Chris@16: ~xsi_named_mutex(); Chris@16: Chris@16: //!Returns the path used to construct the Chris@16: //!named mutex. Chris@16: const char *get_path() const; Chris@16: Chris@16: //!Returns access Chris@16: //!permissions Chris@16: int get_permissions() const; Chris@16: Chris@16: //!Returns the mapping handle. Chris@16: //!Never throws Chris@16: mapping_handle_t get_mapping_handle() const; Chris@16: Chris@16: //!Erases a XSI-based named mutex from the system. Chris@16: //!Returns false on error. Never throws Chris@16: bool remove(); Chris@16: Chris@16: void lock(); Chris@16: Chris@16: void unlock(); Chris@16: Chris@101: #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) Chris@16: private: Chris@16: Chris@16: //!Closes a previously opened file mapping. Never throws. Chris@16: void priv_close(); Chris@16: Chris@16: //!Closes a previously opened file mapping. Never throws. Chris@16: bool priv_open_or_create( ipcdetail::create_enum_t type Chris@16: , const char *path Chris@16: , boost::uint8_t id Chris@16: , int perm); Chris@16: int m_semid; Chris@16: key_t m_key; Chris@16: boost::uint8_t m_id; Chris@16: int m_perm; Chris@16: std::string m_path; Chris@101: #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED Chris@16: }; Chris@16: Chris@101: #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) Chris@16: Chris@16: inline xsi_named_mutex::xsi_named_mutex() Chris@16: : m_semid(-1), m_key(-1), m_id(0), m_perm(0), m_path() Chris@16: {} Chris@16: Chris@16: inline xsi_named_mutex::~xsi_named_mutex() Chris@16: { this->priv_close(); } Chris@16: Chris@16: inline const char *xsi_named_mutex::get_path() const Chris@16: { return m_path.c_str(); } Chris@16: Chris@16: inline void xsi_named_mutex::swap(xsi_named_mutex &other) Chris@16: { Chris@101: (simple_swap)(m_key, other.m_key); Chris@101: (simple_swap)(m_id, other.m_id); Chris@101: (simple_swap)(m_semid, other.m_semid); Chris@101: (simple_swap)(m_perm, other.m_perm); Chris@16: m_path.swap(other.m_path); Chris@16: } Chris@16: Chris@16: inline mapping_handle_t xsi_named_mutex::get_mapping_handle() const Chris@16: { mapping_handle_t mhnd = { m_semid, true}; return mhnd; } Chris@16: Chris@16: inline int xsi_named_mutex::get_permissions() const Chris@16: { return m_perm; } Chris@16: Chris@16: inline bool xsi_named_mutex::priv_open_or_create Chris@16: (ipcdetail::create_enum_t type, const char *path, boost::uint8_t id, int perm) Chris@16: { Chris@16: key_t key; Chris@16: if(path){ Chris@16: key = ::ftok(path, id); Chris@16: if(((key_t)-1) == key){ Chris@16: error_info err = system_error_code(); Chris@16: throw interprocess_exception(err); Chris@16: } Chris@16: } Chris@16: else{ Chris@16: key = IPC_PRIVATE; Chris@16: } Chris@16: Chris@16: perm &= 0x01FF; Chris@16: Chris@16: int semid; Chris@16: if(!xsi::simple_sem_open_or_create(key, 1, semid, perm)){ Chris@16: error_info err = system_error_code(); Chris@16: throw interprocess_exception(err); Chris@16: } Chris@16: Chris@16: m_perm = perm; Chris@16: m_semid = semid; Chris@16: m_path = path ? path : ""; Chris@16: m_id = id; Chris@16: m_key = key; Chris@16: Chris@16: return true; Chris@16: } Chris@16: Chris@16: inline void xsi_named_mutex::priv_close() Chris@16: { Chris@16: } Chris@16: Chris@16: inline void xsi_named_mutex::lock() Chris@16: { Chris@16: if(!xsi::simple_sem_op(m_semid, -1)){ Chris@16: error_info err = system_error_code(); Chris@16: throw interprocess_exception(err); Chris@16: } Chris@16: } Chris@16: Chris@16: inline void xsi_named_mutex::unlock() Chris@16: { Chris@16: bool success = xsi::simple_sem_op(m_semid, 1); Chris@16: (void)success; Chris@16: BOOST_ASSERT(success); Chris@16: } Chris@16: Chris@16: inline bool xsi_named_mutex::remove() Chris@16: { Chris@16: if(m_semid != -1){ Chris@16: int ret = ::semctl(m_semid, IPC_RMID, 0); Chris@16: if(-1 == ret) Chris@16: return false; Chris@16: //Now put it in default-constructed state Chris@16: m_semid = -1; Chris@16: m_key = -1; Chris@16: m_id = 0; Chris@16: m_perm = 0; Chris@16: m_path.clear(); Chris@16: } Chris@16: return false; Chris@16: } Chris@16: Chris@101: #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED Chris@16: Chris@16: } //namespace interprocess { Chris@16: } //namespace boost { Chris@16: Chris@16: #include Chris@16: Chris@16: #endif //BOOST_INTERPROCESS_XSI_XSI_NAMED_MUTEX_HPP