niftie-multiton 0.5 → 0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/multiton.rb +135 -31
- data/multiton.gemspec +2 -2
- metadata +2 -2
data/lib/multiton.rb
CHANGED
@@ -1,62 +1,166 @@
|
|
1
1
|
require 'monitor'
|
2
2
|
|
3
|
+
module Kernel
|
4
|
+
def Multiton(size)
|
5
|
+
@instance_map = Multiton::LRUMap.new(size)
|
6
|
+
Multiton
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
3
10
|
module Multiton
|
4
|
-
def self.
|
5
|
-
base.
|
11
|
+
def self.included(base)
|
12
|
+
base.instance_eval do
|
13
|
+
@instance_map ||= Multiton::Map.new
|
14
|
+
end
|
15
|
+
|
6
16
|
class << base
|
7
17
|
attr_reader :instance_map
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
def instance_map
|
15
|
-
superclass.instance_map
|
18
|
+
|
19
|
+
def inherited(subclass)
|
20
|
+
def subclass.instance_map
|
21
|
+
superclass.instance_map
|
22
|
+
end
|
23
|
+
super
|
16
24
|
end
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
25
|
+
|
26
|
+
def instance(*args, &block)
|
27
|
+
key = begin
|
28
|
+
multiton_key(*args, &block)
|
29
|
+
rescue NameError
|
30
|
+
args
|
31
|
+
end
|
32
|
+
|
33
|
+
instance_map.synchronize do
|
34
|
+
instance_map[key] ||= begin
|
35
|
+
multiton_new(*args, &block)
|
36
|
+
rescue NameError
|
37
|
+
new(*args, &block)
|
38
|
+
end
|
39
|
+
end
|
32
40
|
end
|
33
41
|
end
|
42
|
+
|
34
43
|
end
|
35
44
|
|
36
45
|
class Map
|
37
46
|
def initialize
|
38
|
-
@store = {}
|
39
47
|
extend MonitorMixin
|
48
|
+
@store = {}
|
40
49
|
end
|
41
50
|
|
42
51
|
def [](key)
|
43
52
|
@store[key]
|
44
53
|
end
|
45
54
|
|
46
|
-
def []=(key,
|
47
|
-
synchronize { @store[key] =
|
55
|
+
def []=(key, value)
|
56
|
+
synchronize { @store[key] = value }
|
57
|
+
end
|
58
|
+
|
59
|
+
def delete_if(&block)
|
60
|
+
synchronize { @store.delete_if(&block) }
|
61
|
+
self
|
62
|
+
end
|
63
|
+
|
64
|
+
def delete(key)
|
65
|
+
synchronize { @store.delete(key) }
|
48
66
|
end
|
49
67
|
|
50
68
|
def clear
|
51
69
|
synchronize { @store.clear }
|
52
70
|
end
|
53
71
|
|
54
|
-
def
|
55
|
-
|
72
|
+
def size
|
73
|
+
@store.size
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
class LRUMap < Map
|
78
|
+
Item = Struct.new(:key, :value, :prev, :next)
|
79
|
+
|
80
|
+
def initialize(limit)
|
81
|
+
raise ArgumentError, "limit must be an Integer" unless limit.is_a? Integer
|
82
|
+
super()
|
83
|
+
@limit = limit
|
84
|
+
setup
|
85
|
+
end
|
86
|
+
|
87
|
+
def [](key)
|
88
|
+
if item = super
|
89
|
+
synchronize do
|
90
|
+
remove(item)
|
91
|
+
append(head, item)
|
92
|
+
end
|
93
|
+
item.value
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def []=(key, value)
|
98
|
+
item = Item.new(key, value)
|
99
|
+
synchronize do
|
100
|
+
super(key, item)
|
101
|
+
|
102
|
+
delete(last.key) if size > @limit
|
103
|
+
append(head, item)
|
104
|
+
end
|
105
|
+
item.value
|
106
|
+
end
|
107
|
+
|
108
|
+
def delete_if
|
109
|
+
synchronize do
|
110
|
+
@store.keys.each { |key| delete(key) if yield key, @store[key].value }
|
111
|
+
end
|
112
|
+
self
|
56
113
|
end
|
57
114
|
|
58
115
|
def delete(key)
|
59
|
-
synchronize
|
116
|
+
synchronize do
|
117
|
+
if item = super
|
118
|
+
remove(item)
|
119
|
+
return item.value
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def clear
|
125
|
+
synchronize do
|
126
|
+
super
|
127
|
+
setup
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
private
|
132
|
+
|
133
|
+
def head
|
134
|
+
@head
|
135
|
+
end
|
136
|
+
|
137
|
+
def tail
|
138
|
+
@tail
|
139
|
+
end
|
140
|
+
|
141
|
+
def last
|
142
|
+
@tail.prev
|
143
|
+
end
|
144
|
+
|
145
|
+
def setup
|
146
|
+
@head = Item.new
|
147
|
+
@tail = Item.new
|
148
|
+
join(head, tail)
|
149
|
+
end
|
150
|
+
|
151
|
+
def remove(item)
|
152
|
+
join(item.prev, item.next)
|
153
|
+
item
|
154
|
+
end
|
155
|
+
|
156
|
+
def append(x, y)
|
157
|
+
join(y, x.next)
|
158
|
+
join(x, y)
|
159
|
+
end
|
160
|
+
|
161
|
+
def join(x, y)
|
162
|
+
x.next = y
|
163
|
+
y.prev = x
|
60
164
|
end
|
61
165
|
end
|
62
166
|
|
data/multiton.gemspec
CHANGED
@@ -3,8 +3,8 @@ Gem::Specification.new do |s|
|
|
3
3
|
s.homepage = 'http://github.com/niftie/multiton'
|
4
4
|
s.author = 'Nicolas Steenlant'
|
5
5
|
s.email = 'nicolas.steenlant@gmail.com'
|
6
|
-
s.version = '0.
|
7
|
-
s.date = '2008-
|
6
|
+
s.version = '0.6'
|
7
|
+
s.date = '2008-12-04'
|
8
8
|
s.summary = ''
|
9
9
|
s.files = ['multiton.gemspec', 'lib/multiton.rb']
|
10
10
|
s.require_path = 'lib'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: niftie-multiton
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: "0.
|
4
|
+
version: "0.6"
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nicolas Steenlant
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2008-
|
12
|
+
date: 2008-12-04 00:00:00 -08:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|