/
Timeout.pm6
executable file
·114 lines (95 loc) · 2.55 KB
/
Timeout.pm6
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#!/usr/bin/env perl6
use Hash::Agnostic;
role Hash::Timeout:ver<0.0.1>:auth<cpan:FRITH>[$timeout = 3600] does Hash::Agnostic
{
has %!hash;
has %!cancel;
method AT-KEY($key) is raw {
Proxy.new(
FETCH => { %!hash{$key} },
STORE => -> $, \v is raw { %!hash{$key} = v }
);
}
method EXISTS-KEY($key) {
%!hash.{$key}.DEFINITE
}
method ASSIGN-KEY(\key, \value) {
.cancel with %!cancel{key};
%!cancel{key} := $*SCHEDULER.cue({ %!hash{key}:delete }, :in($timeout));
%!hash{key} = value;
}
method BIND-KEY(\key, \value) {
.cancel with %!cancel{key};
%!cancel{key} := $*SCHEDULER.cue({ %!hash{key}:delete }, :in($timeout));
%!hash{key} := value;
}
method DELETE-KEY(\key) {
.cancel with %!cancel{key};
%!hash{key}:delete
}
method CLEAR() {
for %!cancel.keys -> \k {
.cancel with %!cancel{k}
}
%!hash = Hash.new;
%!cancel = Hash.new;
}
multi method STORE(::?ROLE:D: \values, :$initialize) {
self.CLEAR;
given values.WHAT {
when List { self!STOREL(values) }
when Hash { self!STOREH(values) }
}
self;
}
method !STOREH(%hash --> Int:D) {
for %hash.kv -> \k, \v {
self.ASSIGN-KEY(k, v);
}
}
method !STOREL(@values --> Int:D) {
my $last := Mu;
my int $found;
for @values {
if $_ ~~ Pair {
self.ASSIGN-KEY(.key, .value);
++$found;
} elsif $_ ~~ Failure {
.throw
} elsif !$last =:= Mu {
self.ASSIGN-KEY($last, $_);
++$found;
$last := Mu;
} elsif $_ ~~ Map {
$found += self!STOREL([.pairs])
} else {
$last := $_;
}
}
$last =:= Mu
?? $found
!! X::Hash::Store::OddNumber.new(:$found, :$last).throw
}
method keys { %!hash.keys }
method iterator() { %!hash.pairs.iterator }
method timeout { $timeout }
method debug { %!hash.elems, %!cancel.elems }
}
=begin pod
=head1 NAME
Hash::Timeout - Role for hashes whose elements timeout and disappear
=head1 SYNOPSIS
use Hash::Timeout;
my %cookies does Hash::Timeout[0.5];
%cookies<user001> = 'id';
sleep 1;
say %cookies.elems; # prints 0
=head1 DESCRIPTION
Hash::Timeout provides a C<role> that can be mixed with a C<Hash>.
There's just one optional parameter, the timeout, which accepts fractional seconds and defaults to 1 hour.
=head1 AUTHOR
Fernando Santagata <nando.santagata@gmail.com>
=head1 COPYRIGHT AND LICENSE
Copyright 2018 Fernando Santagata
This library is free software; you can redistribute it and/or modify it under the Artistic License 2.0.
=end pod