93
93
#
94
94
module Singleton
95
95
VERSION = "0.2.0"
96
+ VERSION . freeze
96
97
97
- # Raises a TypeError to prevent cloning.
98
- def clone
99
- raise TypeError , "can't clone instance of singleton #{ self . class } "
100
- end
98
+ module SingletonInstanceMethods
99
+ # Raises a TypeError to prevent cloning.
100
+ def clone
101
+ raise TypeError , "can't clone instance of singleton #{ self . class } "
102
+ end
101
103
102
- # Raises a TypeError to prevent duping.
103
- def dup
104
- raise TypeError , "can't dup instance of singleton #{ self . class } "
105
- end
104
+ # Raises a TypeError to prevent duping.
105
+ def dup
106
+ raise TypeError , "can't dup instance of singleton #{ self . class } "
107
+ end
106
108
107
- # By default, do not retain any state when marshalling.
108
- def _dump ( depth = -1 )
109
- ''
109
+ # By default, do not retain any state when marshalling.
110
+ def _dump ( depth = -1 )
111
+ ''
112
+ end
110
113
end
114
+ include SingletonInstanceMethods
111
115
112
116
module SingletonClassMethods # :nodoc:
113
117
@@ -121,7 +125,7 @@ def _load(str)
121
125
end
122
126
123
127
def instance # :nodoc:
124
- @singleton__instance__ || @singleton__mutex__ . synchronize { @singleton__instance__ ||= new }
128
+ @singleton__instance__ || @singleton__mutex__ . synchronize { @singleton__instance__ ||= set_instance ( new ) }
125
129
end
126
130
127
131
private
@@ -130,22 +134,42 @@ def inherited(sub_klass)
130
134
super
131
135
Singleton . __init__ ( sub_klass )
132
136
end
137
+
138
+ def set_instance ( val )
139
+ @singleton__instance__ = val
140
+ end
141
+
142
+ def set_mutex ( val )
143
+ @singleton__mutex__ = val
144
+ end
133
145
end
134
146
135
- class << Singleton # :nodoc:
147
+ def self . module_with_class_methods
148
+ SingletonClassMethods
149
+ end
150
+
151
+ module SingletonClassProperties
152
+
153
+ def self . included ( c )
154
+ # extending an object with Singleton is a bad idea
155
+ c . undef_method :extend_object
156
+ end
157
+
158
+ def self . extended ( c )
159
+ # extending an object with Singleton is a bad idea
160
+ c . singleton_class . undef_method :extend_object
161
+ end
162
+
136
163
def __init__ ( klass ) # :nodoc:
137
164
klass . instance_eval {
138
- @singleton__instance__ = nil
139
- @singleton__mutex__ = Thread ::Mutex . new
165
+ set_instance ( nil )
166
+ set_mutex ( Thread ::Mutex . new )
140
167
}
141
168
klass
142
169
end
143
170
144
171
private
145
172
146
- # extending an object with Singleton is a bad idea
147
- undef_method :extend_object
148
-
149
173
def append_features ( mod )
150
174
# help out people counting on transitive mixins
151
175
unless mod . instance_of? ( Class )
@@ -157,10 +181,11 @@ def append_features(mod)
157
181
def included ( klass )
158
182
super
159
183
klass . private_class_method :new , :allocate
160
- klass . extend SingletonClassMethods
184
+ klass . extend module_with_class_methods
161
185
Singleton . __init__ ( klass )
162
186
end
163
187
end
188
+ extend SingletonClassProperties
164
189
165
190
##
166
191
# :singleton-method: _load
@@ -170,3 +195,44 @@ def included(klass)
170
195
# :singleton-method: instance
171
196
# Returns the singleton instance.
172
197
end
198
+
199
+ module PerRactorSingleton
200
+ include Singleton ::SingletonInstanceMethods
201
+
202
+ module PerRactorSingletonClassMethods
203
+ include Singleton ::SingletonClassMethods
204
+ def instance
205
+ set_mutex ( Thread ::Mutex . new ) if Ractor . current [ mutex_key ] . nil?
206
+ return Ractor . current [ instance_key ] if Ractor . current [ instance_key ]
207
+ Ractor . current [ mutex_key ] . synchronize {
208
+ return Ractor . current [ instance_key ] if Ractor . current [ instance_key ]
209
+ set_instance ( new ( ) )
210
+ }
211
+ Ractor . current [ instance_key ]
212
+ end
213
+
214
+ private
215
+
216
+ def instance_key
217
+ :"__PerRactorSingleton_instance_with_class_id_#{ object_id } __"
218
+ end
219
+
220
+ def mutex_key
221
+ :"__PerRactorSingleton_mutex_with_class_id_#{ object_id } __"
222
+ end
223
+
224
+ def set_instance ( val )
225
+ Ractor . current [ instance_key ] = val
226
+ end
227
+
228
+ def set_mutex ( val )
229
+ Ractor . current [ mutex_key ] = val
230
+ end
231
+ end
232
+
233
+ def self . module_with_class_methods
234
+ PerRactorSingletonClassMethods
235
+ end
236
+
237
+ extend Singleton ::SingletonClassProperties
238
+ end
0 commit comments