File Coverage

Shared.xs
Criterion Covered Total %
statement 137 196 69.9
branch 141 308 45.7
condition n/a
subroutine n/a
pod n/a
total 278 504 55.1


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 "deque.h"
7              
8             #define EXTRACT_DEQ(sv) \
9             if (!sv_isobject(sv) || !sv_derived_from(sv, "Data::Deque::Shared")) \
10             croak("Expected a Data::Deque::Shared object"); \
11             DeqHandle *h = INT2PTR(DeqHandle*, SvIV(SvRV(sv))); \
12             if (!h) croak("Attempted to use a destroyed Data::Deque::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             MODULE = Data::Deque::Shared PACKAGE = Data::Deque::Shared
21              
22             PROTOTYPES: DISABLE
23              
24             void
25             DESTROY(self)
26             SV *self
27             CODE:
28 20 50         if (!SvROK(self)) return;
29 20           DeqHandle *h = INT2PTR(DeqHandle*, SvIV(SvRV(self)));
30 20 50         if (!h) return;
31 20           sv_setiv(SvRV(self), 0);
32 20           deq_destroy(h);
33              
34             UV
35             size(self)
36             SV *self
37             PREINIT:
38 12 50         EXTRACT_DEQ(self);
    50          
    50          
39             CODE:
40 12 50         RETVAL = (UV)deq_size(h);
41             OUTPUT:
42             RETVAL
43              
44             UV
45             capacity(self)
46             SV *self
47             PREINIT:
48 2 50         EXTRACT_DEQ(self);
    50          
    50          
49             CODE:
50 2 50         RETVAL = (UV)h->hdr->capacity;
51             OUTPUT:
52             RETVAL
53              
54             bool
55             is_empty(self)
56             SV *self
57             PREINIT:
58 7 50         EXTRACT_DEQ(self);
    50          
    50          
59             CODE:
60 7 50         RETVAL = deq_size(h) == 0;
61             OUTPUT:
62             RETVAL
63              
64             bool
65             is_full(self)
66             SV *self
67             PREINIT:
68 3 50         EXTRACT_DEQ(self);
    50          
    50          
69             CODE:
70 3 50         RETVAL = deq_size(h) >= h->hdr->capacity;
71             OUTPUT:
72             RETVAL
73              
74             void
75             clear(self)
76             SV *self
77             PREINIT:
78 3 50         EXTRACT_DEQ(self);
    50          
    50          
79             CODE:
80 3           deq_clear(h);
81              
82             UV
83             drain(self)
84             SV *self
85             PREINIT:
86 4 50         EXTRACT_DEQ(self);
    50          
    50          
87             CODE:
88 4 50         RETVAL = (UV)deq_drain(h);
89             OUTPUT:
90             RETVAL
91              
92             SV *
93             path(self)
94             SV *self
95             PREINIT:
96 1 50         EXTRACT_DEQ(self);
    50          
    50          
97             CODE:
98 1 50         RETVAL = h->path ? newSVpv(h->path, 0) : &PL_sv_undef;
99             OUTPUT:
100             RETVAL
101              
102             IV
103             memfd(self)
104             SV *self
105             PREINIT:
106 1 50         EXTRACT_DEQ(self);
    50          
    50          
107             CODE:
108 1 50         RETVAL = h->backing_fd;
109             OUTPUT:
110             RETVAL
111              
112             IV
113             eventfd(self)
114             SV *self
115             PREINIT:
116 2 50         EXTRACT_DEQ(self);
    50          
    50          
117             CODE:
118 2           RETVAL = deq_create_eventfd(h);
119 2 50         if (RETVAL < 0) croak("eventfd: %s", strerror(errno));
120             OUTPUT:
121             RETVAL
122              
123             void
124             eventfd_set(self, fd)
125             SV *self
126             int fd
127             PREINIT:
128 3 50         EXTRACT_DEQ(self);
    50          
    50          
129             CODE:
130 3 50         if (h->notify_fd >= 0 && h->notify_fd != fd) close(h->notify_fd);
    100          
131 3           h->notify_fd = fd;
132              
133             IV
134             fileno(self)
135             SV *self
136             PREINIT:
137 3 50         EXTRACT_DEQ(self);
    50          
    50          
138             CODE:
139 3 50         RETVAL = h->notify_fd;
140             OUTPUT:
141             RETVAL
142              
143             bool
144             notify(self)
145             SV *self
146             PREINIT:
147 2 50         EXTRACT_DEQ(self);
    50          
    50          
148             CODE:
149 2 50         RETVAL = deq_notify(h);
150             OUTPUT:
151             RETVAL
152              
153             SV *
154             eventfd_consume(self)
155             SV *self
156             PREINIT:
157 2 50         EXTRACT_DEQ(self);
    50          
    50          
158             CODE:
159 2           int64_t v = deq_eventfd_consume(h);
160 2 50         RETVAL = (v >= 0) ? newSViv((IV)v) : &PL_sv_undef;
161             OUTPUT:
162             RETVAL
163              
164             void
165             sync(self)
166             SV *self
167             PREINIT:
168 1 50         EXTRACT_DEQ(self);
    50          
    50          
169             CODE:
170 1 50         if (deq_msync(h) != 0) croak("msync: %s", strerror(errno));
171              
172             void
173             unlink(self_or_class, ...)
174             SV *self_or_class
175             CODE:
176             const char *p;
177 2 50         if (sv_isobject(self_or_class)) {
178 2           DeqHandle *h = INT2PTR(DeqHandle*, SvIV(SvRV(self_or_class)));
179 2 50         if (!h) croak("Attempted to use a destroyed object");
180 2           p = h->path;
181             } else {
182 0 0         if (items < 2) croak("Usage: ...->unlink($path)");
183 0           p = SvPV_nolen(ST(1));
184             }
185 2 50         if (!p) croak("cannot unlink anonymous or memfd object");
186 2 50         if (unlink(p) != 0) croak("unlink(%s): %s", p, strerror(errno));
187              
188             SV *
189             stats(self)
190             SV *self
191             PREINIT:
192 3 50         EXTRACT_DEQ(self);
    50          
    50          
193             CODE:
194 3           HV *hv = newHV();
195 3           DeqHeader *hdr = h->hdr;
196 3           hv_store(hv, "size", 4, newSVuv((UV)deq_size(h)), 0);
197 3           hv_store(hv, "capacity", 8, newSVuv((UV)hdr->capacity), 0);
198 3           hv_store(hv, "pushes", 6, newSVuv((UV)__atomic_load_n(&hdr->stat_pushes, __ATOMIC_RELAXED)), 0);
199 3           hv_store(hv, "pops", 4, newSVuv((UV)__atomic_load_n(&hdr->stat_pops, __ATOMIC_RELAXED)), 0);
200 3           hv_store(hv, "waits", 5, newSVuv((UV)__atomic_load_n(&hdr->stat_waits, __ATOMIC_RELAXED)), 0);
201 3           hv_store(hv, "timeouts", 8, newSVuv((UV)__atomic_load_n(&hdr->stat_timeouts, __ATOMIC_RELAXED)), 0);
202 3           hv_store(hv, "recoveries", 10, newSVuv((UV)__atomic_load_n(&hdr->stat_recoveries, __ATOMIC_RELAXED)), 0);
203 3           hv_store(hv, "mmap_size", 9, newSVuv((UV)h->mmap_size), 0);
204 3           RETVAL = newRV_noinc((SV *)hv);
205             OUTPUT:
206             RETVAL
207              
208              
209             MODULE = Data::Deque::Shared PACKAGE = Data::Deque::Shared::Int
210              
211             PROTOTYPES: DISABLE
212              
213             SV *
214             new(class, path, capacity)
215             const char *class
216             SV *path
217             UV capacity
218             PREINIT:
219             char errbuf[DEQ_ERR_BUFLEN];
220             CODE:
221 15 100         const char *p = SvOK(path) ? SvPV_nolen(path) : NULL;
222 15           DeqHandle *h = deq_create(p, capacity, sizeof(int64_t), DEQ_VAR_INT, errbuf);
223 15 100         if (!h) croak("Data::Deque::Shared::Int->new: %s", errbuf);
224 13           MAKE_OBJ(class, h);
225             OUTPUT:
226             RETVAL
227              
228             SV *
229             new_memfd(class, name, capacity)
230             const char *class
231             const char *name
232             UV capacity
233             PREINIT:
234             char errbuf[DEQ_ERR_BUFLEN];
235             CODE:
236 1           DeqHandle *h = deq_create_memfd(name, capacity, sizeof(int64_t), DEQ_VAR_INT, errbuf);
237 1 50         if (!h) croak("Data::Deque::Shared::Int->new_memfd: %s", errbuf);
238 1           MAKE_OBJ(class, h);
239             OUTPUT:
240             RETVAL
241              
242             SV *
243             new_from_fd(class, fd)
244             const char *class
245             int fd
246             PREINIT:
247             char errbuf[DEQ_ERR_BUFLEN];
248             CODE:
249 1           DeqHandle *h = deq_open_fd(fd, DEQ_VAR_INT, errbuf);
250 1 50         if (!h) croak("Data::Deque::Shared::Int->new_from_fd: %s", errbuf);
251 1           MAKE_OBJ(class, h);
252             OUTPUT:
253             RETVAL
254              
255             bool
256             push_back(self, val)
257             SV *self
258             IV val
259             PREINIT:
260 72 50         EXTRACT_DEQ(self);
    50          
    50          
261             CODE:
262 72           int64_t v = (int64_t)val;
263 72 100         RETVAL = deq_try_push_back(h, &v, sizeof(v));
264             OUTPUT:
265             RETVAL
266              
267             bool
268             push_front(self, val)
269             SV *self
270             IV val
271             PREINIT:
272 10 50         EXTRACT_DEQ(self);
    50          
    50          
273             CODE:
274 10           int64_t v = (int64_t)val;
275 10 100         RETVAL = deq_try_push_front(h, &v, sizeof(v));
276             OUTPUT:
277             RETVAL
278              
279             bool
280             push_back_wait(self, val, ...)
281             SV *self
282             IV val
283             PREINIT:
284 1 50         EXTRACT_DEQ(self);
    50          
    50          
285 1           double timeout = -1;
286             CODE:
287 1 50         if (items > 2) timeout = SvNV(ST(2));
288 1           int64_t v = (int64_t)val;
289 1 50         RETVAL = deq_push_wait(h, &v, sizeof(v), 0, timeout);
290             OUTPUT:
291             RETVAL
292              
293             bool
294             push_front_wait(self, val, ...)
295             SV *self
296             IV val
297             PREINIT:
298 1 50         EXTRACT_DEQ(self);
    50          
    50          
299 1           double timeout = -1;
300             CODE:
301 1 50         if (items > 2) timeout = SvNV(ST(2));
302 1           int64_t v = (int64_t)val;
303 1 50         RETVAL = deq_push_wait(h, &v, sizeof(v), 1, timeout);
304             OUTPUT:
305             RETVAL
306              
307             SV *
308             pop_front(self)
309             SV *self
310             PREINIT:
311 18027 50         EXTRACT_DEQ(self);
    50          
    50          
312             CODE:
313             int64_t v;
314 18027 100         RETVAL = deq_try_pop_front(h, &v) ? newSViv((IV)v) : &PL_sv_undef;
315             OUTPUT:
316             RETVAL
317              
318             SV *
319             pop_back(self)
320             SV *self
321             PREINIT:
322 10 50         EXTRACT_DEQ(self);
    50          
    50          
323             CODE:
324             int64_t v;
325 10 100         RETVAL = deq_try_pop_back(h, &v) ? newSViv((IV)v) : &PL_sv_undef;
326             OUTPUT:
327             RETVAL
328              
329             SV *
330             pop_front_wait(self, ...)
331             SV *self
332             PREINIT:
333 2 50         EXTRACT_DEQ(self);
    50          
    50          
334 2           double timeout = -1;
335             CODE:
336 2 50         if (items > 1) timeout = SvNV(ST(1));
337             int64_t v;
338 2 100         RETVAL = deq_pop_wait(h, &v, 0, timeout) ? newSViv((IV)v) : &PL_sv_undef;
339             OUTPUT:
340             RETVAL
341              
342             SV *
343             pop_back_wait(self, ...)
344             SV *self
345             PREINIT:
346 1 50         EXTRACT_DEQ(self);
    50          
    50          
347 1           double timeout = -1;
348             CODE:
349 1 50         if (items > 1) timeout = SvNV(ST(1));
350             int64_t v;
351 1 50         RETVAL = deq_pop_wait(h, &v, 1, timeout) ? newSViv((IV)v) : &PL_sv_undef;
352             OUTPUT:
353             RETVAL
354              
355             MODULE = Data::Deque::Shared PACKAGE = Data::Deque::Shared::Str
356              
357             PROTOTYPES: DISABLE
358              
359             SV *
360             new(class, path, capacity, max_len)
361             const char *class
362             SV *path
363             UV capacity
364             UV max_len
365             PREINIT:
366             char errbuf[DEQ_ERR_BUFLEN];
367             CODE:
368 7 100         if (max_len == 0) croak("max_len must be > 0");
369 6 50         if (max_len > (UV)(UINT32_MAX - sizeof(uint32_t)))
370 0           croak("max_len too large");
371 6           uint32_t elem_size = (uint32_t)(sizeof(uint32_t) + max_len);
372 6 100         const char *p = SvOK(path) ? SvPV_nolen(path) : NULL;
373 6           DeqHandle *h = deq_create(p, capacity, elem_size, DEQ_VAR_STR, errbuf);
374 6 100         if (!h) croak("Data::Deque::Shared::Str->new: %s", errbuf);
375 5           MAKE_OBJ(class, h);
376             OUTPUT:
377             RETVAL
378              
379             SV *
380             new_memfd(class, name, capacity, max_len)
381             const char *class
382             const char *name
383             UV capacity
384             UV max_len
385             PREINIT:
386             char errbuf[DEQ_ERR_BUFLEN];
387             CODE:
388 0 0         if (max_len == 0) croak("max_len must be > 0");
389 0 0         if (max_len > (UV)(UINT32_MAX - sizeof(uint32_t)))
390 0           croak("max_len too large");
391 0           uint32_t elem_size = (uint32_t)(sizeof(uint32_t) + max_len);
392 0           DeqHandle *h = deq_create_memfd(name, capacity, elem_size, DEQ_VAR_STR, errbuf);
393 0 0         if (!h) croak("Data::Deque::Shared::Str->new_memfd: %s", errbuf);
394 0           MAKE_OBJ(class, h);
395             OUTPUT:
396             RETVAL
397              
398             SV *
399             new_from_fd(class, fd)
400             const char *class
401             int fd
402             PREINIT:
403             char errbuf[DEQ_ERR_BUFLEN];
404             CODE:
405 0           DeqHandle *h = deq_open_fd(fd, DEQ_VAR_STR, errbuf);
406 0 0         if (!h) croak("Data::Deque::Shared::Str->new_from_fd: %s", errbuf);
407 0           MAKE_OBJ(class, h);
408             OUTPUT:
409             RETVAL
410              
411             bool
412             push_back(self, val)
413             SV *self
414             SV *val
415             PREINIT:
416 19 50         EXTRACT_DEQ(self);
    50          
    50          
417             CODE:
418             STRLEN slen;
419 19           const char *s = SvPV(val, slen);
420 19           uint32_t max_len = h->elem_size - sizeof(uint32_t);
421 19 100         if (slen > max_len) slen = max_len;
422             uint8_t *buf;
423 19           Newxz(buf, h->elem_size, uint8_t);
424 19           uint32_t l32 = (uint32_t)slen;
425 19           memcpy(buf, &l32, sizeof(uint32_t));
426 19           memcpy(buf + sizeof(uint32_t), s, slen);
427 19           RETVAL = deq_try_push_back(h, buf, h->elem_size);
428 19           Safefree(buf);
429             OUTPUT:
430             RETVAL
431              
432             bool
433             push_front(self, val)
434             SV *self
435             SV *val
436             PREINIT:
437 3 50         EXTRACT_DEQ(self);
    50          
    50          
438             CODE:
439             STRLEN slen;
440 3           const char *s = SvPV(val, slen);
441 3           uint32_t max_len = h->elem_size - sizeof(uint32_t);
442 3 50         if (slen > max_len) slen = max_len;
443             uint8_t *buf;
444 3           Newxz(buf, h->elem_size, uint8_t);
445 3           uint32_t l32 = (uint32_t)slen;
446 3           memcpy(buf, &l32, sizeof(uint32_t));
447 3           memcpy(buf + sizeof(uint32_t), s, slen);
448 3           RETVAL = deq_try_push_front(h, buf, h->elem_size);
449 3           Safefree(buf);
450             OUTPUT:
451             RETVAL
452              
453             bool
454             push_back_wait(self, val, ...)
455             SV *self
456             SV *val
457             PREINIT:
458 0 0         EXTRACT_DEQ(self);
    0          
    0          
459 0           double timeout = -1;
460             CODE:
461 0 0         if (items > 2) timeout = SvNV(ST(2));
462             STRLEN slen;
463 0           const char *s = SvPV(val, slen);
464 0           uint32_t max_len = h->elem_size - sizeof(uint32_t);
465 0 0         if (slen > max_len) slen = max_len;
466             uint8_t *buf;
467 0           Newxz(buf, h->elem_size, uint8_t);
468 0           uint32_t l32 = (uint32_t)slen;
469 0           memcpy(buf, &l32, sizeof(uint32_t));
470 0           memcpy(buf + sizeof(uint32_t), s, slen);
471 0           RETVAL = deq_push_wait(h, buf, h->elem_size, 0, timeout);
472 0           Safefree(buf);
473             OUTPUT:
474             RETVAL
475              
476             bool
477             push_front_wait(self, val, ...)
478             SV *self
479             SV *val
480             PREINIT:
481 0 0         EXTRACT_DEQ(self);
    0          
    0          
482 0           double timeout = -1;
483             CODE:
484 0 0         if (items > 2) timeout = SvNV(ST(2));
485             STRLEN slen;
486 0           const char *s = SvPV(val, slen);
487 0           uint32_t max_len = h->elem_size - sizeof(uint32_t);
488 0 0         if (slen > max_len) slen = max_len;
489             uint8_t *buf;
490 0           Newxz(buf, h->elem_size, uint8_t);
491 0           uint32_t l32 = (uint32_t)slen;
492 0           memcpy(buf, &l32, sizeof(uint32_t));
493 0           memcpy(buf + sizeof(uint32_t), s, slen);
494 0           RETVAL = deq_push_wait(h, buf, h->elem_size, 1, timeout);
495 0           Safefree(buf);
496             OUTPUT:
497             RETVAL
498              
499             SV *
500             pop_front(self)
501             SV *self
502             PREINIT:
503 20 50         EXTRACT_DEQ(self);
    50          
    50          
504             CODE:
505             uint8_t *buf;
506 20           Newx(buf, h->elem_size, uint8_t);
507 20 100         if (deq_try_pop_front(h, buf)) {
508             uint32_t len;
509 19           memcpy(&len, buf, sizeof(uint32_t));
510 19           uint32_t max_len = h->elem_size - sizeof(uint32_t);
511 19 50         if (len > max_len) len = max_len;
512 19           RETVAL = newSVpvn((char *)buf + sizeof(uint32_t), len);
513             } else {
514 1           RETVAL = &PL_sv_undef;
515             }
516 20           Safefree(buf);
517             OUTPUT:
518             RETVAL
519              
520             SV *
521             pop_back(self)
522             SV *self
523             PREINIT:
524 2 50         EXTRACT_DEQ(self);
    50          
    50          
525             CODE:
526             uint8_t *buf;
527 2           Newx(buf, h->elem_size, uint8_t);
528 2 100         if (deq_try_pop_back(h, buf)) {
529             uint32_t len;
530 1           memcpy(&len, buf, sizeof(uint32_t));
531 1           uint32_t max_len = h->elem_size - sizeof(uint32_t);
532 1 50         if (len > max_len) len = max_len;
533 1           RETVAL = newSVpvn((char *)buf + sizeof(uint32_t), len);
534             } else {
535 1           RETVAL = &PL_sv_undef;
536             }
537 2           Safefree(buf);
538             OUTPUT:
539             RETVAL
540              
541             SV *
542             pop_front_wait(self, ...)
543             SV *self
544             PREINIT:
545 0 0         EXTRACT_DEQ(self);
    0          
    0          
546 0           double timeout = -1;
547             CODE:
548 0 0         if (items > 1) timeout = SvNV(ST(1));
549             uint8_t *buf;
550 0           Newx(buf, h->elem_size, uint8_t);
551 0 0         if (deq_pop_wait(h, buf, 0, timeout)) {
552             uint32_t len;
553 0           memcpy(&len, buf, sizeof(uint32_t));
554 0           uint32_t max_len = h->elem_size - sizeof(uint32_t);
555 0 0         if (len > max_len) len = max_len;
556 0           RETVAL = newSVpvn((char *)buf + sizeof(uint32_t), len);
557             } else {
558 0           RETVAL = &PL_sv_undef;
559             }
560 0           Safefree(buf);
561             OUTPUT:
562             RETVAL
563              
564             SV *
565             pop_back_wait(self, ...)
566             SV *self
567             PREINIT:
568 0 0         EXTRACT_DEQ(self);
    0          
    0          
569 0           double timeout = -1;
570             CODE:
571 0 0         if (items > 1) timeout = SvNV(ST(1));
572             uint8_t *buf;
573 0           Newx(buf, h->elem_size, uint8_t);
574 0 0         if (deq_pop_wait(h, buf, 1, timeout)) {
575             uint32_t len;
576 0           memcpy(&len, buf, sizeof(uint32_t));
577 0           uint32_t max_len = h->elem_size - sizeof(uint32_t);
578 0 0         if (len > max_len) len = max_len;
579 0           RETVAL = newSVpvn((char *)buf + sizeof(uint32_t), len);
580             } else {
581 0           RETVAL = &PL_sv_undef;
582             }
583 0           Safefree(buf);
584             OUTPUT:
585             RETVAL