File Coverage

xs/i16.xs
Criterion Covered Total %
statement 82 291 28.1
branch 105 570 18.4
condition n/a
subroutine n/a
pod n/a
total 187 861 21.7


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