libshevek
|
00001 /* shm.hh - shared memory 00002 * Copyright 2007 Bas Wijnen <wijnen@debian.org> 00003 * 00004 * This program is free software: you can redistribute it and/or modify 00005 * it under the terms of the GNU General Public License as published by 00006 * the Free Software Foundation, either version 3 of the License, or 00007 * (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00016 */ 00017 00018 #ifndef SHEVEK_SHM_HH 00019 #define SHEVEK_SHM_HH 00020 00021 #include "refbase.hh" 00022 #include "error.hh" 00023 #include <string> 00024 #include <typeinfo> 00025 #include <sys/mman.h> 00026 #include <sys/stat.h> 00027 #include <fcntl.h> 00028 #include <unistd.h> 00029 00030 namespace shevek 00031 { 00033 template <typename T> class shm : public refbase 00034 { 00035 shm (std::string const &name, bool l_create, bool writable, bool keep); 00036 ~shm (); 00037 T *m_data; 00038 std::string m_name; 00039 int m_fd; 00040 bool m_destroy; 00041 public: 00043 00045 static Glib::RefPtr <shm <T> > create (std::string const &name, bool keep = false) { return Glib::RefPtr <shm <T> > (new shm (name, true, true, keep)); } 00047 static Glib::RefPtr <shm <T> > open (std::string const &name, bool writable = true) { return Glib::RefPtr <shm <T> > (new shm (name, false, writable, true)); } 00049 T *data () { return m_data; } 00051 T const *data () const { return m_data; } 00052 }; 00053 00054 template <typename T> shm <T>::shm (std::string const &name, bool l_create, bool writable, bool keep) 00055 { 00056 m_destroy = !keep; 00057 m_name = std::string ("/") + typeid (T).name () + '-' + name; 00058 m_fd = shm_open (m_name.c_str (), l_create ? O_CREAT | O_EXCL | O_RDWR : writable ? O_RDWR : O_RDONLY, 0666); 00059 if (m_fd < 0) 00060 { 00061 shevek_error_errno ("unable to open shared memory file " + m_name); 00062 throw "unable to open shared memory file"; 00063 } 00064 if (l_create && ftruncate (m_fd, sizeof (T)) < 0) 00065 { 00066 shevek_error_errno ("unable to set size of shared memory file " + m_name); 00067 throw "unable to set size of shared memory file"; 00068 } 00069 m_data = reinterpret_cast <T *> (mmap (NULL, sizeof (T), writable ? PROT_READ | PROT_WRITE : PROT_READ, MAP_SHARED, m_fd, 0)); 00070 if (!m_data) 00071 { 00072 shevek_error_errno ("unable to map shared memory file " + m_name); 00073 throw "unable to map shared memory"; 00074 } 00075 } 00076 00077 template <typename T> shm <T>::~shm () 00078 { 00079 close (m_fd); 00080 munmap (m_data, sizeof (T)); 00081 if (m_destroy) 00082 shm_unlink (m_name.c_str ()); 00083 } 00084 } 00085 00086 #endif