File Coverage

xs/i32.xs
Criterion Covered Total %
statement 56 330 16.9
branch 75 660 11.3
condition n/a
subroutine n/a
pod n/a
total 131 990 13.2


line stmt bran cond sub pod time code
1             MODULE = Data::HashMap::Shared PACKAGE = Data::HashMap::Shared::I32
2             PROTOTYPES: DISABLE
3              
4             SV*
5             new(char* class, SV* path_sv, UV max_entries, UV lru_max = 0, UV ttl_default = 0, UV lru_skip = 0)
6             CODE:
7 5 50         char errbuf[SHM_ERR_BUFLEN]; const char* path = SvOK(path_sv) ? SvPV_nolen(path_sv) : NULL; ShmHandle* map = shm_i32_create(path, (uint32_t)max_entries, (uint32_t)lru_max, (uint32_t)ttl_default, (uint32_t)lru_skip, errbuf);
8 5 50         if (!map) croak("HashMap::Shared::I32: %s", errbuf[0] ? errbuf : "unknown error");
    0          
9 5           RETVAL = sv_setref_pv(newSV(0), class, (void*)map);
10             OUTPUT:
11             RETVAL
12              
13             SV*
14             new_sharded(char* class, char* path_prefix, UV num_shards, UV max_entries, UV lru_max = 0, UV ttl_default = 0, UV lru_skip = 0)
15             CODE:
16 0           char errbuf[SHM_ERR_BUFLEN]; ShmHandle* map = shm_i32_create_sharded(path_prefix, (uint32_t)num_shards, (uint32_t)max_entries, (uint32_t)lru_max, (uint32_t)ttl_default, (uint32_t)lru_skip, errbuf);
17 0 0         if (!map) croak("HashMap::Shared::I32: %s", errbuf[0] ? errbuf : "unknown error");
    0          
18 0           RETVAL = sv_setref_pv(newSV(0), class, (void*)map);
19             OUTPUT:
20             RETVAL
21              
22              
23             SV*
24             new_memfd(char* class, SV* name_sv, UV max_entries, UV lru_max = 0, UV ttl_default = 0, UV lru_skip = 0)
25             CODE:
26             char errbuf[SHM_ERR_BUFLEN];
27 0 0         const char* name = SvOK(name_sv) ? SvPV_nolen(name_sv) : NULL;
28 0           ShmHandle* map = shm_i32_create_memfd(name, (uint32_t)max_entries, (uint32_t)lru_max, (uint32_t)ttl_default, (uint32_t)lru_skip, errbuf);
29 0 0         if (!map) croak("Data::HashMap::Shared::I32: %s", errbuf[0] ? errbuf : "unknown error");
    0          
30 0           RETVAL = sv_setref_pv(newSV(0), class, (void*)map);
31             OUTPUT:
32             RETVAL
33              
34             SV*
35             new_from_fd(char* class, int fd)
36             CODE:
37             char errbuf[SHM_ERR_BUFLEN];
38 0           ShmHandle* map = shm_i32_open_fd(fd, errbuf);
39 0 0         if (!map) croak("Data::HashMap::Shared::I32: %s", errbuf[0] ? errbuf : "unknown error");
    0          
40 0           RETVAL = sv_setref_pv(newSV(0), class, (void*)map);
41             OUTPUT:
42             RETVAL
43              
44             IV
45             memfd(SV* self_sv)
46             CODE:
47 0 0         EXTRACT_MAP("Data::HashMap::Shared::I32", self_sv);
    0          
    0          
48 0 0         RETVAL = h->backing_fd;
49             OUTPUT:
50             RETVAL
51              
52              
53             void
54             sync(SV* self_sv)
55             CODE:
56 0 0         EXTRACT_MAP("Data::HashMap::Shared::I32", self_sv);
    0          
    0          
57 0 0         if (shm_msync(h) != 0) croak("Data::HashMap::Shared::I32 sync: %s", strerror(errno));
58              
59             void
60             DESTROY(SV* self_sv)
61             CODE:
62 5 50         if (!SvROK(self_sv)) return;
63 5           ShmHandle* h = INT2PTR(ShmHandle*, SvIV(SvRV(self_sv)));
64 5 50         if (!h) return;
65 5           sv_setiv(SvRV(self_sv), 0);
66 5           shm_close_map(h);
67              
68             bool
69             put(SV* self_sv, int32_t key, int32_t value)
70             CODE:
71 1014 50         EXTRACT_MAP("Data::HashMap::Shared::I32", self_sv);
    50          
    50          
72 1014 50         RETVAL = shm_i32_put(h, key, value);
73             OUTPUT:
74             RETVAL
75              
76             UV
77             set_multi(SV* self_sv, ...)
78             CODE:
79 0 0         EXTRACT_MAP("Data::HashMap::Shared::I32", self_sv);
    0          
    0          
80 0 0         if ((items - 1) % 2 != 0) croak("set_multi requires even number of arguments (key, value pairs)");
81 0           uint32_t count = 0;
82 0 0         if (h->shard_handles) {
83 0 0         for (int i = 1; i < items; i += 2)
84 0           count += shm_i32_put(h, (int32_t)SvIV(ST(i)), (int32_t)SvIV(ST(i + 1)));
85             } else {
86 0           ShmHeader *hdr = h->hdr;
87 0           shm_rwlock_wrlock(hdr);
88 0           shm_seqlock_write_begin(&hdr->seq);
89 0 0         for (int i = 1; i < items; i += 2)
90 0           count += shm_i32_put_inner(h, (int32_t)SvIV(ST(i)), (int32_t)SvIV(ST(i + 1)), SHM_TTL_USE_DEFAULT);
91 0           shm_seqlock_write_end(&hdr->seq);
92 0           shm_rwlock_wrunlock(hdr);
93             }
94 0 0         RETVAL = count;
95             OUTPUT:
96             RETVAL
97              
98             UV
99             remove_multi(SV* self_sv, ...)
100             CODE:
101 0 0         EXTRACT_MAP("Data::HashMap::Shared::I32", self_sv);
    0          
    0          
102 0           uint32_t count = 0;
103 0 0         if (h->shard_handles) {
104 0 0         for (int i = 1; i < items; i++)
105 0           count += shm_i32_remove(h, (int32_t)SvIV(ST(i)));
106             } else {
107 0           ShmHeader *hdr = h->hdr;
108 0           shm_rwlock_wrlock(hdr);
109 0           shm_seqlock_write_begin(&hdr->seq);
110 0 0         for (int i = 1; i < items; i++)
111 0           count += shm_i32_remove_inner(h, (int32_t)SvIV(ST(i)));
112 0 0         if (count) shm_i32_maybe_shrink(h);
113 0           shm_seqlock_write_end(&hdr->seq);
114 0           shm_rwlock_wrunlock(hdr);
115             }
116 0 0         RETVAL = count;
117             OUTPUT:
118             RETVAL
119              
120             void
121             get_multi(SV* self_sv, ...)
122             PPCODE:
123 0 0         EXTRACT_MAP("Data::HashMap::Shared::I32", self_sv);
    0          
    0          
124 0           int nkeys = items - 1;
125 0 0         if (nkeys == 0) XSRETURN_EMPTY;
126 0 0         EXTEND(SP, nkeys);
    0          
127 0 0         if (h->shard_handles) {
128 0 0         for (int i = 0; i < nkeys; i++) {
129 0           int32_t key = (int32_t)SvIV(ST(i + 1));
130             int32_t val;
131 0 0         if (shm_i32_get(h, key, &val))
132 0           mPUSHi(val);
133             else
134 0           PUSHs(&PL_sv_undef);
135             }
136             } else {
137 0           ShmHeader *hdr = h->hdr;
138 0           ShmNodeI32 *nodes = (ShmNodeI32 *)h->nodes;
139 0           uint8_t *states = h->states;
140 0 0         uint32_t now = h->expires_at ? shm_now() : 0;
141             /* Phase 1: compute hashes and prefetch first probe positions */
142 0           uint32_t *hashes = NULL;
143 0           Newx(hashes, nkeys, uint32_t);
144 0           SAVEFREEPV(hashes);
145 0           RDLOCK_GUARD(hdr);
146 0           uint32_t mask = hdr->table_cap - 1;
147 0 0         for (int i = 0; i < nkeys; i++) {
148 0           hashes[i] = shm_hash_int64((int64_t)(int32_t)SvIV(ST(i + 1)));
149 0           __builtin_prefetch(&states[hashes[i] & mask], 0, 0);
150 0           __builtin_prefetch(&nodes[hashes[i] & mask], 0, 0);
151             }
152             /* Phase 2: probe each key */
153 0 0         for (int i = 0; i < nkeys; i++) {
154 0           int32_t key = (int32_t)SvIV(ST(i + 1));
155 0           uint32_t hash = hashes[i];
156 0           uint32_t pos = hash & mask;
157 0           uint8_t tag = SHM_MAKE_TAG(hash);
158 0           int found = 0;
159 0           int32_t val = 0;
160 0 0         for (uint32_t j = 0; j <= mask; j++) {
161 0           uint32_t idx = (pos + j) & mask;
162 0           uint8_t st = states[idx];
163 0 0         if (st == SHM_EMPTY) break;
164 0 0         if (st != tag) continue;
165 0 0         if (nodes[idx].key == key) {
166 0 0         if (h->expires_at && h->expires_at[idx] && now >= h->expires_at[idx]) break;
    0          
    0          
167 0           val = nodes[idx].value;
168 0           found = 1;
169 0           break;
170             }
171             }
172 0 0         if (found) mPUSHi(val);
173 0           else PUSHs(&PL_sv_undef);
174             /* Prefetch next key's probe position */
175 0 0         if (i + 1 < nkeys) {
176 0           uint32_t npos = hashes[i + 1] & mask;
177 0           __builtin_prefetch(&states[npos], 0, 0);
178 0           __builtin_prefetch(&nodes[npos], 0, 0);
179             }
180             }
181             }
182              
183             void
184             get_with_ttl(SV* self_sv, int32_t key)
185             PPCODE:
186 0 0         EXTRACT_MAP("Data::HashMap::Shared::I32", self_sv);
    0          
    0          
187             int32_t out_value;
188             int64_t out_ttl;
189 0 0         if (!shm_i32_get_with_ttl(h, key, &out_value, &out_ttl)) XSRETURN_EMPTY;
190 0 0         EXTEND(SP, 2);
191 0           mPUSHi(out_value);
192 0 0         if (out_ttl < 0) PUSHs(&PL_sv_undef);
193 0           else mPUSHi(out_ttl);
194              
195             SV*
196             stats(SV* self_sv)
197             CODE:
198 0 0         EXTRACT_MAP("Data::HashMap::Shared::I32", self_sv);
    0          
    0          
199 0           HV *hv = newHV();
200 0           hv_store(hv, "size", 4, newSVuv(shm_i32_size(h)), 0);
201 0           hv_store(hv, "capacity", 8, newSVuv(shm_i32_capacity(h)), 0);
202 0           hv_store(hv, "max_entries", 11, newSVuv(shm_i32_max_entries(h)), 0);
203 0           hv_store(hv, "tombstones", 10, newSVuv(shm_i32_tombstones(h)), 0);
204 0           hv_store(hv, "mmap_size", 9, newSVuv(shm_i32_mmap_size(h)), 0);
205 0           hv_store(hv, "arena_used", 10, newSVuv(shm_i32_arena_used(h)), 0);
206 0           hv_store(hv, "arena_cap", 9, newSVuv(shm_i32_arena_cap(h)), 0);
207 0           hv_store(hv, "evictions", 9, newSVuv(shm_i32_stat_evictions(h)), 0);
208 0           hv_store(hv, "expired", 7, newSVuv(shm_i32_stat_expired(h)), 0);
209 0           hv_store(hv, "recoveries", 10, newSVuv(shm_i32_stat_recoveries(h)), 0);
210 0           hv_store(hv, "max_size", 8, newSVuv(shm_i32_max_size(h)), 0);
211 0           hv_store(hv, "ttl", 3, newSVuv(shm_i32_ttl(h)), 0);
212 0           RETVAL = newRV_noinc((SV*)hv);
213             OUTPUT:
214             RETVAL
215              
216             bool
217             cas(SV* self_sv, int32_t key, int32_t expected, int32_t desired)
218             CODE:
219 2 50         EXTRACT_MAP("Data::HashMap::Shared::I32", self_sv);
    50          
    50          
220 2 100         RETVAL = shm_i32_cas(h, key, expected, desired);
221             OUTPUT:
222             RETVAL
223              
224             SV*
225             cas_take(SV* self_sv, int32_t key, int32_t expected)
226             CODE:
227 0 0         EXTRACT_MAP("Data::HashMap::Shared::I32", self_sv);
    0          
    0          
228             int32_t out_value;
229 0 0         if (!shm_i32_cas_take(h, key, expected, &out_value)) XSRETURN_UNDEF;
230 0           RETVAL = newSViv(out_value);
231             OUTPUT:
232             RETVAL
233              
234             bool
235             persist(SV* self_sv, int32_t key)
236             CODE:
237 0 0         EXTRACT_MAP("Data::HashMap::Shared::I32", self_sv);
    0          
    0          
238 0 0         RETVAL = shm_i32_persist(h, key);
239             OUTPUT:
240             RETVAL
241              
242             bool
243             set_ttl(SV* self_sv, int32_t key, UV ttl_sec)
244             CODE:
245 0 0         EXTRACT_MAP("Data::HashMap::Shared::I32", self_sv);
    0          
    0          
246 0 0         RETVAL = shm_i32_set_ttl(h, key, (uint32_t)ttl_sec);
247             OUTPUT:
248             RETVAL
249              
250             SV*
251             get(SV* self_sv, int32_t key)
252             CODE:
253 8 50         EXTRACT_MAP("Data::HashMap::Shared::I32", self_sv);
    50          
    50          
254             int32_t value;
255 8 50         if (!shm_i32_get(h, key, &value)) XSRETURN_UNDEF;
256 8           RETVAL = newSViv(value);
257             OUTPUT:
258             RETVAL
259              
260             bool
261             remove(SV* self_sv, int32_t key)
262             CODE:
263 500 50         EXTRACT_MAP("Data::HashMap::Shared::I32", self_sv);
    50          
    50          
264 500 50         RETVAL = shm_i32_remove(h, key);
265             OUTPUT:
266             RETVAL
267              
268             bool
269             exists(SV* self_sv, int32_t key)
270             CODE:
271 0 0         EXTRACT_MAP("Data::HashMap::Shared::I32", self_sv);
    0          
    0          
272 0 0         RETVAL = shm_i32_exists(h, key);
273             OUTPUT:
274             RETVAL
275              
276             SV*
277             incr(SV* self_sv, int32_t key)
278             CODE:
279 1 50         EXTRACT_MAP("Data::HashMap::Shared::I32", self_sv);
    50          
    50          
280             int ok;
281 1           int32_t val = shm_i32_incr_by(h, key, 1, &ok);
282 1 50         if (!ok) croak("HashMap::Shared::I32: increment failed");
283 1           RETVAL = newSViv(val);
284             OUTPUT:
285             RETVAL
286              
287             SV*
288             decr(SV* self_sv, int32_t key)
289             CODE:
290 0 0         EXTRACT_MAP("Data::HashMap::Shared::I32", self_sv);
    0          
    0          
291             int ok;
292 0           int32_t val = shm_i32_incr_by(h, key, -1, &ok);
293 0 0         if (!ok) croak("HashMap::Shared::I32: decrement failed");
294 0           RETVAL = newSViv(val);
295             OUTPUT:
296             RETVAL
297              
298             SV*
299             incr_by(SV* self_sv, int32_t key, int32_t delta)
300             CODE:
301 1 50         EXTRACT_MAP("Data::HashMap::Shared::I32", self_sv);
    50          
    50          
302             int ok;
303 1           int32_t val = shm_i32_incr_by(h, key, delta, &ok);
304 1 50         if (!ok) croak("HashMap::Shared::I32: incr_by failed");
305 1           RETVAL = newSViv(val);
306             OUTPUT:
307             RETVAL
308              
309             UV
310             size(SV* self_sv)
311             CODE:
312 2 50         EXTRACT_MAP("Data::HashMap::Shared::I32", self_sv);
    50          
    50          
313 2 50         RETVAL = (UV)shm_i32_size(h);
314             OUTPUT:
315             RETVAL
316              
317             UV
318             max_entries(SV* self_sv)
319             CODE:
320 0 0         EXTRACT_MAP("Data::HashMap::Shared::I32", self_sv);
    0          
    0          
321 0 0         RETVAL = (UV)shm_i32_max_entries(h);
322             OUTPUT:
323             RETVAL
324              
325             void
326             keys(SV* self_sv)
327             PPCODE:
328 0 0         EXTRACT_MAP("Data::HashMap::Shared::I32", self_sv);
    0          
    0          
329 0 0         uint32_t ns = h->shard_handles ? h->num_shards : 1;
330 0 0         for (uint32_t si = 0; si < ns; si++) {
331 0 0         ShmHandle *sh = h->shard_handles ? h->shard_handles[si] : h;
332 0           ShmHeader *hdr = sh->hdr;
333 0           ShmNodeI32 *nodes = (ShmNodeI32 *)sh->nodes;
334 0 0         uint32_t now = sh->expires_at ? shm_now() : 0;
335 0           RDLOCK_GUARD(hdr);
336 0 0         EXTEND(SP, hdr->size);
337 0 0         for (uint32_t i = 0; i < hdr->table_cap; i++) {
338 0 0         if (SHM_IS_LIVE(sh->states[i]) && !SHM_IS_EXPIRED(sh, i, now))
    0          
    0          
    0          
339 0 0         mXPUSHi(nodes[i].key);
340             }
341             }
342              
343             void
344             values(SV* self_sv)
345             PPCODE:
346 1 50         EXTRACT_MAP("Data::HashMap::Shared::I32", self_sv);
    50          
    50          
347 1 50         uint32_t ns = h->shard_handles ? h->num_shards : 1;
348 2 100         for (uint32_t si = 0; si < ns; si++) {
349 1 50         ShmHandle *sh = h->shard_handles ? h->shard_handles[si] : h;
350 1           ShmHeader *hdr = sh->hdr;
351 1           ShmNodeI32 *nodes = (ShmNodeI32 *)sh->nodes;
352 1 50         uint32_t now = sh->expires_at ? shm_now() : 0;
353 1           RDLOCK_GUARD(hdr);
354 1 50         EXTEND(SP, hdr->size);
355 17 100         for (uint32_t i = 0; i < hdr->table_cap; i++) {
356 16 100         if (SHM_IS_LIVE(sh->states[i]) && !SHM_IS_EXPIRED(sh, i, now))
    50          
    0          
    0          
357 10 50         mXPUSHi(nodes[i].value);
358             }
359             }
360              
361             void
362             items(SV* self_sv)
363             PPCODE:
364 0 0         EXTRACT_MAP("Data::HashMap::Shared::I32", self_sv);
    0          
    0          
365 0 0         uint32_t ns = h->shard_handles ? h->num_shards : 1;
366 0 0         for (uint32_t si = 0; si < ns; si++) {
367 0 0         ShmHandle *sh = h->shard_handles ? h->shard_handles[si] : h;
368 0           ShmHeader *hdr = sh->hdr;
369 0           ShmNodeI32 *nodes = (ShmNodeI32 *)sh->nodes;
370 0 0         uint32_t now = sh->expires_at ? shm_now() : 0;
371 0           RDLOCK_GUARD(hdr);
372 0 0         EXTEND(SP, hdr->size * 2);
373 0 0         for (uint32_t i = 0; i < hdr->table_cap; i++) {
374 0 0         if (SHM_IS_LIVE(sh->states[i]) && !SHM_IS_EXPIRED(sh, i, now)) {
    0          
    0          
    0          
375 0 0         mXPUSHi(nodes[i].key);
376 0 0         mXPUSHi(nodes[i].value);
377             }
378             }
379             }
380            
381              
382             void
383             each(SV* self_sv)
384             PPCODE:
385 0 0         EXTRACT_MAP("Data::HashMap::Shared::I32", self_sv);
    0          
    0          
386             int32_t out_key, out_value;
387 0 0         if (shm_i32_each(h, &out_key, &out_value)) {
388 0 0         EXTEND(SP, 2);
389 0 0         mXPUSHi(out_key);
390 0 0         mXPUSHi(out_value);
391 0           XSRETURN(2);
392             }
393 0           shm_i32_flush_deferred(h);
394 0           XSRETURN_EMPTY;
395              
396             void
397             iter_reset(SV* self_sv)
398             CODE:
399 0 0         EXTRACT_MAP("Data::HashMap::Shared::I32", self_sv);
    0          
    0          
400 0           shm_i32_iter_reset(h);
401 0           shm_i32_flush_deferred(h);
402              
403             void
404             clear(SV* self_sv)
405             CODE:
406 1 50         EXTRACT_MAP("Data::HashMap::Shared::I32", self_sv);
    50          
    50          
407 1           shm_i32_clear(h);
408              
409             SV*
410             to_hash(SV* self_sv)
411             CODE:
412 0 0         EXTRACT_MAP("Data::HashMap::Shared::I32", self_sv);
    0          
    0          
413 0           HV* hv = newHV();
414 0 0         uint32_t ns = h->shard_handles ? h->num_shards : 1;
415 0 0         for (uint32_t si = 0; si < ns; si++) {
416 0 0         ShmHandle *sh = h->shard_handles ? h->shard_handles[si] : h;
417 0           ShmHeader *hdr = sh->hdr;
418 0           ShmNodeI32 *nodes = (ShmNodeI32 *)sh->nodes;
419 0 0         uint32_t now = sh->expires_at ? shm_now() : 0;
420 0           RDLOCK_GUARD(hdr);
421 0 0         for (uint32_t i = 0; i < hdr->table_cap; i++) {
422 0 0         if (SHM_IS_LIVE(sh->states[i]) && !SHM_IS_EXPIRED(sh, i, now)) {
    0          
    0          
    0          
423 0           SV* val = newSViv(nodes[i].value);
424             char kbuf[24];
425 0           int klen = my_snprintf(kbuf, sizeof(kbuf), "%" IVdf, (IV)nodes[i].key);
426 0 0         if (!hv_store(hv, kbuf, klen, val, 0)) SvREFCNT_dec(val);
427             }
428             }
429             }
430            
431 0           RETVAL = newRV_noinc((SV*)hv);
432             OUTPUT:
433             RETVAL
434              
435             SV*
436             get_or_set(SV* self_sv, int32_t key, int32_t default_value)
437             CODE:
438 2 50         EXTRACT_MAP("Data::HashMap::Shared::I32", self_sv);
    50          
    50          
439             int32_t out;
440 2           int rc = shm_i32_get_or_set(h, key, default_value, &out);
441 2 50         if (!rc) XSRETURN_UNDEF;
442 2           RETVAL = newSViv(out);
443             OUTPUT:
444             RETVAL
445              
446             bool
447             put_ttl(SV* self_sv, int32_t key, int32_t value, UV ttl_sec)
448             CODE:
449 0 0         EXTRACT_MAP("Data::HashMap::Shared::I32", self_sv);
    0          
    0          
450 0 0         REQUIRE_TTL(h);
    0          
451 0 0         RETVAL = shm_i32_put_ttl(h, key, value, (uint32_t)ttl_sec);
452             OUTPUT:
453             RETVAL
454              
455             UV
456             max_size(SV* self_sv)
457             CODE:
458 0 0         EXTRACT_MAP("Data::HashMap::Shared::I32", self_sv);
    0          
    0          
459 0 0         RETVAL = (UV)shm_i32_max_size(h);
460             OUTPUT:
461             RETVAL
462              
463             UV
464             ttl(SV* self_sv)
465             CODE:
466 0 0         EXTRACT_MAP("Data::HashMap::Shared::I32", self_sv);
    0          
    0          
467 0 0         RETVAL = (UV)shm_i32_ttl(h);
468             OUTPUT:
469             RETVAL
470              
471             SV*
472             take(SV* self_sv, int32_t key)
473             CODE:
474 0 0         EXTRACT_MAP("Data::HashMap::Shared::I32", self_sv);
    0          
    0          
475             int32_t out_value;
476 0 0         if (!shm_i32_take(h, key, &out_value)) XSRETURN_UNDEF;
477 0           RETVAL = newSViv(out_value);
478             OUTPUT:
479             RETVAL
480              
481             void
482             pop(SV* self_sv)
483             PPCODE:
484 0 0         EXTRACT_MAP("Data::HashMap::Shared::I32", self_sv);
    0          
    0          
485             int32_t out_key;
486             int32_t out_val;
487 0 0         if (!shm_i32_pop(h, &out_key, &out_val)) XSRETURN_EMPTY;
488 0 0         EXTEND(SP, 2);
489 0           mPUSHi(out_key);
490 0           mPUSHi(out_val);
491              
492             void
493             shift(SV* self_sv)
494             PPCODE:
495 0 0         EXTRACT_MAP("Data::HashMap::Shared::I32", self_sv);
    0          
    0          
496             int32_t out_key;
497             int32_t out_val;
498 0 0         if (!shm_i32_shift(h, &out_key, &out_val)) XSRETURN_EMPTY;
499 0 0         EXTEND(SP, 2);
500 0           mPUSHi(out_key);
501 0           mPUSHi(out_val);
502              
503             void
504             drain(SV* self_sv, UV limit)
505             PPCODE:
506 0 0         EXTRACT_MAP("Data::HashMap::Shared::I32", self_sv);
    0          
    0          
507 0 0         if (limit == 0) XSRETURN_EMPTY;
508             shm_i32_drain_entry *entries;
509 0 0         Newxz(entries, limit, shm_i32_drain_entry);
510            
511 0           SAVEFREEPV(entries);
512 0           char *buf = NULL; uint32_t buf_cap = 0;
513 0           uint32_t n = shm_i32_drain(h, (uint32_t)limit, entries, &buf, &buf_cap);
514            
515 0 0         EXTEND(SP, n * 2);
516 0 0         for (uint32_t i = 0; i < n; i++) {
517 0           mPUSHi(entries[i].key);
518 0           mPUSHi(entries[i].value);
519             }
520 0 0         if (buf) free(buf);
521            
522              
523             UV
524             flush_expired(SV* self_sv)
525             CODE:
526 0 0         EXTRACT_MAP("Data::HashMap::Shared::I32", self_sv);
    0          
    0          
527 0 0         RETVAL = (UV)shm_i32_flush_expired(h);
528             OUTPUT:
529             RETVAL
530              
531             void
532             flush_expired_partial(SV* self_sv, UV limit)
533             PPCODE:
534 0 0         EXTRACT_MAP("Data::HashMap::Shared::I32", self_sv);
    0          
    0          
535 0           int done = 0;
536 0           uint32_t flushed = shm_i32_flush_expired_partial(h, (uint32_t)limit, &done);
537 0 0         EXTEND(SP, 2);
538 0           mPUSHu(flushed);
539 0           mPUSHi(done);
540              
541             UV
542             mmap_size(SV* self_sv)
543             CODE:
544 0 0         EXTRACT_MAP("Data::HashMap::Shared::I32", self_sv);
    0          
    0          
545 0           RETVAL = (UV)shm_i32_mmap_size(h);
546             OUTPUT:
547             RETVAL
548              
549             bool
550             touch(SV* self_sv, int32_t key)
551             CODE:
552 0 0         EXTRACT_MAP("Data::HashMap::Shared::I32", self_sv);
    0          
    0          
553 0 0         RETVAL = shm_i32_touch(h, key);
554             OUTPUT:
555             RETVAL
556              
557             bool
558             reserve(SV* self_sv, UV target)
559             CODE:
560 0 0         EXTRACT_MAP("Data::HashMap::Shared::I32", self_sv);
    0          
    0          
561 0 0         RETVAL = shm_i32_reserve(h, (uint32_t)target);
562             OUTPUT:
563             RETVAL
564              
565             UV
566             stat_evictions(SV* self_sv)
567             CODE:
568 0 0         EXTRACT_MAP("Data::HashMap::Shared::I32", self_sv);
    0          
    0          
569 0           RETVAL = (UV)shm_i32_stat_evictions(h);
570             OUTPUT:
571             RETVAL
572              
573             UV
574             stat_expired(SV* self_sv)
575             CODE:
576 0 0         EXTRACT_MAP("Data::HashMap::Shared::I32", self_sv);
    0          
    0          
577 0           RETVAL = (UV)shm_i32_stat_expired(h);
578             OUTPUT:
579             RETVAL
580              
581             UV
582             stat_recoveries(SV* self_sv)
583             CODE:
584 0 0         EXTRACT_MAP("Data::HashMap::Shared::I32", self_sv);
    0          
    0          
585 0 0         RETVAL = (UV)shm_i32_stat_recoveries(h);
586             OUTPUT:
587             RETVAL
588              
589             UV
590             arena_used(SV* self_sv)
591             CODE:
592 0 0         EXTRACT_MAP("Data::HashMap::Shared::I32", self_sv);
    0          
    0          
593 0           RETVAL = (UV)shm_i32_arena_used(h);
594             OUTPUT:
595             RETVAL
596              
597             UV
598             arena_cap(SV* self_sv)
599             CODE:
600 0 0         EXTRACT_MAP("Data::HashMap::Shared::I32", self_sv);
    0          
    0          
601 0           RETVAL = (UV)shm_i32_arena_cap(h);
602             OUTPUT:
603             RETVAL
604              
605             bool
606             add(SV* self_sv, int32_t key, int32_t value)
607             CODE:
608 2 50         EXTRACT_MAP("Data::HashMap::Shared::I32", self_sv);
    50          
    50          
609 2 100         RETVAL = shm_i32_add(h, key, value);
610             OUTPUT:
611             RETVAL
612              
613             bool
614             add_ttl(SV* self_sv, int32_t key, int32_t value, UV ttl_sec)
615             CODE:
616 2 50         EXTRACT_MAP("Data::HashMap::Shared::I32", self_sv);
    50          
    50          
617 2 50         REQUIRE_TTL(h);
    50          
618 2 100         RETVAL = shm_i32_add_ttl(h, key, value, (uint32_t)ttl_sec);
619             OUTPUT:
620             RETVAL
621              
622             bool
623             update(SV* self_sv, int32_t key, int32_t value)
624             CODE:
625 1 50         EXTRACT_MAP("Data::HashMap::Shared::I32", self_sv);
    50          
    50          
626 1 50         RETVAL = shm_i32_update(h, key, value);
627             OUTPUT:
628             RETVAL
629              
630             bool
631             update_ttl(SV* self_sv, int32_t key, int32_t value, UV ttl_sec)
632             CODE:
633 0 0         EXTRACT_MAP("Data::HashMap::Shared::I32", self_sv);
    0          
    0          
634 0 0         REQUIRE_TTL(h);
    0          
635 0 0         RETVAL = shm_i32_update_ttl(h, key, value, (uint32_t)ttl_sec);
636             OUTPUT:
637             RETVAL
638              
639             SV*
640             swap(SV* self_sv, int32_t key, int32_t value)
641             CODE:
642 1 50         EXTRACT_MAP("Data::HashMap::Shared::I32", self_sv);
    50          
    50          
643             int32_t out_value;
644 1           int rc = shm_i32_swap(h, key, value, &out_value);
645 1 50         if (rc != 1) XSRETURN_UNDEF;
646 1           RETVAL = newSViv(out_value);
647             OUTPUT:
648             RETVAL
649              
650             SV*
651             path(SV* self_sv)
652             CODE:
653 0 0         EXTRACT_MAP("Data::HashMap::Shared::I32", self_sv);
    0          
    0          
654 0 0         RETVAL = h->path ? newSVpv(h->path, 0) : &PL_sv_undef;
655             OUTPUT:
656             RETVAL
657              
658             bool
659             unlink(SV* self_or_class, ...)
660             CODE:
661             const char *p;
662 0 0         if (SvROK(self_or_class) && SvOBJECT(SvRV(self_or_class))) {
    0          
663 0           ShmHandle* h = INT2PTR(ShmHandle*, SvIV(SvRV(self_or_class)));
664 0 0         if (!h) croak("Attempted to use a destroyed Data::HashMap::Shared::I32 object");
665 0           p = h->path;
666             } else {
667 0 0         if (items < 2) croak("Usage: Data::HashMap::Shared::I32->unlink($path)");
668 0           p = SvPV_nolen(ST(1));
669             }
670 0 0         RETVAL = (SvROK(self_or_class) && SvOBJECT(SvRV(self_or_class))) ?
    0          
671 0 0         shm_unlink_sharded(INT2PTR(ShmHandle*, SvIV(SvRV(self_or_class)))) :
672 0           shm_unlink_path(p);
673             OUTPUT:
674             RETVAL
675              
676             SV*
677             ttl_remaining(SV* self_sv, int32_t key)
678             CODE:
679 0 0         EXTRACT_MAP("Data::HashMap::Shared::I32", self_sv);
    0          
    0          
680 0           int64_t remaining = shm_i32_ttl_remaining(h, key);
681 0 0         if (remaining < 0) XSRETURN_UNDEF;
682 0           RETVAL = newSViv(remaining);
683             OUTPUT:
684             RETVAL
685              
686             UV
687             capacity(SV* self_sv)
688             CODE:
689 0 0         EXTRACT_MAP("Data::HashMap::Shared::I32", self_sv);
    0          
    0          
690 0 0         RETVAL = (UV)shm_i32_capacity(h);
691             OUTPUT:
692             RETVAL
693              
694             UV
695             tombstones(SV* self_sv)
696             CODE:
697 0 0         EXTRACT_MAP("Data::HashMap::Shared::I32", self_sv);
    0          
    0          
698 0 0         RETVAL = (UV)shm_i32_tombstones(h);
699             OUTPUT:
700             RETVAL
701              
702             SV*
703             cursor(SV* self_sv)
704             CODE:
705 0 0         EXTRACT_MAP("Data::HashMap::Shared::I32", self_sv);
    0          
    0          
706 0           ShmCursor* c = shm_cursor_create(h);
707 0 0         if (!c) croak("Failed to allocate cursor");
708 0           RETVAL = sv_setref_pv(newSV(0), "Data::HashMap::Shared::I32::Cursor", (void*)c);
709             OUTPUT:
710             RETVAL
711              
712             MODULE = Data::HashMap::Shared PACKAGE = Data::HashMap::Shared::I32::Cursor
713             PROTOTYPES: DISABLE
714              
715             void
716             DESTROY(SV* self_sv)
717             CODE:
718 0 0         if (!SvROK(self_sv)) return;
719 0           ShmCursor* c = INT2PTR(ShmCursor*, SvIV(SvRV(self_sv)));
720 0 0         if (!c) return;
721 0           ShmHandle* h = c->current;
722 0           shm_cursor_destroy(c);
723 0 0         if (h) shm_i32_flush_deferred(h);
724 0           sv_setiv(SvRV(self_sv), 0);
725              
726             void
727             next(SV* self_sv)
728             PPCODE:
729 0 0         EXTRACT_CURSOR("Data::HashMap::Shared::I32::Cursor", self_sv);
    0          
    0          
730             int32_t out_key; int32_t out_value;
731 0 0         if (shm_i32_cursor_next(c, &out_key, &out_value)) {
732 0 0         EXTEND(SP, 2);
733 0 0         mXPUSHi(out_key);
734 0 0         mXPUSHi(out_value);
735 0           XSRETURN(2);
736             }
737 0           XSRETURN_EMPTY;
738              
739             void
740             reset(SV* self_sv)
741             CODE:
742 0 0         EXTRACT_CURSOR("Data::HashMap::Shared::I32::Cursor", self_sv);
    0          
    0          
743 0           shm_i32_cursor_reset(c);
744              
745             bool
746             seek(SV* self_sv, int32_t key)
747             CODE:
748 0 0         EXTRACT_CURSOR("Data::HashMap::Shared::I32::Cursor", self_sv);
    0          
    0          
749 0 0         RETVAL = shm_i32_cursor_seek(c, key);
750             OUTPUT:
751             RETVAL
752