File Coverage

Shared.xs
Criterion Covered Total %
statement 81 83 97.5
branch 92 172 53.4
condition n/a
subroutine n/a
pod n/a
total 173 255 67.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 "heap.h"
7              
8             #define EXTRACT_HEAP(sv) \
9             if (!sv_isobject(sv) || !sv_derived_from(sv, "Data::Heap::Shared")) \
10             croak("Expected a Data::Heap::Shared object"); \
11             HeapHandle *h = INT2PTR(HeapHandle*, SvIV(SvRV(sv))); \
12             if (!h) croak("Attempted to use a destroyed Data::Heap::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::Heap::Shared PACKAGE = Data::Heap::Shared
21              
22             PROTOTYPES: DISABLE
23              
24             SV *
25             new(class, path, capacity)
26             const char *class
27             SV *path
28             UV capacity
29             PREINIT:
30             char errbuf[HEAP_ERR_BUFLEN];
31             CODE:
32 9 100         const char *p = SvOK(path) ? SvPV_nolen(path) : NULL;
33 9           HeapHandle *h = heap_create(p, capacity, errbuf);
34 9 50         if (!h) croak("Data::Heap::Shared->new: %s", errbuf);
35 9           MAKE_OBJ(class, h);
36             OUTPUT:
37             RETVAL
38              
39             SV *
40             new_memfd(class, name, capacity)
41             const char *class
42             const char *name
43             UV capacity
44             PREINIT:
45             char errbuf[HEAP_ERR_BUFLEN];
46             CODE:
47 7           HeapHandle *h = heap_create_memfd(name, capacity, errbuf);
48 7 50         if (!h) croak("Data::Heap::Shared->new_memfd: %s", errbuf);
49 7           MAKE_OBJ(class, h);
50             OUTPUT:
51             RETVAL
52              
53             SV *
54             new_from_fd(class, fd)
55             const char *class
56             int fd
57             PREINIT:
58             char errbuf[HEAP_ERR_BUFLEN];
59             CODE:
60 1           HeapHandle *h = heap_open_fd(fd, errbuf);
61 1 50         if (!h) croak("Data::Heap::Shared->new_from_fd: %s", errbuf);
62 1           MAKE_OBJ(class, h);
63             OUTPUT:
64             RETVAL
65              
66             void
67             DESTROY(self)
68             SV *self
69             CODE:
70 17 50         if (!SvROK(self)) return;
71 17           HeapHandle *h = INT2PTR(HeapHandle*, SvIV(SvRV(self)));
72 17 50         if (!h) return;
73 17           sv_setiv(SvRV(self), 0);
74 17           heap_destroy(h);
75              
76             bool
77             push(self, priority, value)
78             SV *self
79             IV priority
80             IV value
81             PREINIT:
82 57 50         EXTRACT_HEAP(self);
    50          
    50          
83             CODE:
84 57 100         RETVAL = heap_push(h, (int64_t)priority, (int64_t)value);
85             OUTPUT:
86             RETVAL
87              
88             void
89             pop(self)
90             SV *self
91             PREINIT:
92 33 50         EXTRACT_HEAP(self);
    50          
    50          
93             PPCODE:
94             int64_t p, v;
95 33 100         if (heap_pop(h, &p, &v)) {
96 31 50         EXTEND(SP, 2);
97 31           PUSHs(sv_2mortal(newSViv((IV)p)));
98 31           PUSHs(sv_2mortal(newSViv((IV)v)));
99             }
100              
101             void
102             pop_wait(self, ...)
103             SV *self
104             PREINIT:
105 2 50         EXTRACT_HEAP(self);
    50          
    50          
106 2           double timeout = -1;
107             PPCODE:
108 2 50         if (items > 1) timeout = SvNV(ST(1));
109             int64_t p, v;
110 2 100         if (heap_pop_wait(h, &p, &v, timeout)) {
111 1 50         EXTEND(SP, 2);
112 1           PUSHs(sv_2mortal(newSViv((IV)p)));
113 1           PUSHs(sv_2mortal(newSViv((IV)v)));
114             }
115              
116             void
117             peek(self)
118             SV *self
119             PREINIT:
120 2 50         EXTRACT_HEAP(self);
    50          
    50          
121             PPCODE:
122             int64_t p, v;
123 2 50         if (heap_peek(h, &p, &v)) {
124 2 50         EXTEND(SP, 2);
125 2           PUSHs(sv_2mortal(newSViv((IV)p)));
126 2           PUSHs(sv_2mortal(newSViv((IV)v)));
127             }
128              
129             UV
130             size(self)
131             SV *self
132             PREINIT:
133 17 50         EXTRACT_HEAP(self);
    50          
    50          
134             CODE:
135 17 100         RETVAL = heap_size(h);
136             OUTPUT:
137             RETVAL
138              
139             UV
140             capacity(self)
141             SV *self
142             PREINIT:
143 1 50         EXTRACT_HEAP(self);
    50          
    50          
144             CODE:
145 1 50         RETVAL = (UV)h->hdr->capacity;
146             OUTPUT:
147             RETVAL
148              
149             bool
150             is_empty(self)
151             SV *self
152             PREINIT:
153 4 50         EXTRACT_HEAP(self);
    50          
    50          
154             CODE:
155 4 50         RETVAL = heap_size(h) == 0;
156             OUTPUT:
157             RETVAL
158              
159             bool
160             is_full(self)
161             SV *self
162             PREINIT:
163 2 50         EXTRACT_HEAP(self);
    50          
    50          
164             CODE:
165 2 50         RETVAL = heap_size(h) >= (UV)h->hdr->capacity;
166             OUTPUT:
167             RETVAL
168              
169             void
170             clear(self)
171             SV *self
172             PREINIT:
173 3 50         EXTRACT_HEAP(self);
    50          
    50          
174             CODE:
175 3           heap_clear(h);
176              
177             SV *
178             path(self)
179             SV *self
180             PREINIT:
181 2 50         EXTRACT_HEAP(self);
    50          
    50          
182             CODE:
183 2 100         RETVAL = h->path ? newSVpv(h->path, 0) : &PL_sv_undef;
184             OUTPUT:
185             RETVAL
186              
187             IV
188             memfd(self)
189             SV *self
190             PREINIT:
191 1 50         EXTRACT_HEAP(self);
    50          
    50          
192             CODE:
193 1 50         RETVAL = h->backing_fd;
194             OUTPUT:
195             RETVAL
196              
197             IV
198             eventfd(self)
199             SV *self
200             PREINIT:
201 2 50         EXTRACT_HEAP(self);
    50          
    50          
202             CODE:
203 2           RETVAL = heap_create_eventfd(h);
204 2 50         if (RETVAL < 0) croak("eventfd: %s", strerror(errno));
205             OUTPUT:
206             RETVAL
207              
208             void
209             eventfd_set(self, fd)
210             SV *self
211             int fd
212             PREINIT:
213 3 50         EXTRACT_HEAP(self);
    50          
    50          
214             CODE:
215 3 50         if (h->notify_fd >= 0 && h->notify_fd != fd) close(h->notify_fd);
    100          
216 3           h->notify_fd = fd;
217              
218             IV
219             fileno(self)
220             SV *self
221             PREINIT:
222 4 50         EXTRACT_HEAP(self);
    50          
    50          
223             CODE:
224 4 50         RETVAL = h->notify_fd;
225             OUTPUT:
226             RETVAL
227              
228             bool
229             notify(self)
230             SV *self
231             PREINIT:
232 2 50         EXTRACT_HEAP(self);
    50          
    50          
233             CODE:
234 2 50         RETVAL = heap_notify(h);
235             OUTPUT:
236             RETVAL
237              
238             SV *
239             eventfd_consume(self)
240             SV *self
241             PREINIT:
242 2 50         EXTRACT_HEAP(self);
    50          
    50          
243             CODE:
244 2           int64_t v = heap_eventfd_consume(h);
245 2 50         RETVAL = (v >= 0) ? newSViv((IV)v) : &PL_sv_undef;
246             OUTPUT:
247             RETVAL
248              
249             void
250             sync(self)
251             SV *self
252             PREINIT:
253 1 50         EXTRACT_HEAP(self);
    50          
    50          
254             CODE:
255 1 50         if (heap_msync(h) != 0) croak("msync: %s", strerror(errno));
256              
257             void
258             unlink(self_or_class, ...)
259             SV *self_or_class
260             CODE:
261             const char *p;
262 1 50         if (sv_isobject(self_or_class)) {
263 1           HeapHandle *h = INT2PTR(HeapHandle*, SvIV(SvRV(self_or_class)));
264 1 50         if (!h) croak("Attempted to use a destroyed object");
265 1           p = h->path;
266             } else {
267 0 0         if (items < 2) croak("Usage: ...->unlink($path)");
268 0           p = SvPV_nolen(ST(1));
269             }
270 1 50         if (!p) croak("cannot unlink anonymous or memfd object");
271 1 50         if (unlink(p) != 0) croak("unlink(%s): %s", p, strerror(errno));
272              
273             SV *
274             stats(self)
275             SV *self
276             PREINIT:
277 1 50         EXTRACT_HEAP(self);
    50          
    50          
278             CODE:
279 1           HV *hv = newHV();
280 1           HeapHeader *hdr = h->hdr;
281 1           hv_store(hv, "size", 4, newSVuv(heap_size(h)), 0);
282 1           hv_store(hv, "capacity", 8, newSVuv((UV)hdr->capacity), 0);
283 1           hv_store(hv, "pushes", 6, newSVuv((UV)__atomic_load_n(&hdr->stat_pushes, __ATOMIC_RELAXED)), 0);
284 1           hv_store(hv, "pops", 4, newSVuv((UV)__atomic_load_n(&hdr->stat_pops, __ATOMIC_RELAXED)), 0);
285 1           hv_store(hv, "waits", 5, newSVuv((UV)__atomic_load_n(&hdr->stat_waits, __ATOMIC_RELAXED)), 0);
286 1           hv_store(hv, "timeouts", 8, newSVuv((UV)__atomic_load_n(&hdr->stat_timeouts, __ATOMIC_RELAXED)), 0);
287 1           hv_store(hv, "recoveries", 10, newSVuv((UV)__atomic_load_n(&hdr->stat_recoveries, __ATOMIC_RELAXED)), 0);
288 1           hv_store(hv, "mmap_size", 9, newSVuv((UV)h->mmap_size), 0);
289 1           RETVAL = newRV_noinc((SV *)hv);
290             OUTPUT:
291             RETVAL