psem 0.0.1 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ext/psem/psem.c +90 -84
- metadata +4 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fb05a39b349b2b3112dd9ab2e60c22e703e5899fe68abb2d4dd9cf7bf4654b29
|
4
|
+
data.tar.gz: 22b83d7fc76a14a4f5a4ff19905cc2f6c29e7e8643213bf71421498a39e5ab55
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ab2c2bb09068189156f862ab56441a2f9cab4e4c91f3d7d0771fce57dd6fe425e2f1e2bb7cc336cba6665591637f9270744342b05ac51a775627a1c99175c120
|
7
|
+
data.tar.gz: d6294aecb54955fa5ca3bcdaccf72d500981e1c1305b00ef7b2df05b7b160cd51db92e702fd5eaec9f93b9cb78f07f6593a94ed0d3116bcbfb148396f72d4a3a
|
data/ext/psem/psem.c
CHANGED
@@ -5,17 +5,65 @@
|
|
5
5
|
#include <errno.h>
|
6
6
|
#include <time.h>
|
7
7
|
|
8
|
-
static inline sem_t* get_current_semaphore(VALUE self)
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
8
|
+
static inline sem_t* get_current_semaphore(VALUE self) {
|
9
|
+
sem_t* sem = (sem_t*)rb_ivar_get(self, rb_intern("inner"));
|
10
|
+
if (sem == NULL) {
|
11
|
+
rb_raise(rb_eRuntimeError, "inner semaphore is not initialized");
|
12
|
+
}
|
13
|
+
return sem;
|
14
|
+
}
|
15
|
+
|
16
|
+
#ifdef _WIN32
|
17
|
+
#error Windows not supported
|
18
|
+
#elif __APPLE__
|
19
|
+
// OSX has this deprecated and removed
|
20
|
+
VALUE psem_waitmillis(VALUE self, VALUE rbNum_timeoutMillis) {
|
21
|
+
rb_raise(rb_eRuntimeError, "sem_timedwait() is deprecated on OSX");
|
22
|
+
}
|
23
|
+
// they also broke sem_getvalue to return 0 no matter what on a path
|
24
|
+
// to deprecation
|
25
|
+
VALUE psem_get_value(VALUE self) {
|
26
|
+
rb_raise(rb_eRuntimeError, "sem_getvalue() is deprecated on OSX");
|
27
|
+
}
|
28
|
+
#else
|
29
|
+
VALUE psem_waitmillis(VALUE self, VALUE rbNum_timeoutMillis) {
|
30
|
+
Check_Type(rbNum_timeoutMillis, T_FIXNUM);
|
31
|
+
|
32
|
+
int ms = FIX2INT(rbNum_timeoutMillis);
|
33
|
+
struct timespec ts;
|
34
|
+
ts.tv_sec = ms / 1000;
|
35
|
+
ts.tv_nsec = (ms % 1000) * 1000000;
|
36
|
+
|
37
|
+
sem_t* sem = get_current_semaphore(self);
|
38
|
+
if (sem_timedwait(sem, &ts) == -1) {
|
39
|
+
int err = errno;
|
40
|
+
switch (err) {
|
41
|
+
case ETIMEDOUT:
|
42
|
+
return Qfalse;
|
43
|
+
case EINTR:
|
44
|
+
rb_raise(rb_eRuntimeError, "got interrupted by a signal handler (EINTR)");
|
45
|
+
break;
|
46
|
+
case EINVAL:
|
47
|
+
rb_raise(rb_eRuntimeError, "inner semaphore is not a valid semaphore (EINVAL)");
|
48
|
+
break;
|
49
|
+
default:
|
50
|
+
rb_raise(rb_eRuntimeError, "unknown errno: %d", err);
|
51
|
+
}
|
52
|
+
}
|
53
|
+
return Qtrue;
|
15
54
|
}
|
16
55
|
|
17
|
-
VALUE
|
18
|
-
|
56
|
+
VALUE psem_get_value(VALUE self) {
|
57
|
+
sem_t* sem = get_current_semaphore(self);
|
58
|
+
int val = 0xFFFF;
|
59
|
+
if (sem_getvalue(sem, &val) == -1) {
|
60
|
+
rb_raise(rb_eRuntimeError, "inner semaphore is not a valid semaphore, failed with errno: %d", errno);
|
61
|
+
}
|
62
|
+
return INT2NUM(val);
|
63
|
+
}
|
64
|
+
#endif
|
65
|
+
|
66
|
+
VALUE psem_unlink(VALUE self, VALUE rbStr_semName) {
|
19
67
|
Check_Type(rbStr_semName, T_STRING);
|
20
68
|
|
21
69
|
// Check length and format of semaphore name
|
@@ -46,8 +94,7 @@ VALUE psem_unlink(VALUE self, VALUE rbStr_semName)
|
|
46
94
|
return Qtrue;
|
47
95
|
}
|
48
96
|
|
49
|
-
VALUE psem_exists(VALUE self, VALUE rbStr_semName)
|
50
|
-
{
|
97
|
+
VALUE psem_exists(VALUE self, VALUE rbStr_semName) {
|
51
98
|
Check_Type(rbStr_semName, T_STRING);
|
52
99
|
|
53
100
|
// Check length and format of semaphore name
|
@@ -64,7 +111,8 @@ VALUE psem_exists(VALUE self, VALUE rbStr_semName)
|
|
64
111
|
return Qtrue;
|
65
112
|
}
|
66
113
|
else {
|
67
|
-
|
114
|
+
int err = errno;
|
115
|
+
switch (err) {
|
68
116
|
case ENOENT:
|
69
117
|
// Does not exist
|
70
118
|
return Qfalse;
|
@@ -73,20 +121,19 @@ VALUE psem_exists(VALUE self, VALUE rbStr_semName)
|
|
73
121
|
return Qtrue;
|
74
122
|
break;
|
75
123
|
case ENAMETOOLONG:
|
76
|
-
rb_raise(rb_eRuntimeError, "name was too long");
|
124
|
+
rb_raise(rb_eRuntimeError, "name was too long (ENAMETOOLONG)");
|
77
125
|
break;
|
78
126
|
case EINVAL:
|
79
|
-
rb_raise(rb_eRuntimeError, "
|
127
|
+
rb_raise(rb_eRuntimeError, "name consists only of / and nothing else (EINVAL)");
|
80
128
|
break;
|
81
129
|
default:
|
82
|
-
rb_raise(rb_eRuntimeError, "unknown
|
130
|
+
rb_raise(rb_eRuntimeError, "unknown errno: %d", err);
|
83
131
|
}
|
84
132
|
}
|
85
133
|
return Qnil;
|
86
134
|
}
|
87
135
|
|
88
|
-
VALUE psem_initialize(VALUE self, VALUE rbStr_semName, VALUE rbNum_initialValue)
|
89
|
-
{
|
136
|
+
VALUE psem_initialize(VALUE self, VALUE rbStr_semName, VALUE rbNum_initialValue) {
|
90
137
|
Check_Type(rbStr_semName, T_STRING);
|
91
138
|
Check_Type(rbNum_initialValue, T_FIXNUM);
|
92
139
|
|
@@ -108,9 +155,7 @@ VALUE psem_initialize(VALUE self, VALUE rbStr_semName, VALUE rbNum_initialValue)
|
|
108
155
|
// Create the semaphore
|
109
156
|
sem_t* sem = sem_open(sem_name, O_CREAT, strtol("0644", 0, 8), initialValue);
|
110
157
|
if (sem == SEM_FAILED) {
|
111
|
-
|
112
|
-
snprintf(buf, 64, "sem_open() failed with errno: %d", errno);
|
113
|
-
rb_raise(rb_eRuntimeError, buf);
|
158
|
+
rb_raise(rb_eRuntimeError, "sem_open() failed with errno: %d", errno);
|
114
159
|
}
|
115
160
|
|
116
161
|
// Set inner
|
@@ -118,123 +163,84 @@ VALUE psem_initialize(VALUE self, VALUE rbStr_semName, VALUE rbNum_initialValue)
|
|
118
163
|
return self;
|
119
164
|
}
|
120
165
|
|
121
|
-
VALUE
|
122
|
-
{
|
123
|
-
sem_t* sem = get_current_semaphore(self);
|
124
|
-
int val = 0xFFFF;
|
125
|
-
if (sem_getvalue(sem, &val) == -1) {
|
126
|
-
rb_raise(rb_eRuntimeError, "inner semaphore is not a valid semaphore");
|
127
|
-
}
|
128
|
-
return INT2NUM(val);
|
129
|
-
}
|
130
|
-
|
131
|
-
VALUE psem_post(VALUE self)
|
132
|
-
{
|
166
|
+
VALUE psem_post(VALUE self) {
|
133
167
|
sem_t* sem = get_current_semaphore(self);
|
134
168
|
if (sem_post(sem) == -1) {
|
135
|
-
|
169
|
+
int err = errno;
|
170
|
+
switch (err) {
|
136
171
|
case EINVAL:
|
137
|
-
rb_raise(rb_eRuntimeError, "inner semaphore is not a valid semaphore");
|
172
|
+
rb_raise(rb_eRuntimeError, "inner semaphore is not a valid semaphore (EINVAL)");
|
138
173
|
break;
|
139
174
|
case EOVERFLOW:
|
140
|
-
rb_raise(rb_eRuntimeError, "maximum allowable value for a semaphore would be exceeded");
|
175
|
+
rb_raise(rb_eRuntimeError, "maximum allowable value for a semaphore would be exceeded (EOVERFLOW)");
|
141
176
|
break;
|
142
177
|
default:
|
143
|
-
rb_raise(rb_eRuntimeError, "unknown
|
178
|
+
rb_raise(rb_eRuntimeError, "unknown errno: %d", err);
|
144
179
|
}
|
145
180
|
}
|
146
181
|
return Qnil;
|
147
182
|
}
|
148
183
|
|
149
|
-
VALUE psem_wait(VALUE self)
|
150
|
-
{
|
184
|
+
VALUE psem_wait(VALUE self) {
|
151
185
|
sem_t* sem = get_current_semaphore(self);
|
152
186
|
if (sem_wait(sem) == -1) {
|
153
|
-
|
187
|
+
int err = errno;
|
188
|
+
switch (err) {
|
154
189
|
case EINTR:
|
155
|
-
rb_raise(rb_eRuntimeError, "got interrupted by a signal handler");
|
190
|
+
rb_raise(rb_eRuntimeError, "got interrupted by a signal handler (EINTR)");
|
156
191
|
break;
|
157
192
|
case EINVAL:
|
158
|
-
rb_raise(rb_eRuntimeError, "inner semaphore is not a valid semaphore");
|
193
|
+
rb_raise(rb_eRuntimeError, "inner semaphore is not a valid semaphore (EINVAL)");
|
159
194
|
break;
|
160
195
|
default:
|
161
|
-
rb_raise(rb_eRuntimeError, "unknown
|
196
|
+
rb_raise(rb_eRuntimeError, "unknown errno: %d", err);
|
162
197
|
}
|
163
198
|
}
|
164
199
|
return Qtrue;
|
165
200
|
}
|
166
201
|
|
167
|
-
VALUE psem_trywait(VALUE self)
|
168
|
-
{
|
202
|
+
VALUE psem_trywait(VALUE self) {
|
169
203
|
sem_t* sem = get_current_semaphore(self);
|
170
204
|
if (sem_trywait(sem) == -1) {
|
171
|
-
|
205
|
+
int err = errno;
|
206
|
+
switch (err) {
|
172
207
|
case EAGAIN:
|
173
208
|
return Qfalse;
|
174
209
|
case EINTR:
|
175
|
-
rb_raise(rb_eRuntimeError, "got interrupted by a signal handler");
|
176
|
-
break;
|
177
|
-
case EINVAL:
|
178
|
-
rb_raise(rb_eRuntimeError, "inner semaphore is not a valid semaphore");
|
179
|
-
break;
|
180
|
-
default:
|
181
|
-
rb_raise(rb_eRuntimeError, "unknown error");
|
182
|
-
}
|
183
|
-
}
|
184
|
-
return Qtrue;
|
185
|
-
}
|
186
|
-
|
187
|
-
VALUE psem_waitmillis(VALUE self, VALUE rbNum_timeoutMillis)
|
188
|
-
{
|
189
|
-
Check_Type(rbNum_timeoutMillis, T_FIXNUM);
|
190
|
-
|
191
|
-
int ms = FIX2INT(rbNum_timeoutMillis);
|
192
|
-
struct timespec ts;
|
193
|
-
ts.tv_sec = ms / 1000;
|
194
|
-
ts.tv_nsec = (ms % 1000) * 1000000;
|
195
|
-
|
196
|
-
sem_t* sem = get_current_semaphore(self);
|
197
|
-
if (sem_timedwait(sem, &ts) == -1) {
|
198
|
-
switch (errno) {
|
199
|
-
case ETIMEDOUT:
|
200
|
-
return Qfalse;
|
201
|
-
case EINTR:
|
202
|
-
rb_raise(rb_eRuntimeError, "got interrupted by a signal handler");
|
210
|
+
rb_raise(rb_eRuntimeError, "got interrupted by a signal handler (EINTR)");
|
203
211
|
break;
|
204
212
|
case EINVAL:
|
205
|
-
rb_raise(rb_eRuntimeError, "inner semaphore is not a valid semaphore");
|
213
|
+
rb_raise(rb_eRuntimeError, "inner semaphore is not a valid semaphore (EINVAL)");
|
206
214
|
break;
|
207
215
|
default:
|
208
|
-
rb_raise(rb_eRuntimeError, "unknown
|
216
|
+
rb_raise(rb_eRuntimeError, "unknown errno: %d", err);
|
209
217
|
}
|
210
218
|
}
|
211
219
|
return Qtrue;
|
212
220
|
}
|
213
221
|
|
214
|
-
VALUE psem_close(VALUE self)
|
215
|
-
{
|
222
|
+
VALUE psem_close(VALUE self) {
|
216
223
|
sem_t* sem = get_current_semaphore(self);
|
217
224
|
if (sem_close(sem) == -1) {
|
218
|
-
|
225
|
+
int err = errno;
|
226
|
+
switch (err) {
|
219
227
|
case EINVAL:
|
220
|
-
rb_raise(rb_eRuntimeError, "inner semaphore is not a valid semaphore");
|
228
|
+
rb_raise(rb_eRuntimeError, "inner semaphore is not a valid semaphore (EINVAL)");
|
221
229
|
break;
|
222
230
|
default:
|
223
|
-
rb_raise(rb_eRuntimeError, "unknown
|
231
|
+
rb_raise(rb_eRuntimeError, "unknown errno: %d", err);
|
224
232
|
}
|
225
233
|
}
|
226
234
|
return Qnil;
|
227
235
|
}
|
228
236
|
|
229
|
-
VALUE psem_get_inner(VALUE self)
|
230
|
-
{
|
237
|
+
VALUE psem_get_inner(VALUE self) {
|
231
238
|
// Get inner as size_t type. Primarily for debugging purposes.
|
232
239
|
size_t cast = (size_t)rb_ivar_get(self, rb_intern("inner"));
|
233
240
|
return INT2NUM(cast);
|
234
241
|
}
|
235
242
|
|
236
|
-
void Init_psem()
|
237
|
-
{
|
243
|
+
void Init_psem() {
|
238
244
|
VALUE psemClass = rb_define_class("PSem", rb_cObject);
|
239
245
|
|
240
246
|
// Initialize (does not change the value of the semaphore if it already exists
|
metadata
CHANGED
@@ -1,19 +1,17 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: psem
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Can Selcik
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-02-
|
11
|
+
date: 2019-02-13 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
|
-
description:
|
14
|
-
|
15
|
-
|
16
|
-
The sem_open function creates a new named semaphore or opens an existing named semaphore. After the semaphore has been opened, it can be operated on using sem_post and sem_wait. When a process has finished using the semaphore, it can use sem_close to close the semaphore. When all processes have finished using the semaphore, it can be removed from the system using sem_unlink.
|
13
|
+
description: Supports named semaphores both on Linux and OSX. "get_value" and "timedwait"
|
14
|
+
is deprecated on OSX but everything else is functional and safe.
|
17
15
|
email: selcik.can@gmail.com
|
18
16
|
executables: []
|
19
17
|
extensions:
|