Although Ruby allows the use of global variables, I still prefer not to
use them. I am wary that someone else might have chosen the same
variable name as me, and besides, they just don’t feel properly OO.
Singletons seem like the best solution to this problem, but I’m
concerned about garbage collection.
Say I have two classes that each do a lot of work. I instantiate one,
do a bunch of calculations and return a result. I then instantiate a
second class and do a bunch more work on that result. Say both classes
want to use this global / singleton, and want to make sure that it
doesn’t get garbage collected between calls, what’s the best way to do
this?
Example code:
class Stats
include Singleton
def initialize @count = 0
end
def sawAnother @count += 1
end
end
class Worker1
def doStuff @stats = Stats.instance
…
end
end
class Worker2
def doOtherStuff @stats = Stats.instance
…
end
def showResult @stats.dumpStats
end
end
w1 = Worker1.new
w1.doStuff
w2 = Worker2.new
w2.doStuff
w2.showResult
What I want to avoid is having the Stats singleton get garbage
collected between calls to w1.doStuff and the creation of Worker2.new.
Any comments?
Classes are global and a singleton instance will be referenced by a
static variable/class variable of the singleton class. (See the design
patterns book by the GOF.) I can’t see a problem for the GC there.
It’s easy to test: Invoke the GC within your example. Does it still
work?
I recommend that you try to avoid using global access paths to
singletons whenever you design a big application. The application will
be easier to maintain if you identify components and make each
component access global objects via access paths local to that
component. You could use another singleton to do so , e. g.
MyComponentGlobals.instance.getStats.
You can find some discussions about the problems singletons might
introduce here:
Search for the thread “Q: Singleton” in comp.lang.smalltalk
Although Ruby allows the use of global variables, I still prefer not to
use them. I am wary that someone else might have chosen the same
variable name as me, and besides, they just don’t feel properly OO.
Singletons seem like the best solution to this problem, but I’m
concerned about garbage collection.
Say I have two classes that each do a lot of work. I instantiate one,
do a bunch of calculations and return a result. I then instantiate a
second class and do a bunch more work on that result. Say both classes
want to use this global / singleton, and want to make sure that it
doesn’t get garbage collected between calls, what’s the best way to do
this?
Sorry I wasn’t more clear. I meant to give a case where there are no more
references to w1 after the doStuff method is called. It’s not w1 or w2 being
garbage-collected that I’m worried about, it’s the “@stats” variable that
they both use, which is a singleton instance.
What I’d like is a way to make sure that the instance variable of a singleton
object I create in the first class still exists by the time the second class
tries to create it.
class Worker1
def doStuff @stats = Stats.instance # The instance of the stats singleton is created
…
end
end
class Worker2
def doOtherStuff @stats = Stats.instance # It still exists here
…
end
def showResult @stats.dumpStats
end
end
Worker1.new.doStuff
Here is where I don’t want the stats singleton to be GC’d
w = Worker2.new
w.doOtherStuff
w.showResult
I guess what I’m looking for is a way to create a hidden global variable when
a singleton instance is created, in a way that there is no danger of name
clashes. Because there would always be at least one reference to the
singleton, it would only get GC’d at the end of the program’s lifetime, and
this would guarantee it would only ever be created once.
Some examples of where this would be useful:
There are a large number of unrelated classes which should dump debugging
info into a log. You want a new log each time the program is run, and you
want to replace the old log. So you create / truncate the file when the
first class needs to log something, and each other class appends to the log,
until the end of the program.
The act of creating an instance of a class is long and time-consuming, so
you only want it to happen once for the entire lifetime of the program,
whether it’s used frequently or not
I hope I explained it better this time.
Ben
···
On Tue July 29 2003 3:50 am, Yukihiro Matsumoto wrote:
w1 = Worker1.new
w1.doStuff
w2 = Worker2.new
w2.doStuff
w2.showResult
I don’t know what you meant. If w1 is referenced from somewhere, w1
will not be garbage-collected.
Ah, how cool. I have never (knowingly) encountered a class instance variable
before, especially not one that contained an instance of itself. Now that I
take a closer look it all makes good sense, and does exactly what I want.
When I found out that classes in ruby are instances of the “Class” type, I
knew that would add all kinds of flexibility, but I didn’t anticipate this
use.
Thanks,
Ben
···
On Tue July 29 2003 11:10 am, ts wrote:
the instance is a class instance variable, because the class Stats will be
not removed, the instance will be marked when the GC run
Just another warning. I don’t know how to control the instance
creation time of singletons in Ruby. I would guess it’s lazy
initialisation. This could introduce problems when comparing memory
snapshots. You gonna get differences where you don’t expect them.
So although you are happy that the GC don’t kill your singleton, I
would like to know: Is there a standard way to remove a singleton in
Ruby?
(---- Off topic remark: ---- snip >-----
I’ve seen some discussion about Ruby IDEs stating that you’ll need an
image based ruby IDE to implement a powerful debugging environment. In
an image based IDE all objects building the IDE could be made
persistent. You can store the complete state of the IDE including
windows and running processes. Think about storing the state of IRB
and you have an image based system.
Not only IDEs benefit from storing the state of processes, a PC with
powermanagement or a database needs to store the state of running
processes, too.
------)
the instance is a class instance variable, because the class Stats will be
not removed, the instance will be marked when the GC run
Ah, how cool. I have never (knowingly) encountered a class instance variable
before, especially not one that contained an instance of itself. Now that I
take a closer look it all makes good sense, and does exactly what I want.
When I found out that classes in ruby are instances of the “Class” type, I
knew that would add all kinds of flexibility, but I didn’t anticipate this
use.