<skip easy case>
>
> b) the singleton object is needed until the absolute last
> object (that uses
> it) is destroyed.
>
> If you can resolve this problem with a reference counting
> interface, then
> another option would be to build your own reference counting solution.
> Create a list inside your singleton which adds each object as it is
> processed (during initialization/runtime) and removes each
> object as it is
> processed (during finalization). Then when the list count
> gets to zero, the
> singleton frees itself.

True.  I thought originally that it was important that each object's
reference to the singleton was governed by scope, but given that I want the
singleton to hang around anyway, that isn't really the case.  So I don't
have to use interfaces to do it.  Although at the moment I don't need to
keep a list of the objects that the object references.  I'm still trying to
think of whether there are any other benefits, were I to do that.

If I understand you correctly, I would have to have the objects that use
singleton methods call "StartNeedingSingleton(Self)" (or something like
that) in their constructors and "EndNeedingSingleton(Self)" in their
destructors.  Alternatively, I could dispense with the object list and make
the "StartNeedingSingleton" and "EndNeedingSingleton" just be the
equivalents of Singleton._AddRef and Singleton._Release under other names,
and then I would only need to keep a count.  The downside of either method
is it leaves open the possibility that somebody somewhere might forget to
put the "EndNeedingSingleton" in, which would screw everything up.  But
having said that, people haven't always bothered to create a referencing
interface variable in every place where the singleton is used as it is,
which means the use of it in some areas is unprotected.

I guess if I did keep a list of objects it would allow me to raise an
exception if some object tried to use the singleton without calling the
"StartNeedingSingleton" first.  But that wouldn't help me if they left
"EndNeedingSingleton" out.  Thinking about it, that would be much worse than
what occurs now, because it would guarantee that the singleton was never
freed, whereas right now that only happens if the singleton, sans interface
reference, is referenced during finalization.  Resulting in rampant AVs if
it does happen, but hey.

For those that are interested, my current implementation goes something like
this:

unit MySingletonUnit;

type
  IMySingleton = interface
  <guid>
  end;

  TMySingleton = class(TWhatever, IMySingleton);
  // inc the count in _AddRef, dec it in _Release, free self when 0
  end;

function Singleton: TMySingleton;

implementation

{
slightly insincere apologies for the following terminology - I use M prefix
to mean "module level variable", or to put it another way, "unit
implementation section global variable"
}
var MSingleton: TMySingleton = nil;
  MISingleton: IMySingleton = nil;

function MySingleton: TMySingleton;
begin
  if not Assigned(MSingleton) then
  begin
    // create it
    MISingleton := MSingleton; // Hold an additional reference for this unit
when the singleton is created (so that it hangs around)
  end;
  Result := MISingleton;
end;

initialization
finalization
  MISingleton := nil; // Release this unit's reference
end.

Then other objects go, for example:

constructor TMyObject.Create;
begin
  FISingleton := MySingleton; // Hold a reference for the lifetime of the
object, driven by the scope of the interface

or if I need to reference it outside an object, I can grab a reference in a
"module level" variable the same way the unit that contains the singleton
does:

implementation

var
  MISingleton: ISingleton;

// and somewhere in the code before I use Singleton for the first time, the
following line:

  MISingleton := MySingleton; // Hold a reference for the lifetime of this
unit

initialization
finalization
  MISingleton := nil; // Remove the reference during the finalization of
this unit
end.

Cheers,
Carl

_______________________________________________
Delphi mailing list
[email protected]
http://ns3.123.co.nz/mailman/listinfo/delphi

Reply via email to