octave-maintainers
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Singletons


From: Jordi Gutiérrez Hermoso
Subject: Singletons
Date: Wed, 25 May 2011 13:29:49 -0500

Sorry for feeling argumentative today, but Octave activity has been a
little low lately, so I don't feel too bad about livening it up.

2011/5/25 John W. Eaton <address@hidden>:
> On 25-May-2011, Jordi Gutiérrez Hermoso wrote:
>
> | I've never seen that place. A namespaced global object works just as
> | well and has less syntactic cruft built around it.
>
> It does not work just as well when a static object is involved.  Then
> you have to somehow be sure that the initialization happens at the
> right time, and that can be problematic because you have no control
> over the order of initialization of file-scope or global static
> objects.

Well, as an example that I got curious about from your list further
below, from reading the source of src/DLD-FUNCTIONS/fftw.cc and the
associated liboctave/oct-fftw.* files, I see that initialisation is
right now done at the moment when octave_fftw_planner::method() is
first called (which calls instance_ok which in turn attempts the
initialisation). It would in fact be relatively easy to change this
code to simply namespace the global octave_fftw_planner object; the
calling code in fftw.cc is in fact only using the class aspects of the
singleton as namespacing. And the dtor is never called; it's in fact
protected and the class is never derived from (and you would probably
run into problems if you tried to subclass it).

The point is that a singleton is antithetical to OOP because it's not
really a class with instantiated objects; it's just a global object
with global functions. Singletons are procedural programming with the
keywords "class" and "static" attached to them. You can't usually
derive from them (hence they don't enable polymorphism), you can't
instantiate several of their kind, so the actual benefits of OOP
aren't there with singletons.

But as I said, it's mostly about style. A singleton is just about
writing global objects and functions with the "class" and "static"
keywords; it's about de-OOPifying a class. This is for example
essential in Java where you can't have code outside of a class; there
you really have no choice but to use singletons if you don't want OOP.
It is a matter of style if you still prefer to write singletons in C++
instead of using namespaces.

> We've seen this kind of problem before where Octave crashes
> at startup on some systems and not others due to some object being
> instantiated in an order that we didn't expect.

We could be explicit about this order by calling an init() function
from main(), for objects that really need to exist for the entire
duration of execution.

> | This is overall a minor stylistic point, though. If everyone else
> | agrees that a singleton profiler is really the way to go, I will
> | relent. There is the issue of memory management, but we already
> | have a bunch of minor "memory leaks" (mostly allocations of small
> | global objects that last for the entire duration of execution and
> | are never deleted) that one more probably won't be noticed.
>
> If they are global objects that may be used at any time during the
> execution of the program and their expected lifetime is the entire
> lifetime of the program, then I don't see that these are really
> memory leaks.  Maybe that's what you meant to imply with your
> quotation marks?

Yes, that's what I meant, most of these are not really memory leaks
because they really are needed throughout the entire execution, so
valgrind is just a little cautious because free() is never called on
them, but...

> Here is a list of all the singleton objects in Octave that I could
> find (I grepped the .cc files for "instance = 0") and that might give
> rise to these "memory leaks":
>
>  path searching class
>  command history
>  fftw planner info
>  file directory separator character info
>  sparse matrix parameters
>  machine info
>  random number generator state
>  execution environment info
>  command editor
>  debugging breakpoint table
>  font manager
>  comment buffer for parser
>  interpreter call stack
>  symbol table info
>  list of dynamically loaded functions
>  list of figure objects
>  function load path info
>  list of graphics handles
>  graphics display info
>  pager output stream
>  diary output stream
>  list of other i/o streams
>  list of child processes

Some of these shouldn't really exist for the entire execution, right?
The fftw stuff should be deleted when Octave is done working with fft;
same if all sparse matrices go out of scope, as well as graphical
stuff. Is this correct? I think all of these are small, though, so
they're not really noticeable.

Not that I think it's worth the trouble "fixing" this. Not broke,
don't fix it. But I do think it's not necessary to introduce more
elements to that list unless it's essential, and it's not clear to me
that a profiler should necessarily belong to this list.

- Jordi G. H.


reply via email to

[Prev in Thread] Current Thread [Next in Thread]