File Coverage

Shared.xs
Criterion Covered Total %
statement 108 151 71.5
branch 105 252 41.6
condition n/a
subroutine n/a
pod n/a
total 213 403 52.8


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