File Coverage

Shared.xs
Criterion Covered Total %
statement 108 149 72.4
branch 105 244 43.0
condition n/a
subroutine n/a
pod n/a
total 213 393 54.2


line stmt bran cond sub pod time code
1             #define PERL_NO_GET_CONTEXT
2             #include "EXTERN.h"
3             #include "perl.h"
4             #include "XSUB.h"
5             #include "ppport.h"
6             #include "stack.h"
7              
8             #define EXTRACT_STK(sv) \
9             if (!sv_isobject(sv) || !sv_derived_from(sv, "Data::Stack::Shared")) \
10             croak("Expected a Data::Stack::Shared object"); \
11             StkHandle *h = INT2PTR(StkHandle*, SvIV(SvRV(sv))); \
12             if (!h) croak("Attempted to use a destroyed Data::Stack::Shared object")
13              
14             #define MAKE_OBJ(class, handle) \
15             SV *obj = newSViv(PTR2IV(handle)); \
16             SV *ref = newRV_noinc(obj); \
17             sv_bless(ref, gv_stashpv(class, GV_ADD)); \
18             RETVAL = ref
19              
20              
21              
22             MODULE = Data::Stack::Shared PACKAGE = Data::Stack::Shared
23              
24             PROTOTYPES: DISABLE
25              
26             void
27             DESTROY(self)
28             SV *self
29             CODE:
30 10 50         if (!SvROK(self)) return;
31 10           StkHandle *h = INT2PTR(StkHandle*, SvIV(SvRV(self)));
32 10 50         if (!h) return;
33 10           sv_setiv(SvRV(self), 0);
34 10           stk_destroy(h);
35              
36             UV
37             size(self)
38             SV *self
39             PREINIT:
40 6 50         EXTRACT_STK(self);
    50          
    50          
41             CODE:
42 6 50         RETVAL = stk_size(h);
43             OUTPUT:
44             RETVAL
45              
46             UV
47             capacity(self)
48             SV *self
49             PREINIT:
50 2 50         EXTRACT_STK(self);
    50          
    50          
51             CODE:
52 2 50         RETVAL = (UV)h->hdr->capacity;
53             OUTPUT:
54             RETVAL
55              
56             bool
57             is_empty(self)
58             SV *self
59             PREINIT:
60 3 50         EXTRACT_STK(self);
    50          
    50          
61             CODE:
62 3 50         RETVAL = stk_size(h) == 0;
63             OUTPUT:
64             RETVAL
65              
66             bool
67             is_full(self)
68             SV *self
69             PREINIT:
70 1 50         EXTRACT_STK(self);
    50          
    50          
71             CODE:
72 1 50         RETVAL = stk_size(h) >= (UV)h->hdr->capacity;
73             OUTPUT:
74             RETVAL
75              
76             void
77             clear(self)
78             SV *self
79             PREINIT:
80 3 50         EXTRACT_STK(self);
    50          
    50          
81             CODE:
82 3           stk_clear(h);
83              
84             SV *
85             path(self)
86             SV *self
87             PREINIT:
88 1 50         EXTRACT_STK(self);
    50          
    50          
89             CODE:
90 1 50         RETVAL = h->path ? newSVpv(h->path, 0) : &PL_sv_undef;
91             OUTPUT:
92             RETVAL
93              
94             IV
95             memfd(self)
96             SV *self
97             PREINIT:
98 1 50         EXTRACT_STK(self);
    50          
    50          
99             CODE:
100 1 50         RETVAL = h->backing_fd;
101             OUTPUT:
102             RETVAL
103              
104             IV
105             eventfd(self)
106             SV *self
107             PREINIT:
108 1 50         EXTRACT_STK(self);
    50          
    50          
109             CODE:
110 1 50         RETVAL = stk_create_eventfd(h);
111             OUTPUT:
112             RETVAL
113              
114             void
115             eventfd_set(self, fd)
116             SV *self
117             int fd
118             PREINIT:
119 0 0         EXTRACT_STK(self);
    0          
    0          
120             CODE:
121 0 0         if (h->notify_fd >= 0 && h->notify_fd != fd) close(h->notify_fd);
    0          
122 0           h->notify_fd = fd;
123              
124             IV
125             fileno(self)
126             SV *self
127             PREINIT:
128 2 50         EXTRACT_STK(self);
    50          
    50          
129             CODE:
130 2 50         RETVAL = h->notify_fd;
131             OUTPUT:
132             RETVAL
133              
134             bool
135             notify(self)
136             SV *self
137             PREINIT:
138 2 50         EXTRACT_STK(self);
    50          
    50          
139             CODE:
140 2 50         RETVAL = stk_notify(h);
141             OUTPUT:
142             RETVAL
143              
144             SV *
145             eventfd_consume(self)
146             SV *self
147             PREINIT:
148 1 50         EXTRACT_STK(self);
    50          
    50          
149             CODE:
150 1           int64_t v = stk_eventfd_consume(h);
151 1 50         RETVAL = (v >= 0) ? newSViv((IV)v) : &PL_sv_undef;
152             OUTPUT:
153             RETVAL
154              
155             void
156             sync(self)
157             SV *self
158             PREINIT:
159 1 50         EXTRACT_STK(self);
    50          
    50          
160             CODE:
161 1           stk_msync(h);
162              
163             void
164             unlink(self_or_class, ...)
165             SV *self_or_class
166             CODE:
167             const char *p;
168 1 50         if (sv_isobject(self_or_class)) {
169 1           StkHandle *h = INT2PTR(StkHandle*, SvIV(SvRV(self_or_class)));
170 1 50         if (!h) croak("destroyed object");
171 1           p = h->path;
172             } else {
173 0 0         if (items < 2) croak("Usage: ...->unlink($path)");
174 0           p = SvPV_nolen(ST(1));
175             }
176 1 50         if (!p) croak("cannot unlink anonymous or memfd object");
177 1 50         if (unlink(p) != 0) croak("unlink(%s): %s", p, strerror(errno));
178              
179             SV *
180             stats(self)
181             SV *self
182             PREINIT:
183 2 50         EXTRACT_STK(self);
    50          
    50          
184             CODE:
185 2           HV *hv = newHV();
186 2           StkHeader *hdr = h->hdr;
187 2           hv_store(hv, "size", 4, newSVuv(stk_size(h)), 0);
188 2           hv_store(hv, "capacity", 8, newSVuv((UV)hdr->capacity), 0);
189 2           hv_store(hv, "pushes", 6, newSVuv((UV)hdr->stat_pushes), 0);
190 2           hv_store(hv, "pops", 4, newSVuv((UV)hdr->stat_pops), 0);
191 2           hv_store(hv, "waits", 5, newSVuv((UV)hdr->stat_waits), 0);
192 2           hv_store(hv, "timeouts", 8, newSVuv((UV)hdr->stat_timeouts), 0);
193 2           hv_store(hv, "mmap_size", 9, newSVuv((UV)h->mmap_size), 0);
194 2           RETVAL = newRV_noinc((SV *)hv);
195             OUTPUT:
196             RETVAL
197              
198              
199              
200             MODULE = Data::Stack::Shared PACKAGE = Data::Stack::Shared::Int
201              
202             PROTOTYPES: DISABLE
203              
204             SV *
205             new(class, path, capacity)
206             const char *class
207             SV *path
208             UV capacity
209             PREINIT:
210             char errbuf[STK_ERR_BUFLEN];
211             CODE:
212 5 100         const char *p = SvOK(path) ? SvPV_nolen(path) : NULL;
213 5           StkHandle *h = stk_create(p, capacity, sizeof(int64_t), STK_VAR_INT, errbuf);
214 5 50         if (!h) croak("Data::Stack::Shared::Int->new: %s", errbuf);
215 5           MAKE_OBJ(class, h);
216             OUTPUT:
217             RETVAL
218              
219             SV *
220             new_memfd(class, name, capacity)
221             const char *class
222             const char *name
223             UV capacity
224             PREINIT:
225             char errbuf[STK_ERR_BUFLEN];
226             CODE:
227 1           StkHandle *h = stk_create_memfd(name, capacity, sizeof(int64_t), STK_VAR_INT, errbuf);
228 1 50         if (!h) croak("Data::Stack::Shared::Int->new_memfd: %s", errbuf);
229 1           MAKE_OBJ(class, h);
230             OUTPUT:
231             RETVAL
232              
233             SV *
234             new_from_fd(class, fd)
235             const char *class
236             int fd
237             PREINIT:
238             char errbuf[STK_ERR_BUFLEN];
239             CODE:
240 1           StkHandle *h = stk_open_fd(fd, STK_VAR_INT, errbuf);
241 1 50         if (!h) croak("Data::Stack::Shared::Int->new_from_fd: %s", errbuf);
242 1           MAKE_OBJ(class, h);
243             OUTPUT:
244             RETVAL
245              
246             bool
247             push(self, val)
248             SV *self
249             IV val
250             PREINIT:
251 35 50         EXTRACT_STK(self);
    50          
    50          
252             CODE:
253 35           int64_t v = (int64_t)val;
254 35 100         RETVAL = stk_try_push(h, &v, sizeof(v));
255             OUTPUT:
256             RETVAL
257              
258             bool
259             push_wait(self, val, ...)
260             SV *self
261             IV val
262             PREINIT:
263 1 50         EXTRACT_STK(self);
    50          
    50          
264 1           double timeout = -1;
265             CODE:
266 1 50         if (items > 2) timeout = SvNV(ST(2));
267 1           int64_t v = (int64_t)val;
268 1 50         RETVAL = stk_push(h, &v, sizeof(v), timeout);
269             OUTPUT:
270             RETVAL
271              
272             SV *
273             pop(self)
274             SV *self
275             PREINIT:
276 18 50         EXTRACT_STK(self);
    50          
    50          
277             CODE:
278             int64_t v;
279 18 100         RETVAL = stk_try_pop(h, &v) ? newSViv((IV)v) : &PL_sv_undef;
280             OUTPUT:
281             RETVAL
282              
283             SV *
284             pop_wait(self, ...)
285             SV *self
286             PREINIT:
287 2 50         EXTRACT_STK(self);
    50          
    50          
288 2           double timeout = -1;
289             CODE:
290 2 50         if (items > 1) timeout = SvNV(ST(1));
291             int64_t v;
292 2 100         RETVAL = stk_pop(h, &v, timeout) ? newSViv((IV)v) : &PL_sv_undef;
293             OUTPUT:
294             RETVAL
295              
296             SV *
297             peek(self)
298             SV *self
299             PREINIT:
300 1 50         EXTRACT_STK(self);
    50          
    50          
301             CODE:
302             int64_t v;
303 1 50         RETVAL = stk_peek(h, &v) ? newSViv((IV)v) : &PL_sv_undef;
304             OUTPUT:
305             RETVAL
306              
307              
308              
309             MODULE = Data::Stack::Shared PACKAGE = Data::Stack::Shared::Str
310              
311             PROTOTYPES: DISABLE
312              
313             SV *
314             new(class, path, capacity, max_len)
315             const char *class
316             SV *path
317             UV capacity
318             UV max_len
319             PREINIT:
320             char errbuf[STK_ERR_BUFLEN];
321             CODE:
322 3 50         if (max_len == 0) croak("max_len must be > 0");
323 3 50         if (max_len > (UV)(UINT32_MAX - sizeof(uint32_t)))
324 0           croak("max_len too large");
325 3           uint32_t elem_size = (uint32_t)(sizeof(uint32_t) + max_len);
326 3 50         const char *p = SvOK(path) ? SvPV_nolen(path) : NULL;
327 3           StkHandle *h = stk_create(p, capacity, elem_size, STK_VAR_STR, errbuf);
328 3 50         if (!h) croak("Data::Stack::Shared::Str->new: %s", errbuf);
329 3           MAKE_OBJ(class, h);
330             OUTPUT:
331             RETVAL
332              
333             SV *
334             new_memfd(class, name, capacity, max_len)
335             const char *class
336             const char *name
337             UV capacity
338             UV max_len
339             PREINIT:
340             char errbuf[STK_ERR_BUFLEN];
341             CODE:
342 0 0         if (max_len == 0) croak("max_len must be > 0");
343 0 0         if (max_len > (UV)(UINT32_MAX - sizeof(uint32_t)))
344 0           croak("max_len too large");
345 0           uint32_t elem_size = (uint32_t)(sizeof(uint32_t) + max_len);
346 0           StkHandle *h = stk_create_memfd(name, capacity, elem_size, STK_VAR_STR, errbuf);
347 0 0         if (!h) croak("Data::Stack::Shared::Str->new_memfd: %s", errbuf);
348 0           MAKE_OBJ(class, h);
349             OUTPUT:
350             RETVAL
351              
352             SV *
353             new_from_fd(class, fd)
354             const char *class
355             int fd
356             PREINIT:
357             char errbuf[STK_ERR_BUFLEN];
358             CODE:
359 0           StkHandle *h = stk_open_fd(fd, STK_VAR_STR, errbuf);
360 0 0         if (!h) croak("Data::Stack::Shared::Str->new_from_fd: %s", errbuf);
361 0           MAKE_OBJ(class, h);
362             OUTPUT:
363             RETVAL
364              
365             bool
366             push(self, val)
367             SV *self
368             SV *val
369             PREINIT:
370 6 50         EXTRACT_STK(self);
    50          
    50          
371             CODE:
372             STRLEN slen;
373 6           const char *s = SvPV(val, slen);
374 6           uint32_t max_len = h->elem_size - sizeof(uint32_t);
375 6 50         if (slen > max_len) slen = max_len;
376             uint8_t *buf;
377 6           Newx(buf, h->elem_size, uint8_t);
378 6           uint32_t l32 = (uint32_t)slen;
379 6           memcpy(buf, &l32, sizeof(uint32_t));
380 6           memcpy(buf + sizeof(uint32_t), s, slen);
381 6 50         if (slen < max_len) memset(buf + sizeof(uint32_t) + slen, 0, max_len - slen);
382 6           RETVAL = stk_try_push(h, buf, h->elem_size);
383 6           Safefree(buf);
384             OUTPUT:
385             RETVAL
386              
387             bool
388             push_wait(self, val, ...)
389             SV *self
390             SV *val
391             PREINIT:
392 0 0         EXTRACT_STK(self);
    0          
    0          
393 0           double timeout = -1;
394             CODE:
395 0 0         if (items > 2) timeout = SvNV(ST(2));
396             STRLEN slen;
397 0           const char *s = SvPV(val, slen);
398 0           uint32_t max_len = h->elem_size - sizeof(uint32_t);
399 0 0         if (slen > max_len) slen = max_len;
400             uint8_t *buf;
401 0           Newx(buf, h->elem_size, uint8_t);
402 0           uint32_t l32 = (uint32_t)slen;
403 0           memcpy(buf, &l32, sizeof(uint32_t));
404 0           memcpy(buf + sizeof(uint32_t), s, slen);
405 0 0         if (slen < max_len) memset(buf + sizeof(uint32_t) + slen, 0, max_len - slen);
406 0           RETVAL = stk_push(h, buf, h->elem_size, timeout);
407 0           Safefree(buf);
408             OUTPUT:
409             RETVAL
410              
411             SV *
412             pop(self)
413             SV *self
414             PREINIT:
415 5 50         EXTRACT_STK(self);
    50          
    50          
416             CODE:
417             uint8_t *buf;
418 5           Newx(buf, h->elem_size, uint8_t);
419 5 100         if (stk_try_pop(h, buf)) {
420             uint32_t len;
421 4           memcpy(&len, buf, sizeof(uint32_t));
422 4           uint32_t max_len = h->elem_size - sizeof(uint32_t);
423 4 50         if (len > max_len) len = max_len;
424 4           RETVAL = newSVpvn((char *)buf + sizeof(uint32_t), len);
425             } else {
426 1           RETVAL = &PL_sv_undef;
427             }
428 5           Safefree(buf);
429             OUTPUT:
430             RETVAL
431              
432             SV *
433             pop_wait(self, ...)
434             SV *self
435             PREINIT:
436 0 0         EXTRACT_STK(self);
    0          
    0          
437 0           double timeout = -1;
438             CODE:
439 0 0         if (items > 1) timeout = SvNV(ST(1));
440             uint8_t *buf;
441 0           Newx(buf, h->elem_size, uint8_t);
442 0 0         if (stk_pop(h, buf, timeout)) {
443             uint32_t len;
444 0           memcpy(&len, buf, sizeof(uint32_t));
445 0           uint32_t max_len = h->elem_size - sizeof(uint32_t);
446 0 0         if (len > max_len) len = max_len;
447 0           RETVAL = newSVpvn((char *)buf + sizeof(uint32_t), len);
448             } else {
449 0           RETVAL = &PL_sv_undef;
450             }
451 0           Safefree(buf);
452             OUTPUT:
453             RETVAL
454              
455             SV *
456             peek(self)
457             SV *self
458             PREINIT:
459 1 50         EXTRACT_STK(self);
    50          
    50          
460             CODE:
461             uint8_t *buf;
462 1           Newx(buf, h->elem_size, uint8_t);
463 1 50         if (stk_peek(h, buf)) {
464             uint32_t len;
465 1           memcpy(&len, buf, sizeof(uint32_t));
466 1           uint32_t max_len = h->elem_size - sizeof(uint32_t);
467 1 50         if (len > max_len) len = max_len;
468 1           RETVAL = newSVpvn((char *)buf + sizeof(uint32_t), len);
469             } else {
470 0           RETVAL = &PL_sv_undef;
471             }
472 1           Safefree(buf);
473             OUTPUT:
474             RETVAL