File Coverage

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