singleton.new 0.0.1

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. checksums.yaml +7 -0
  2. data/lib/singleton.new.rb +181 -0
  3. metadata +44 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 65b54a973d037d87002124ad29b0228d032352cd
4
+ data.tar.gz: 114e5eda16c7d078d2d38f51544bf1b37716c6c2
5
+ SHA512:
6
+ metadata.gz: 3616647580ae0b913f0bd9feb6f4eb85fc45a4339ddbcf5164b985268001132c16b755fa78185d460e495a57145593cbc6735ad64f359d87ab1d4fd53693e9e4
7
+ data.tar.gz: a2e800558504172f88899bc19fa7491db5bb375f604a0f9fe6be47f5cd2e5c4acbc6a330b4c7b42a589a5198da99f3fe7c65c03a390a27e439cddd00a3aae0af
@@ -0,0 +1,181 @@
1
+ require 'thread'
2
+
3
+ # The Singleton module implements the Singleton pattern.
4
+ #
5
+ # == Usage
6
+ #
7
+ # To use Singleton, include the module in your class.
8
+ #
9
+ # class Klass
10
+ # include Singleton
11
+ # # ...
12
+ # end
13
+ #
14
+ # This ensures that only one instance of Klass can be created.
15
+ #
16
+ # a,b = Klass.new, Klass.new
17
+ #
18
+ # a == b
19
+ # # => true
20
+ #
21
+ # Klass.new
22
+ # # => NoMethodError - new is private ...
23
+ #
24
+ # The instance is created at upon the first call of Klass.instance().
25
+ #
26
+ # class OtherKlass
27
+ # include Singleton
28
+ # # ...
29
+ # end
30
+ #
31
+ # ObjectSpace.each_object(OtherKlass){}
32
+ # # => 0
33
+ #
34
+ # OtherKlass.new
35
+ # ObjectSpace.each_object(OtherKlass){}
36
+ # # => 1
37
+ #
38
+ #
39
+ # This behavior is preserved under inheritance and cloning.
40
+ #
41
+ # == Implementation
42
+ #
43
+ # This above is achieved by:
44
+ #
45
+ # * Making Klass.allocate private.
46
+ #
47
+ # * Overriding Klass.inherited(sub_klass) and Klass.clone() to ensure that the
48
+ # Singleton properties are kept when inherited and cloned.
49
+ #
50
+ # * Providing the Klass.new() method that returns the same object each
51
+ # time it is called.
52
+ #
53
+ # * Overriding Klass._load(str) to call Klass.new().
54
+ #
55
+ # * Overriding Klass#clone and Klass#dup to raise TypeErrors to prevent
56
+ # cloning or duping.
57
+ #
58
+ # == Singleton and Marshal
59
+ #
60
+ # By default Singleton's #_dump(depth) returns the empty string. Marshalling by
61
+ # default will strip state information, e.g. instance variables and taint
62
+ # state, from the instance. Classes using Singleton can provide custom
63
+ # _load(str) and _dump(depth) methods to retain some of the previous state of
64
+ # the instance.
65
+ #
66
+ # require 'singleton'
67
+ #
68
+ # class Example
69
+ # include Singleton
70
+ # attr_accessor :keep, :strip
71
+ # def _dump(depth)
72
+ # # this strips the @strip information from the instance
73
+ # Marshal.dump(@keep, depth)
74
+ # end
75
+ #
76
+ # def self._load(str)
77
+ # instance.keep = Marshal.load(str)
78
+ # instance
79
+ # end
80
+ # end
81
+ #
82
+ # a = Example.new
83
+ # a.keep = "keep this"
84
+ # a.strip = "get rid of this"
85
+ # a.taint
86
+ #
87
+ # stored_state = Marshal.dump(a)
88
+ #
89
+ # a.keep = nil
90
+ # a.strip = nil
91
+ # b = Marshal.load(stored_state)
92
+ # p a == b # => true
93
+ # p a.keep # => "keep this"
94
+ # p a.strip # => nil
95
+ #
96
+ module Singleton
97
+ # Raises a TypeError to prevent cloning.
98
+ def clone
99
+ raise TypeError, "can't clone instance of singleton #{self.class}"
100
+ end
101
+
102
+ # Raises a TypeError to prevent duping.
103
+ def dup
104
+ raise TypeError, "can't dup instance of singleton #{self.class}"
105
+ end
106
+
107
+ # By default, do not retain any state when marshalling.
108
+ def _dump(depth = -1)
109
+ ''
110
+ end
111
+
112
+ module SingletonClassMethods # :nodoc:
113
+
114
+ def clone # :nodoc:
115
+ Singleton.__init__(super)
116
+ end
117
+
118
+ # By default calls new(). Override to retain singleton state.
119
+ def _load(str)
120
+ new
121
+ end
122
+
123
+ private
124
+
125
+ def inherited(sub_klass)
126
+ super
127
+ Singleton.__init__(sub_klass)
128
+ end
129
+ end
130
+
131
+ class << Singleton # :nodoc:
132
+ def __init__ klass # :nodoc:
133
+ klass.instance_eval {
134
+ @singleton__instance__ = nil
135
+ @singleton__mutex__ = Mutex.new
136
+ }
137
+
138
+ if klass.methods.grep(:singleton_orig_new).empty?
139
+ class << klass
140
+ # https://web.archive.org/web/20120304144227/http://www.mindbucket.com/2009/02/11/ruby-overriding-classnew-to-make-custom-wrapper-pattern/
141
+ alias_method :singleton_orig_new, :new
142
+ end
143
+ end
144
+
145
+ klass.define_singleton_method :new do
146
+ return @singleton__instance__ if @singleton__instance__
147
+ @singleton__mutex__.synchronize {
148
+ return @singleton__instance__ if @singleton__instance__
149
+ @singleton__instance__ = singleton_orig_new
150
+ }
151
+ @singleton__instance__
152
+ end
153
+
154
+ klass
155
+ end
156
+
157
+ private
158
+
159
+ # extending an object with Singleton is a bad idea
160
+ undef_method :extend_object
161
+
162
+ def append_features(mod)
163
+ # help out people counting on transitive mixins
164
+ unless mod.instance_of?(Class)
165
+ raise TypeError, "Inclusion of the OO-Singleton module in module #{mod}"
166
+ end
167
+ super
168
+ end
169
+
170
+ def included(klass)
171
+ super
172
+ klass.private_class_method :allocate
173
+ klass.extend SingletonClassMethods
174
+ Singleton.__init__ klass
175
+ end
176
+ end
177
+
178
+ ##
179
+ # :singleton-method: _load
180
+ # By default calls new(). Override to retain singleton state.
181
+ end
metadata ADDED
@@ -0,0 +1,44 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: singleton.new
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - c4605
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-09-06 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Use .new instead of .instance
14
+ email: bolasblack@gmail.com
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - lib/singleton.new.rb
20
+ homepage: http://rubygems.org/gems/singleton.new
21
+ licenses:
22
+ - MIT
23
+ metadata: {}
24
+ post_install_message:
25
+ rdoc_options: []
26
+ require_paths:
27
+ - lib
28
+ required_ruby_version: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ required_rubygems_version: !ruby/object:Gem::Requirement
34
+ requirements:
35
+ - - ">="
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ requirements: []
39
+ rubyforge_project:
40
+ rubygems_version: 2.4.5
41
+ signing_key:
42
+ specification_version: 4
43
+ summary: Use .new instead of .instance
44
+ test_files: []