• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //////////////////////////////////////////////////////////////////////////////
2 //
3 // (C) Copyright Ion Gaztanaga 2009-2012. Distributed under the Boost
4 // Software License, Version 1.0. (See accompanying file
5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // See http://www.boost.org/libs/interprocess for documentation.
8 //
9 //////////////////////////////////////////////////////////////////////////////
10 
11 #ifndef BOOST_INTERPROCESS_XSI_SHARED_MEMORY_HPP
12 #define BOOST_INTERPROCESS_XSI_SHARED_MEMORY_HPP
13 
14 #ifndef BOOST_CONFIG_HPP
15 #  include <boost/config.hpp>
16 #endif
17 #
18 #if defined(BOOST_HAS_PRAGMA_ONCE)
19 #  pragma once
20 #endif
21 
22 #include <boost/interprocess/detail/config_begin.hpp>
23 #include <boost/interprocess/detail/workaround.hpp>
24 
25 #if !defined(BOOST_INTERPROCESS_XSI_SHARED_MEMORY_OBJECTS)
26 #error "This header can't be used in operating systems without XSI (System V) shared memory support"
27 #endif
28 
29 #include <boost/interprocess/creation_tags.hpp>
30 #include <boost/interprocess/exceptions.hpp>
31 #include <boost/interprocess/detail/utilities.hpp>
32 
33 #include <boost/interprocess/detail/os_file_functions.hpp>
34 #include <boost/interprocess/interprocess_fwd.hpp>
35 #include <boost/interprocess/exceptions.hpp>
36 #include <boost/interprocess/xsi_key.hpp>
37 #include <boost/interprocess/permissions.hpp>
38 #include <boost/interprocess/detail/simple_swap.hpp>
39 // move
40 #include <boost/move/utility_core.hpp>
41 // other boost
42 #include <boost/cstdint.hpp>
43 // std
44 #include <cstddef>
45 // OS
46 #include <sys/shm.h>
47 
48 
49 //!\file
50 //!Describes a class representing a native xsi shared memory.
51 
52 namespace boost {
53 namespace interprocess {
54 
55 //!A class that wraps XSI (System V) shared memory.
56 //!Unlike shared_memory_object, xsi_shared_memory needs a valid
57 //!xsi_key to identify a shared memory object.
58 //!
59 //!Warning: XSI shared memory and interprocess portable
60 //!shared memory (boost::interprocess::shared_memory_object)
61 //!can't communicate between them.
62 class xsi_shared_memory
63 {
64    #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
65    //Non-copyable and non-assignable
66    BOOST_MOVABLE_BUT_NOT_COPYABLE(xsi_shared_memory)
67    #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
68 
69    public:
70    //!Default constructor.
71    //!Represents an empty xsi_shared_memory.
72    xsi_shared_memory();
73 
74    //!Initializes *this with a shmid previously obtained (possibly from another process)
75    //!This lower-level initializer allows shared memory mapping without having a key.
xsi_shared_memory(open_only_t,int shmid)76    xsi_shared_memory(open_only_t, int shmid)
77       : m_shmid (shmid)
78    {}
79 
80    //!Creates a new XSI shared memory from 'key', with size "size" and permissions "perm".
81    //!If the shared memory previously exists, throws an error.
xsi_shared_memory(create_only_t,const xsi_key & key,std::size_t size,const permissions & perm=permissions ())82    xsi_shared_memory(create_only_t, const xsi_key &key, std::size_t size, const permissions& perm = permissions())
83    {  this->priv_open_or_create(ipcdetail::DoCreate, key, perm, size);  }
84 
85    //!Opens an existing shared memory with identifier 'key' or creates a new XSI shared memory from
86    //!identifier 'key', with size "size" and permissions "perm".
xsi_shared_memory(open_or_create_t,const xsi_key & key,std::size_t size,const permissions & perm=permissions ())87    xsi_shared_memory(open_or_create_t, const xsi_key &key, std::size_t size, const permissions& perm = permissions())
88    {  this->priv_open_or_create(ipcdetail::DoOpenOrCreate, key, perm, size);  }
89 
90    //!Tries to open a XSI shared memory with identifier 'key'
91    //!If the shared memory does not previously exist, it throws an error.
xsi_shared_memory(open_only_t,const xsi_key & key)92    xsi_shared_memory(open_only_t, const xsi_key &key)
93    {  this->priv_open_or_create(ipcdetail::DoOpen, key, permissions(), 0);  }
94 
95    //!Moves the ownership of "moved"'s shared memory object to *this.
96    //!After the call, "moved" does not represent any shared memory object.
97    //!Does not throw
xsi_shared_memory(BOOST_RV_REF (xsi_shared_memory)moved)98    xsi_shared_memory(BOOST_RV_REF(xsi_shared_memory) moved)
99       : m_shmid(-1)
100    {  this->swap(moved);   }
101 
102    //!Moves the ownership of "moved"'s shared memory to *this.
103    //!After the call, "moved" does not represent any shared memory.
104    //!Does not throw
operator =(BOOST_RV_REF (xsi_shared_memory)moved)105    xsi_shared_memory &operator=(BOOST_RV_REF(xsi_shared_memory) moved)
106    {
107       xsi_shared_memory tmp(boost::move(moved));
108       this->swap(tmp);
109       return *this;
110    }
111 
112    //!Swaps two xsi_shared_memorys. Does not throw
113    void swap(xsi_shared_memory &other);
114 
115    //!Destroys *this. The shared memory won't be destroyed, just
116    //!this connection to it. Use remove() to destroy the shared memory.
117    ~xsi_shared_memory();
118 
119    //!Returns the shared memory ID that
120    //!identifies the shared memory
121    int get_shmid() const;
122 
123    //!Returns the mapping handle.
124    //!Never throws
125    mapping_handle_t get_mapping_handle() const;
126 
127    //!Erases the XSI shared memory object identified by shmid
128    //!from the system.
129    //!Returns false on error. Never throws
130    static bool remove(int shmid);
131 
132    #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
133    private:
134 
135    //!Closes a previously opened file mapping. Never throws.
136    bool priv_open_or_create( ipcdetail::create_enum_t type
137                            , const xsi_key &key
138                            , const permissions& perm
139                            , std::size_t size);
140    int            m_shmid;
141    #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
142 };
143 
144 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
145 
xsi_shared_memory()146 inline xsi_shared_memory::xsi_shared_memory()
147    :  m_shmid(-1)
148 {}
149 
~xsi_shared_memory()150 inline xsi_shared_memory::~xsi_shared_memory()
151 {}
152 
get_shmid() const153 inline int xsi_shared_memory::get_shmid() const
154 {  return m_shmid; }
155 
swap(xsi_shared_memory & other)156 inline void xsi_shared_memory::swap(xsi_shared_memory &other)
157 {
158    (simple_swap)(m_shmid, other.m_shmid);
159 }
160 
get_mapping_handle() const161 inline mapping_handle_t xsi_shared_memory::get_mapping_handle() const
162 {  mapping_handle_t mhnd = { m_shmid, true};   return mhnd;   }
163 
priv_open_or_create(ipcdetail::create_enum_t type,const xsi_key & key,const permissions & permissions,std::size_t size)164 inline bool xsi_shared_memory::priv_open_or_create
165    (ipcdetail::create_enum_t type, const xsi_key &key, const permissions& permissions, std::size_t size)
166 {
167    int perm = permissions.get_permissions();
168    perm &= 0x01FF;
169    int shmflg = perm;
170 
171    switch(type){
172       case ipcdetail::DoOpen:
173          shmflg |= 0;
174       break;
175       case ipcdetail::DoCreate:
176          shmflg |= IPC_CREAT | IPC_EXCL;
177       break;
178       case ipcdetail::DoOpenOrCreate:
179          shmflg |= IPC_CREAT;
180       break;
181       default:
182          {
183             error_info err = other_error;
184             throw interprocess_exception(err);
185          }
186    }
187 
188    int ret = ::shmget(key.get_key(), size, shmflg);
189    int shmid = ret;
190    if((type == ipcdetail::DoOpen) && (-1 != ret)){
191       //Now get the size
192       ::shmid_ds xsi_ds;
193       ret = ::shmctl(ret, IPC_STAT, &xsi_ds);
194       size = xsi_ds.shm_segsz;
195    }
196    if(-1 == ret){
197       error_info err = system_error_code();
198       throw interprocess_exception(err);
199    }
200 
201    m_shmid = shmid;
202    return true;
203 }
204 
remove(int shmid)205 inline bool xsi_shared_memory::remove(int shmid)
206 {  return -1 != ::shmctl(shmid, IPC_RMID, 0); }
207 
208 #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
209 
210 }  //namespace interprocess {
211 }  //namespace boost {
212 
213 #include <boost/interprocess/detail/config_end.hpp>
214 
215 #endif   //BOOST_INTERPROCESS_XSI_SHARED_MEMORY_HPP
216