File Coverage

Shared.xs
Criterion Covered Total %
statement 136 195 69.7
branch 140 308 45.4
condition n/a
subroutine n/a
pod n/a
total 276 503 54.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 "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 18 50         if (!SvROK(self)) return;
29 18           DeqHandle *h = INT2PTR(DeqHandle*, SvIV(SvRV(self)));
30 18 50         if (!h) return;
31 18           sv_setiv(SvRV(self), 0);
32 18           deq_destroy(h);
33              
34             UV
35             size(self)
36             SV *self
37             PREINIT:
38 8 50         EXTRACT_DEQ(self);
    50          
    50          
39             CODE:
40 8 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 2 50         EXTRACT_DEQ(self);
    50          
    50          
87             CODE:
88 2 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 1 50         EXTRACT_DEQ(self);
    50          
    50          
193             CODE:
194 1           HV *hv = newHV();
195 1           DeqHeader *hdr = h->hdr;
196 1           hv_store(hv, "size", 4, newSVuv((UV)deq_size(h)), 0);
197 1           hv_store(hv, "capacity", 8, newSVuv((UV)hdr->capacity), 0);
198 1           hv_store(hv, "pushes", 6, newSVuv((UV)__atomic_load_n(&hdr->stat_pushes, __ATOMIC_RELAXED)), 0);
199 1           hv_store(hv, "pops", 4, newSVuv((UV)__atomic_load_n(&hdr->stat_pops, __ATOMIC_RELAXED)), 0);
200 1           hv_store(hv, "waits", 5, newSVuv((UV)__atomic_load_n(&hdr->stat_waits, __ATOMIC_RELAXED)), 0);
201 1           hv_store(hv, "timeouts", 8, newSVuv((UV)__atomic_load_n(&hdr->stat_timeouts, __ATOMIC_RELAXED)), 0);
202 1           hv_store(hv, "mmap_size", 9, newSVuv((UV)h->mmap_size), 0);
203 1           RETVAL = newRV_noinc((SV *)hv);
204             OUTPUT:
205             RETVAL
206              
207              
208             MODULE = Data::Deque::Shared PACKAGE = Data::Deque::Shared::Int
209              
210             PROTOTYPES: DISABLE
211              
212             SV *
213             new(class, path, capacity)
214             const char *class
215             SV *path
216             UV capacity
217             PREINIT:
218             char errbuf[DEQ_ERR_BUFLEN];
219             CODE:
220 12 100         const char *p = SvOK(path) ? SvPV_nolen(path) : NULL;
221 12           DeqHandle *h = deq_create(p, capacity, sizeof(int64_t), DEQ_VAR_INT, errbuf);
222 12 100         if (!h) croak("Data::Deque::Shared::Int->new: %s", errbuf);
223 11           MAKE_OBJ(class, h);
224             OUTPUT:
225             RETVAL
226              
227             SV *
228             new_memfd(class, name, capacity)
229             const char *class
230             const char *name
231             UV capacity
232             PREINIT:
233             char errbuf[DEQ_ERR_BUFLEN];
234             CODE:
235 1           DeqHandle *h = deq_create_memfd(name, capacity, sizeof(int64_t), DEQ_VAR_INT, errbuf);
236 1 50         if (!h) croak("Data::Deque::Shared::Int->new_memfd: %s", errbuf);
237 1           MAKE_OBJ(class, h);
238             OUTPUT:
239             RETVAL
240              
241             SV *
242             new_from_fd(class, fd)
243             const char *class
244             int fd
245             PREINIT:
246             char errbuf[DEQ_ERR_BUFLEN];
247             CODE:
248 1           DeqHandle *h = deq_open_fd(fd, DEQ_VAR_INT, errbuf);
249 1 50         if (!h) croak("Data::Deque::Shared::Int->new_from_fd: %s", errbuf);
250 1           MAKE_OBJ(class, h);
251             OUTPUT:
252             RETVAL
253              
254             bool
255             push_back(self, val)
256             SV *self
257             IV val
258             PREINIT:
259 62 50         EXTRACT_DEQ(self);
    50          
    50          
260             CODE:
261 62           int64_t v = (int64_t)val;
262 62 100         RETVAL = deq_try_push_back(h, &v, sizeof(v));
263             OUTPUT:
264             RETVAL
265              
266             bool
267             push_front(self, val)
268             SV *self
269             IV val
270             PREINIT:
271 10 50         EXTRACT_DEQ(self);
    50          
    50          
272             CODE:
273 10           int64_t v = (int64_t)val;
274 10 100         RETVAL = deq_try_push_front(h, &v, sizeof(v));
275             OUTPUT:
276             RETVAL
277              
278             bool
279             push_back_wait(self, val, ...)
280             SV *self
281             IV val
282             PREINIT:
283 1 50         EXTRACT_DEQ(self);
    50          
    50          
284 1           double timeout = -1;
285             CODE:
286 1 50         if (items > 2) timeout = SvNV(ST(2));
287 1           int64_t v = (int64_t)val;
288 1 50         RETVAL = deq_push_wait(h, &v, sizeof(v), 0, timeout);
289             OUTPUT:
290             RETVAL
291              
292             bool
293             push_front_wait(self, val, ...)
294             SV *self
295             IV val
296             PREINIT:
297 1 50         EXTRACT_DEQ(self);
    50          
    50          
298 1           double timeout = -1;
299             CODE:
300 1 50         if (items > 2) timeout = SvNV(ST(2));
301 1           int64_t v = (int64_t)val;
302 1 50         RETVAL = deq_push_wait(h, &v, sizeof(v), 1, timeout);
303             OUTPUT:
304             RETVAL
305              
306             SV *
307             pop_front(self)
308             SV *self
309             PREINIT:
310 18024 50         EXTRACT_DEQ(self);
    50          
    50          
311             CODE:
312             int64_t v;
313 18024 100         RETVAL = deq_try_pop_front(h, &v) ? newSViv((IV)v) : &PL_sv_undef;
314             OUTPUT:
315             RETVAL
316              
317             SV *
318             pop_back(self)
319             SV *self
320             PREINIT:
321 10 50         EXTRACT_DEQ(self);
    50          
    50          
322             CODE:
323             int64_t v;
324 10 100         RETVAL = deq_try_pop_back(h, &v) ? newSViv((IV)v) : &PL_sv_undef;
325             OUTPUT:
326             RETVAL
327              
328             SV *
329             pop_front_wait(self, ...)
330             SV *self
331             PREINIT:
332 2 50         EXTRACT_DEQ(self);
    50          
    50          
333 2           double timeout = -1;
334             CODE:
335 2 50         if (items > 1) timeout = SvNV(ST(1));
336             int64_t v;
337 2 100         RETVAL = deq_pop_wait(h, &v, 0, timeout) ? newSViv((IV)v) : &PL_sv_undef;
338             OUTPUT:
339             RETVAL
340              
341             SV *
342             pop_back_wait(self, ...)
343             SV *self
344             PREINIT:
345 1 50         EXTRACT_DEQ(self);
    50          
    50          
346 1           double timeout = -1;
347             CODE:
348 1 50         if (items > 1) timeout = SvNV(ST(1));
349             int64_t v;
350 1 50         RETVAL = deq_pop_wait(h, &v, 1, timeout) ? newSViv((IV)v) : &PL_sv_undef;
351             OUTPUT:
352             RETVAL
353              
354             MODULE = Data::Deque::Shared PACKAGE = Data::Deque::Shared::Str
355              
356             PROTOTYPES: DISABLE
357              
358             SV *
359             new(class, path, capacity, max_len)
360             const char *class
361             SV *path
362             UV capacity
363             UV max_len
364             PREINIT:
365             char errbuf[DEQ_ERR_BUFLEN];
366             CODE:
367 6 100         if (max_len == 0) croak("max_len must be > 0");
368 5 50         if (max_len > (UV)(UINT32_MAX - sizeof(uint32_t)))
369 0           croak("max_len too large");
370 5           uint32_t elem_size = (uint32_t)(sizeof(uint32_t) + max_len);
371 5 100         const char *p = SvOK(path) ? SvPV_nolen(path) : NULL;
372 5           DeqHandle *h = deq_create(p, capacity, elem_size, DEQ_VAR_STR, errbuf);
373 5 50         if (!h) croak("Data::Deque::Shared::Str->new: %s", errbuf);
374 5           MAKE_OBJ(class, h);
375             OUTPUT:
376             RETVAL
377              
378             SV *
379             new_memfd(class, name, capacity, max_len)
380             const char *class
381             const char *name
382             UV capacity
383             UV max_len
384             PREINIT:
385             char errbuf[DEQ_ERR_BUFLEN];
386             CODE:
387 0 0         if (max_len == 0) croak("max_len must be > 0");
388 0 0         if (max_len > (UV)(UINT32_MAX - sizeof(uint32_t)))
389 0           croak("max_len too large");
390 0           uint32_t elem_size = (uint32_t)(sizeof(uint32_t) + max_len);
391 0           DeqHandle *h = deq_create_memfd(name, capacity, elem_size, DEQ_VAR_STR, errbuf);
392 0 0         if (!h) croak("Data::Deque::Shared::Str->new_memfd: %s", errbuf);
393 0           MAKE_OBJ(class, h);
394             OUTPUT:
395             RETVAL
396              
397             SV *
398             new_from_fd(class, fd)
399             const char *class
400             int fd
401             PREINIT:
402             char errbuf[DEQ_ERR_BUFLEN];
403             CODE:
404 0           DeqHandle *h = deq_open_fd(fd, DEQ_VAR_STR, errbuf);
405 0 0         if (!h) croak("Data::Deque::Shared::Str->new_from_fd: %s", errbuf);
406 0           MAKE_OBJ(class, h);
407             OUTPUT:
408             RETVAL
409              
410             bool
411             push_back(self, val)
412             SV *self
413             SV *val
414             PREINIT:
415 19 50         EXTRACT_DEQ(self);
    50          
    50          
416             CODE:
417             STRLEN slen;
418 19           const char *s = SvPV(val, slen);
419 19           uint32_t max_len = h->elem_size - sizeof(uint32_t);
420 19 100         if (slen > max_len) slen = max_len;
421             uint8_t *buf;
422 19           Newxz(buf, h->elem_size, uint8_t);
423 19           uint32_t l32 = (uint32_t)slen;
424 19           memcpy(buf, &l32, sizeof(uint32_t));
425 19           memcpy(buf + sizeof(uint32_t), s, slen);
426 19           RETVAL = deq_try_push_back(h, buf, h->elem_size);
427 19           Safefree(buf);
428             OUTPUT:
429             RETVAL
430              
431             bool
432             push_front(self, val)
433             SV *self
434             SV *val
435             PREINIT:
436 3 50         EXTRACT_DEQ(self);
    50          
    50          
437             CODE:
438             STRLEN slen;
439 3           const char *s = SvPV(val, slen);
440 3           uint32_t max_len = h->elem_size - sizeof(uint32_t);
441 3 50         if (slen > max_len) slen = max_len;
442             uint8_t *buf;
443 3           Newxz(buf, h->elem_size, uint8_t);
444 3           uint32_t l32 = (uint32_t)slen;
445 3           memcpy(buf, &l32, sizeof(uint32_t));
446 3           memcpy(buf + sizeof(uint32_t), s, slen);
447 3           RETVAL = deq_try_push_front(h, buf, h->elem_size);
448 3           Safefree(buf);
449             OUTPUT:
450             RETVAL
451              
452             bool
453             push_back_wait(self, val, ...)
454             SV *self
455             SV *val
456             PREINIT:
457 0 0         EXTRACT_DEQ(self);
    0          
    0          
458 0           double timeout = -1;
459             CODE:
460 0 0         if (items > 2) timeout = SvNV(ST(2));
461             STRLEN slen;
462 0           const char *s = SvPV(val, slen);
463 0           uint32_t max_len = h->elem_size - sizeof(uint32_t);
464 0 0         if (slen > max_len) slen = max_len;
465             uint8_t *buf;
466 0           Newxz(buf, h->elem_size, uint8_t);
467 0           uint32_t l32 = (uint32_t)slen;
468 0           memcpy(buf, &l32, sizeof(uint32_t));
469 0           memcpy(buf + sizeof(uint32_t), s, slen);
470 0           RETVAL = deq_push_wait(h, buf, h->elem_size, 0, timeout);
471 0           Safefree(buf);
472             OUTPUT:
473             RETVAL
474              
475             bool
476             push_front_wait(self, val, ...)
477             SV *self
478             SV *val
479             PREINIT:
480 0 0         EXTRACT_DEQ(self);
    0          
    0          
481 0           double timeout = -1;
482             CODE:
483 0 0         if (items > 2) timeout = SvNV(ST(2));
484             STRLEN slen;
485 0           const char *s = SvPV(val, slen);
486 0           uint32_t max_len = h->elem_size - sizeof(uint32_t);
487 0 0         if (slen > max_len) slen = max_len;
488             uint8_t *buf;
489 0           Newxz(buf, h->elem_size, uint8_t);
490 0           uint32_t l32 = (uint32_t)slen;
491 0           memcpy(buf, &l32, sizeof(uint32_t));
492 0           memcpy(buf + sizeof(uint32_t), s, slen);
493 0           RETVAL = deq_push_wait(h, buf, h->elem_size, 1, timeout);
494 0           Safefree(buf);
495             OUTPUT:
496             RETVAL
497              
498             SV *
499             pop_front(self)
500             SV *self
501             PREINIT:
502 20 50         EXTRACT_DEQ(self);
    50          
    50          
503             CODE:
504             uint8_t *buf;
505 20           Newx(buf, h->elem_size, uint8_t);
506 20 100         if (deq_try_pop_front(h, buf)) {
507             uint32_t len;
508 19           memcpy(&len, buf, sizeof(uint32_t));
509 19           uint32_t max_len = h->elem_size - sizeof(uint32_t);
510 19 50         if (len > max_len) len = max_len;
511 19           RETVAL = newSVpvn((char *)buf + sizeof(uint32_t), len);
512             } else {
513 1           RETVAL = &PL_sv_undef;
514             }
515 20           Safefree(buf);
516             OUTPUT:
517             RETVAL
518              
519             SV *
520             pop_back(self)
521             SV *self
522             PREINIT:
523 2 50         EXTRACT_DEQ(self);
    50          
    50          
524             CODE:
525             uint8_t *buf;
526 2           Newx(buf, h->elem_size, uint8_t);
527 2 100         if (deq_try_pop_back(h, buf)) {
528             uint32_t len;
529 1           memcpy(&len, buf, sizeof(uint32_t));
530 1           uint32_t max_len = h->elem_size - sizeof(uint32_t);
531 1 50         if (len > max_len) len = max_len;
532 1           RETVAL = newSVpvn((char *)buf + sizeof(uint32_t), len);
533             } else {
534 1           RETVAL = &PL_sv_undef;
535             }
536 2           Safefree(buf);
537             OUTPUT:
538             RETVAL
539              
540             SV *
541             pop_front_wait(self, ...)
542             SV *self
543             PREINIT:
544 0 0         EXTRACT_DEQ(self);
    0          
    0          
545 0           double timeout = -1;
546             CODE:
547 0 0         if (items > 1) timeout = SvNV(ST(1));
548             uint8_t *buf;
549 0           Newx(buf, h->elem_size, uint8_t);
550 0 0         if (deq_pop_wait(h, buf, 0, timeout)) {
551             uint32_t len;
552 0           memcpy(&len, buf, sizeof(uint32_t));
553 0           uint32_t max_len = h->elem_size - sizeof(uint32_t);
554 0 0         if (len > max_len) len = max_len;
555 0           RETVAL = newSVpvn((char *)buf + sizeof(uint32_t), len);
556             } else {
557 0           RETVAL = &PL_sv_undef;
558             }
559 0           Safefree(buf);
560             OUTPUT:
561             RETVAL
562              
563             SV *
564             pop_back_wait(self, ...)
565             SV *self
566             PREINIT:
567 0 0         EXTRACT_DEQ(self);
    0          
    0          
568 0           double timeout = -1;
569             CODE:
570 0 0         if (items > 1) timeout = SvNV(ST(1));
571             uint8_t *buf;
572 0           Newx(buf, h->elem_size, uint8_t);
573 0 0         if (deq_pop_wait(h, buf, 1, timeout)) {
574             uint32_t len;
575 0           memcpy(&len, buf, sizeof(uint32_t));
576 0           uint32_t max_len = h->elem_size - sizeof(uint32_t);
577 0 0         if (len > max_len) len = max_len;
578 0           RETVAL = newSVpvn((char *)buf + sizeof(uint32_t), len);
579             } else {
580 0           RETVAL = &PL_sv_undef;
581             }
582 0           Safefree(buf);
583             OUTPUT:
584             RETVAL