Singletons as globals and GC

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?

Ben

Hi,

···

In message “Singletons as globals and GC” on 03/07/29, Ben Giddings ben@thingmagic.com writes:

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?

I don’t know what you meant. If w1 is referenced from somewhere, w1
will not be garbage-collected.

						matz.

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:

Cheers
Sascha

···

Ben Giddings ben@thingmagic.com wrote:

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.

class Worker1
   def doStuff
     @stats = Stats.instance # The instance of the stats singleton is created

svg% cat b.rb
#!/usr/bin/ruby
require 'singleton'
class Stats
   include Singleton
end
p Stats.instance
Stats.instance_eval { p @__instance__}
svg%

svg% b.rb
#<Stats:0x40092d60>
#<Stats:0x40092d60>
svg%

the instance is a class instance variable, because the class Stats will be
not removed, the instance will be marked when the GC run

Guy Decoux

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.

Singletons will cause problems in such an image based system:
http://c2.com/cgi/wiki?SmalltalkSingletonProblem

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

Cheers
Sascha

···

Ben Giddings ben@thingmagic.com wrote:

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

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.