File Coverage

xs/i16.xs
Criterion Covered Total %
statement 82 301 27.2
branch 106 600 17.6
condition n/a
subroutine n/a
pod n/a
total 188 901 20.8


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