mxlib
c++ tools for analyzing astronomical data and other tasks by Jared R. Males. [git repo]
sharedMemSegment.cpp
Go to the documentation of this file.
1 /** \file sharedMemSegment.cpp
2  * \author Jared R. Males (jaredmales@gmail.com)
3  * \brief Definitions for the mxlib shared memory facility
4  * \ingroup IPC_sharedmem
5  * \ingroup IPC
6  *
7 */
8 
9 //***********************************************************************//
10 // Copyright 2021 Jared R. Males (jaredmales@gmail.com)
11 //
12 // This file is part of mxlib.
13 //
14 // mxlib is free software: you can redistribute it and/or modify
15 // it under the terms of the GNU General Public License as published by
16 // the Free Software Foundation, either version 3 of the License, or
17 // (at your option) any later version.
18 //
19 // mxlib is distributed in the hope that it will be useful,
20 // but WITHOUT ANY WARRANTY; without even the implied warranty of
21 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 // GNU General Public License for more details.
23 //
24 // You should have received a copy of the GNU General Public License
25 // along with mxlib. If not, see <http://www.gnu.org/licenses/>.
26 //***********************************************************************//
27 
28 #include "ipc/sharedMemSegment.hpp"
29 
30 namespace mx
31 {
32 namespace ipc
33 {
34 
36 {
37  key_id = 0;
38  key = 0;
39  shmemid = 0;
40  addr = 0;
41  size = 0;
42 
43  attached = 0;
44 
45 }
46 
47 key_t sharedMemSegment::setKey( const char * path,
48  const int id
49  )
50 {
51  if(path != 0)
52  {
53  strncpy( key_path, path, MX_IPC_KEYLEN);
54  key_id = id;
55 
56  key = ftok( key_path, key_id);
57  }
58  else
59  {
60  key_path[0] = 0;
61  key_id = id;
62 
63  key = id;
64  }
65 
66  return key;
67 }
68 
69 int sharedMemSegment::create( size_t sz )
70 {
71  if( ( shmemid = shmget( key, sz + 1*sizeof(uintptr_t), IPC_CREAT | 0666))<0)
72  {
73  //If it failed, try to remove the shmem block and recreate it.
74  shmemid = shmget( key, 1, 0666);
75  if(shmctl( shmemid, IPC_RMID, 0) < 0)
76  {
77  fprintf(stderr, "Could not remove shared memory with key %i\n", key);
78  return -1;
79  }
80 
81  //removal successful, now try to create again
82  if(( shmemid = shmget( key, sz + 1*sizeof(uintptr_t), IPC_CREAT | 0666))<0)
83  {
84  fprintf(stderr, "Could not create shared memory with key %i\n", key);
85  return -1;
86  }
87  }
88 
89  attach( true );
90 
91  //Since we created this segment, we set the address field.
92  *((uintptr_t *) addr) = (uintptr_t) addr;
93 
94  return 0;
95 }
96 
97 int sharedMemSegment::attach( bool donot_set_addr)
98 {
99  struct shmid_ds shmstats;
100  void * new_addr;
101 
102  if( shmemid == 0 )
103  {
104  if(( shmemid = shmget(key, 0, 0666))<0)
105  {
106  fprintf(stderr, "Could not remove shared memory with key %i\n", key);
107  return -1;
108  }
109  }
110 
111  if ((new_addr = shmat( shmemid, 0, 0)) == (char *) -1)
112  {
113  fprintf(stderr, "Could not attach to shared memory with key %i\n", key);
114  return -1;
115  }
116 
117  attached = 1;
118 
119  if (shmctl( shmemid, IPC_STAT, &shmstats) < 0)
120  {
121  fprintf(stderr, "Could not get shared memory stats with key %i\n", key);
122  return -1;
123  }
124 
125  size = shmstats.shm_segsz;
126 
127 
128  //Here we first read in the address from the first unitptr_t size block
129  //then detach, then re-attach specifying the address.
130  if(!donot_set_addr)
131  {
132  addr = (void *) *((uintptr_t *) new_addr); //read the address from the segment itself
133 
134  //now detach
135  if(shmdt(new_addr) != 0)
136  {
137  fprintf(stderr, "Unable to detach from shared memory\n");
138  return -1;
139  }
140 
141  attached = 0;
142 
143  //and then re-attach, but now specifying an address
144  if ((new_addr = shmat(shmemid, addr, 0)) == (char *) -1)
145  {
146  fprintf(stderr, "Could not re-attach shared memory with key %i\n",key);
147  return -1;
148  }
149  }
150  else
151  {
152  addr = new_addr;
153  }
154 
155  attached = 1;
156 
157  return 0;
158 }
159 
161 {
162 
163  if(attached) return 0;
164 
165  if(addr == 0) return 0;
166 
167  //now detach
168  if(shmdt(addr) != 0)
169  {
170  fprintf(stderr, "Unable to detach from shared memory\n");
171  return -1;
172  }
173 
174  return 0;
175 }
176 
177 }//namespace ipc
178 }//namespace mx
void initialize()
Initialize the class.
int shmemid
The shared memory id associated with the key.
int create(size_t sz)
Create and attach to the segment.
int detach()
Detach from the segment.
int key_id
The id to use for key creation.
size_t size
The size of the segment.
int attach(bool donot_set_addr=false)
Attach to a segment without creating it.
void * addr
The base address of the segment.
key_t key
The shared memory key.
int attached
Flag indicating whether or not the segment is attached.
char key_path[MX_IPC_KEYLEN]
The path to use for key creation.
key_t setKey(const char *path, const int id)
Set the key.
The mxlib c++ namespace.
Definition: mxError.hpp:107
Declarations for the mxlib shared memory facility.