1 #include "SharedMemoryServer.h"
5 #include <machine/byte_order.h>
8 SharedMemoryServer::SharedMemoryServer (const char* segmentName
, SegmentOffsetType segmentSize
) :
9 mSegmentName (segmentName
), mSegmentSize (segmentSize
)
12 int segmentDescriptor
= shm_open (segmentName
, O_RDWR
| O_CREAT
, S_IRWXU
| S_IRGRP
| S_IROTH
);
13 if (segmentDescriptor
< 0)
18 // set the segment size
19 ftruncate (segmentDescriptor
, segmentSize
);
22 mSegment
= (u_int8_t
*) mmap (NULL
, mSegmentSize
, PROT_READ
| PROT_WRITE
, MAP_SHARED
, segmentDescriptor
, 0);
23 close (segmentDescriptor
);
25 if (mSegment
== (u_int8_t
*) -1) // can't map the memory?
28 shm_unlink (segmentName
);
36 SharedMemoryServer::~SharedMemoryServer ()
45 munmap (mSegment
, mSegmentSize
);
47 // mark the segment for deletion
48 shm_unlink (mSegmentName
.c_str ());
53 const SegmentOffsetType
55 kDomainOffset
= kSegmentLength
+ sizeof (SegmentOffsetType
),
56 kEventTypeOffset
= kDomainOffset
+ sizeof (SegmentOffsetType
),
57 kHeaderLength
= kEventTypeOffset
+ sizeof (SegmentOffsetType
);
59 void SharedMemoryServer::WriteMessage (SegmentOffsetType domain
, SegmentOffsetType event
, const void *message
, SegmentOffsetType messageLength
)
61 // get the current producer count
62 SegmentOffsetType pCount
= GetProducerCount ();
64 SegmentOffsetType actualLength
= messageLength
+ kHeaderLength
;
66 // for now, write a 0 for the length -- this will give clients the opportunity to not process an
68 WriteOffsetAtOffset (pCount
, 0);
70 // extend the overall write count by enough data to hold the message length and message
71 SetProducerCount (pCount
+ actualLength
);
74 WriteDataAtOffset (pCount
+ kHeaderLength
, message
, messageLength
);
77 WriteOffsetAtOffset (pCount
+ kDomainOffset
, domain
);
79 // write the event type
80 WriteOffsetAtOffset (pCount
+ kEventTypeOffset
, event
);
82 // write the data count
83 WriteOffsetAtOffset (pCount
, actualLength
);
88 const char* SharedMemoryServer::GetSegmentName ()
90 return mSegmentName
.c_str ();
95 size_t SharedMemoryServer::GetSegmentSize ()
102 SegmentOffsetType
SharedMemoryServer::GetProducerCount ()
104 // the data is stored in the buffer in network byte order
105 u_int32_t pCount
= *(u_int32_t
*) mSegment
;
106 return OSSwapHostToBigInt32 (pCount
);
111 void SharedMemoryServer::SetProducerCount (SegmentOffsetType producerCount
)
113 *((u_int32_t
*) mSegment
) = OSSwapHostToBigInt32 (producerCount
);
118 void SharedMemoryServer::WriteOffsetAtOffset (SegmentOffsetType offset
, SegmentOffsetType data
)
120 // convert data to network byte order
122 *((u_int32_t
*) buffer
) = OSSwapHostToBigInt32 (data
);
124 WriteDataAtOffset (offset
, buffer
, sizeof (buffer
));
129 void SharedMemoryServer::WriteDataAtOffset (SegmentOffsetType offset
, const void* data
, SegmentOffsetType length
)
131 // figure out where in the buffer we actually need to write the data
132 SegmentOffsetType realOffset
= offset
% kPoolAvailableForData
;
134 // figure out how many bytes we can write without overflowing the buffer
135 SegmentOffsetType bytesToEnd
= kPoolAvailableForData
- realOffset
;
137 // figure out how many bytes we can write
138 SegmentOffsetType bytesToWrite
= bytesToEnd
< length
? bytesToEnd
: length
;
140 // move the first part of the data, making sure to skip the producer pointer
141 memmove (mSegment
+ sizeof (SegmentOffsetType
) + realOffset
, data
, bytesToWrite
);
143 // deduct the bytes just written
144 length
-= bytesToWrite
;
146 if (length
!= 0) // did we wrap around?
148 memmove (mSegment
+ sizeof (SegmentOffsetType
), ((u_int8_t
*) data
) + bytesToWrite
, length
);