//////////////////////////////////////////////////////////////////////////////
//
// (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
