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.
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