1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
|
/*
* The MIT License
*
* Copyright (C) 2010-2017 Alexander Saprykin <saprykin.spb@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* 'Software'), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* @file pshmbuffer.h
* @brief Shared memory buffer
* @author Alexander Saprykin
*
* A shared memory buffer works like any other buffer but it is built upon a
* shared memory region instead of the process-only address space. Thus it
* inherits all the advantages and disadvantages of shared memory behavior. You
* should read about #PShm before using this buffer implementation to understand
* underlying restrictions.
*
* The shared memory buffer is process-wide and identified by its name across
* the system, thus it can be opened by any process if it knows its name. Use
* p_shm_buffer_new() to open the shared memory buffer and p_shm_buffer_free()
* to close it.
*
* All read/write operations are completely thread- and process-safe, which
* means that no other synchronization primitive is required, even for inter-
* process access. A #PShm locking mechanism is used for access synchronization.
*
* The buffer is cyclic and non-overridable which means that you wouldn't get
* buffer overflow and wouldn't override previously written data until reading
* it.
*
* The read operation checks whether there is any data available and reads it in
* case of successful check. After reading the data used space in the buffer is
* marked as free and any subsequent write operation may overwrite it. Thus you
* couldn't read the same data twice. The read operation is performed with the
* p_shm_buffer_read() call.
*
* The write operation checks whether there is enough free space available and
* writes a given memory block only if the buffer has enough free space.
* Otherwise no data is written. The write operation is performed with the
* p_shm_buffer_write() call.
*
* Data can be read and written into the buffer only sequentially. There is no
* way to access an arbitrary address inside the buffer.
*
* You can take ownership of the shared memory buffer with
* p_shm_buffer_take_ownership() to explicitly remove it from the system after
* closing. Please refer to the #PShm description to understand the intention of
* this action.
*/
#if !defined (PLIBSYS_H_INSIDE) && !defined (PLIBSYS_COMPILATION)
# error "Header files shouldn't be included directly, consider using <plibsys.h> instead."
#endif
#ifndef PLIBSYS_HEADER_PSHMBUFFER_H
#define PLIBSYS_HEADER_PSHMBUFFER_H
#include <ptypes.h>
#include <pmacros.h>
#include <perror.h>
P_BEGIN_DECLS
/** Shared memory buffer opaque data structure. */
typedef struct PShmBuffer_ PShmBuffer;
/**
* @brief Creates a new #PShmBuffer structure.
* @param name Unique buffer name.
* @param size Buffer size in bytes, can't be changed later.
* @param[out] error Error report object, NULL to ignore.
* @return Pointer to the #PShmBuffer structure in case of success, NULL
* otherwise.
* @since 0.0.1
*
* If a buffer with the same name already exists then the @a size will be
* ignored and the existing buffer will be returned.
*/
P_LIB_API PShmBuffer * p_shm_buffer_new (const pchar *name,
psize size,
PError **error);
/**
* @brief Frees #PShmBuffer structure.
* @param buf #PShmBuffer to free.
* @since 0.0.1
*
* Note that a buffer will be completely removed from the system only after the
* last instance of the buffer with the same name is closed.
*/
P_LIB_API void p_shm_buffer_free (PShmBuffer *buf);
/**
* @brief Takes ownership of a shared memory buffer.
* @param buf Shared memory buffer.
* @since 0.0.1
*
* If you take ownership of the shared memory buffer, p_shm_buffer_free() will
* try to completely unlink it and remove from the system. This is useful on
* UNIX systems, where shared memory can survive an application crash. On the
* Windows and OS/2 platforms this call has no effect.
*
* The common usage of this call is upon application startup to ensure that the
* memory segment from the previous crash can be removed from the system. To do
* that, call p_shm_buffer_new() and check if its condition is normal (used
* space, free space). If not, take ownership of the shared memory buffer object
* and remove it with the p_shm_buffer_free() call. After that, create it again.
*/
P_LIB_API void p_shm_buffer_take_ownership (PShmBuffer *buf);
/**
* @brief Tries to read data from a shared memory buffer.
* @param buf #PShmBuffer to read data from.
* @param[out] storage Output buffer to put data in.
* @param len Storage size in bytes.
* @param[out] error Error report object, NULL to ignore.
* @return Number of read bytes (can be 0 if buffer is empty), or -1 if error
* occured.
* @since 0.0.1
*/
P_LIB_API pint p_shm_buffer_read (PShmBuffer *buf,
ppointer storage,
psize len,
PError **error);
/**
* @brief Tries to write data into a shared memory buffer.
* @param buf #PShmBuffer to write data into.
* @param data Data to write.
* @param len Data size in bytes.
* @param[out] error Error report object, NULL to ignore.
* @return Number of written bytes (can be 0 if buffer is full), or -1 if error
* occured.
* @since 0.0.1
* @note Write operation is performed only if the buffer has enough space for
* the given data size.
*/
P_LIB_API pssize p_shm_buffer_write (PShmBuffer *buf,
ppointer data,
psize len,
PError **error);
/**
* @brief Gets free space in the shared memory buffer.
* @param buf #PShmBuffer to check space in.
* @param[out] error Error report object, NULL to ignore.
* @return Free space in bytes in case of success, -1 otherwise.
* @since 0.0.1
*/
P_LIB_API pssize p_shm_buffer_get_free_space (PShmBuffer *buf,
PError **error);
/**
* @brief Gets used space in the shared memory buffer.
* @param buf #PShmBuffer to check space in.
* @param[out] error Error report object, NULL to ignore.
* @return Used space in bytes in case of success, -1 otherwise.
* @since 0.0.1
*/
P_LIB_API pssize p_shm_buffer_get_used_space (PShmBuffer *buf,
PError **error);
/**
* @brief Clears all data in the buffer and fills it with zeros.
* @param buf #PShmBuffer to clear.
* @since 0.0.1
*/
P_LIB_API void p_shm_buffer_clear (PShmBuffer *buf);
P_END_DECLS
#endif /* PLIBSYS_HEADER_PSHMBUFFER_H */
|