niftie-multiton 0.5 → 0.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/lib/multiton.rb +135 -31
  2. data/multiton.gemspec +2 -2
  3. 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.extended(base)
5
- base.instance_variable_set(:@instance_map, Map.new)
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
- end
9
- end
10
-
11
- def inherited(desc)
12
- super
13
- class << desc
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
- end
18
- end
19
-
20
- def instance(*args, &block)
21
- key = begin
22
- multiton_key(*args, &block)
23
- rescue NameError
24
- args
25
- end
26
-
27
- instance_map.synchronize do
28
- instance_map[key] ||= begin
29
- multiton_new(*args, &block)
30
- rescue NameError
31
- new(*args, &block)
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, val)
47
- synchronize { @store[key] = val }
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 delete_if(&block)
55
- synchronize { @store.delete_if(&block) }
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 { @store.delete(key) }
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.5'
7
- s.date = '2008-11-28'
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.5"
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-11-28 00:00:00 -08:00
12
+ date: 2008-12-04 00:00:00 -08:00
13
13
  default_executable:
14
14
  dependencies: []
15
15