A few questions about singletons...

Discussion in 'C++' started by Somebody, Sep 24, 2009.

  1. Somebody

    Somebody Guest

    So, I've been programming for 16 yrs in C++ and it seems like all the OO
    interviews these days think you need to know design patterns to be a good
    (or even decent) programmer :p. What ya gonna do eh? :)...

    Anyways, this is what I have for my singleton class.

    class CSingleton
    {
    protected:

    CSingleton()
    {
    printf("CSingleton()\n");
    }

    ~CSingleton()
    {
    printf("~CSingleton()\n");
    }

    static CSingleton* m_pInst;

    public:

    static CSingleton* GetInstance()
    {
    if (m_pInst == NULL)
    m_pInst = new CSingleton;

    return m_pInst;
    }
    };

    CSingleton* CSingleton::m_pInst = NULL;

    int _tmain(int argc, _TCHAR* argv[])
    {
    CSingleton* p1 = CSingleton::GetInstance();
    CSingleton* p2 = CSingleton::GetInstance();
    printf("--> %x %x\n", p1, p2);
    return 0;
    }

    Works fine... except...

    1) what is the interview approved way to clean up the created object? Having
    a static "clean up" method that the user is responsible for calling seems
    completely retarded and anti-encapsulation. I've seen some solutions that
    create a second CSingletonDestroyer class as static and pass in the pointer.
    Then when the CSingletonDestroyer class is killed naturally, it kills the
    CSingleton...

    2) but the CSingletonDestroyer() class brings up thread safeness issues...
    if I wrap my GetInstance() in a critical section how does the critical
    section get initialized and cleaned up? I guess I can use a mutex, which
    will solve the init problem since that can be static init'ed, but wheres the
    clean up?

    Keep in mind, I'm doing this for Windows jobs, so no "linux only" solutions
    :).
    Somebody, Sep 24, 2009
    #1
    1. Advertising

  2. Somebody

    cpisz Guest

    On Sep 24, 4:03 pm, "Somebody" <> wrote:
    > So, I've been programming for 16 yrs in C++ and it seems like all the OO
    > interviews these days think you need to know design patterns to be a good
    > (or even decent) programmer :p. What ya gonna do eh? :)...
    >
    > Anyways, this is what I have for my singleton class.
    >
    > class CSingleton
    > {
    > protected:
    >
    >  CSingleton()
    >  {
    >   printf("CSingleton()\n");
    >  }
    >
    >  ~CSingleton()
    >  {
    >   printf("~CSingleton()\n");
    >  }
    >
    >  static CSingleton* m_pInst;
    >
    > public:
    >
    >  static CSingleton* GetInstance()
    >  {
    >   if (m_pInst == NULL)
    >    m_pInst = new CSingleton;
    >
    >   return m_pInst;
    >  }
    >
    > };
    >
    > CSingleton* CSingleton::m_pInst = NULL;
    >
    > int _tmain(int argc, _TCHAR* argv[])
    > {
    >  CSingleton* p1 = CSingleton::GetInstance();
    >  CSingleton* p2 = CSingleton::GetInstance();
    >  printf("--> %x %x\n", p1, p2);
    >  return 0;
    >
    > }
    >
    > Works fine... except...
    >
    > 1) what is the interview approved way to clean up the created object? Having
    > a static "clean up" method that the user is responsible for calling seems
    > completely retarded and anti-encapsulation. I've seen some solutions that
    > create a second CSingletonDestroyer class as static and pass in the pointer.
    > Then when the CSingletonDestroyer class is killed naturally, it kills the
    > CSingleton...
    >
    > 2) but the CSingletonDestroyer() class brings up thread safeness issues....
    > if I wrap my GetInstance() in a critical section how does the critical
    > section get initialized and cleaned up? I guess I can use a mutex, which
    > will solve the init problem since that can be static init'ed, but wheres the
    > clean up?
    >
    > Keep in mind, I'm doing this for Windows jobs, so no "linux only" solutions
    > :).


    Some interviewers seem to like to puff themselves up with some
    knowledge they read about, but don't understand the pitfalls of. I
    wouldn't want to work with someone like that anyway. I've had several
    leads that thought they were hot poopy because they read the gang of 4
    and learned some new words like "singleton". Ends up those same guys
    created 6 months worth of debugging for me, because they don't
    understand the pitfalls. I myself, plainly do not use singletons
    anymore. It does not mean I don't understand it, it means I've decided
    passing a reference to an object that is clearly documented has been
    less of a headache then debugging through global and static release at
    program exit. There is always going to be some guy that creates an
    unwanted dependency on a singleton and doesn't understand the mess
    they are making. You cannot control the actions of others, but you can
    try to minimize the mistakes they will make.

    I have to date to see a singleton that did not involve a global or
    static of some sort. The problem of another global or static depending
    on it is unescapable without shockers tied to the entire companies
    nipples. Release order of globals and statics is undefined. Sometimes
    it will break, sometimes not, but it will always give you a massive
    headache when you get to debugging this reappearing/disappearing
    problem.

    Design patterns are great. Knowing about them is also great. Knowing
    about the pitfalls is better. Knowing that everyone that touches your
    code probably won't is excellance.
    Thus I think the answer to 1) is - There is no compeltely safe way to
    cleanup. Everyone needs to be aware of that and the dependency problem
    it creates.
    2) why bother with a static destroyer? You are just moving the issue
    to another place. Maybe I would need to see a specific example to
    understand....
    cpisz, Sep 25, 2009
    #2
    1. Advertising

  3. Somebody

    karthik Guest

    Hi,

    Idea of a singleton class is to have a common instance which can be
    used in other objects. If someone creates or gets an object, he has to
    delete or release it also.

    > 1) what is the interview approved way to clean up the created object? Having
    > a static "clean up" method that the user is responsible for calling seems
    > completely retarded and anti-encapsulation.


    I couldn't really understand what does the above mean by retarded and
    anti-encapsulation method. If some user creates an object, he should
    delete it somehow. Since interface of the class suggests the person to
    use "GetInstance", it should have reverse method like
    "ReleaseInstance" which makes sure deletion of instance will happen if
    no one is using the instance currently.

    * Initially there will be no instance.

    * Some user calls "GetInstance", static userCount variable will be
    one, hence an object will be created. Further calls to "GetInstance"
    will simply
    increase userCount.

    * "ReleaseInstance" decrements userCount and deletes the object, if
    userCount is zero.

    Missing of calling "ReleaseInstance" will lead to Memory leak,
    obviously. Static "userCount" variable is un-avoidable. But It won't
    cause memory leak.

    Regards,
    Karthik.
    karthik, Sep 25, 2009
    #3
  4. On 24 sep, 23:03, "Somebody" <> wrote:
    > So, I've been programming for 16 yrs in C++ and it seems like all the OO
    > interviews these days think you need to know design patterns to be a good
    > (or even decent) programmer :p. What ya gonna do eh? :)...
    >
    > Anyways, this is what I have for my singleton class.


    Some classify singleton as an anti-pattern. It has been too much
    confused with globals (IMO particularly in C++ because of the idiom
    solving the initialisation order issue).

    >
    > class CSingleton
    > {
    > protected:
    >
    >  CSingleton()
    >  {
    >   printf("CSingleton()\n");
    >  }
    >
    >  ~CSingleton()
    >  {
    >   printf("~CSingleton()\n");
    >  }
    >
    >  static CSingleton* m_pInst;
    >
    > public:
    >
    >  static CSingleton* GetInstance()
    >  {
    >   if (m_pInst == NULL)
    >    m_pInst = new CSingleton;
    >
    >   return m_pInst;
    >  }
    >
    > };
    >
    > CSingleton* CSingleton::m_pInst = NULL;


    IIRC, you have implemented the Gamma singleton; it has a number of
    pitfall you may search on internet.

    [snip]

    >
    > Works fine... except...
    >
    > 1) what is the interview approved way to clean up the created object? Having
    > a static "clean up" method that the user is responsible for calling seems
    > completely retarded and anti-encapsulation. I've seen some solutions that
    > create a second CSingletonDestroyer class as static and pass in the pointer.
    > Then when the CSingletonDestroyer class is killed naturally, it kills the
    > CSingleton...


    You can use a Meyer singleton which solve the initialisation order
    issue:

    static CSingleton& GetInstance()
    {
    CSingleton static_instance;

    return static_instance;
    }

    And the cleanup is made at termination. The cleanup of a singleton is
    delicate because you don't known how is currently using it (it is even
    worse when in a DLL); you should let the system decide when it is no
    longer needed.

    > 2) but the CSingletonDestroyer() class brings up thread safeness issues....
    > if I wrap my GetInstance() in a critical section how does the critical
    > section get initialized and cleaned up? I guess I can use a mutex, which
    > will solve the init problem since that can be static init'ed, but wheres the
    > clean up?


    Singleton in multithreading environment is a delicate matter. There is
    currently no standard way of doing it reliably (except in the next C++
    standard).

    You may search "C++ and the Perils of Double-Checked Locking" for a
    detailed explanation.

    --
    Michael
    Michael Doubez, Sep 25, 2009
    #4
  5. Somebody

    Noah Roberts Guest

    In article <M8Rum.245763$>,
    says...
    >
    > So, I've been programming for 16 yrs in C++ and it seems like all the OO
    > interviews these days think you need to know design patterns to be a good
    > (or even decent) programmer :p. What ya gonna do eh? :)...


    It's amazing you've made it 16 years and never learned patterns.
    Patterns ARE central to solid development. Perhaps you've been using
    them and don't even know it. That's cool, but the problem is that
    patterns are also a language of architectural designs. When I, as a
    lead, say, "Perhaps a template method would be a good implementation of
    this," I hope you know what I'm talking about so I don't have to explain
    it to you. Same as if I said, "I implemented the controller with a
    basic state pattern that emits commands," in a code review--I want
    everyone in the room to know that that sentance means because it saves a
    good 20 minutes. You've almost certainly run into this pattern and used
    it on your own but I'd still have to explain myself to someone that
    should already know what I'm talking about. This is, quite frankly, way
    more important than being an expert in how to implement them.

    People that don't know patterns, at least in a rudimentary sense, are
    more difficult to communicate with.

    Further, the fact that you never learned them is a BIG red flag. Basic
    curiosity should have made you look into them even if you decided they
    were useless. That you didn't care enough to know patterns after 16
    years indicates a lack of dedication to your field. People that think
    they know enough already usually tend not to be the best developers out
    there.

    >
    > Anyways, this is what I have for my singleton class.
    >
    > class CSingleton


    This is an orange flag for me. Prefixing class names with C indicates
    attachment to hungarian notation. I'd probably pester you about this
    choice of name in an interview. It wouldn't pass a code review in my
    shop if 'C' stood for "class".

    > {
    > protected:
    >
    > CSingleton()
    > {
    > printf("CSingleton()\n");


    This would be another red flag for me. Use of printf indicates someone
    too attached to the all but obsolete C interface. I'd be worried you
    use char[] and malloc too. Different environments may be different but
    as a pure C++ development team we avoid the C API almost
    entirely...exception being the math library. I'd much rather see
    "std::cout << xxx"

    > }
    >
    > ~CSingleton()
    > {
    > printf("~CSingleton()\n");
    > }
    >
    > static CSingleton* m_pInst;
    >
    > public:
    >
    > static CSingleton* GetInstance()
    > {
    > if (m_pInst == NULL)
    > m_pInst = new CSingleton;
    >
    > return m_pInst;
    > }
    > };
    >
    > CSingleton* CSingleton::m_pInst = NULL;


    This is certainly one implementation. An interviewer is probably only
    interested that you know what the Singleton is for, why you'd use it,
    why you wouldn't, and at least one method to implement it....and if
    you're interviewing for an advanced position I'd ask you what the
    problems are with your chosen implementation and might ask for an
    alternative. One of which is to stick m_pInst as a static variable in
    the function that fetches it:

    static CSingleton * GetInstance()
    {
    static CSingleton * instance = new CSingleton;
    return instance;
    }

    Any time you use a singleton you have to address conditions specific to
    your given problem. Thread safety is certainly a concern in threaded
    environments. Most times when you use a singleton you're not actually
    worried about when it deletes and how it gets cleaned up. Sometimes you
    are.

    You should learn more than the Singleton pattern. The Singleton is
    probably the most commonly known but most useless pattern out there. As
    someone mentioned it is often considered an anti-pattern. There are
    actually very few cases when you should be using one. As an interviewer
    I'd be much more impressed if you knew and understoond template method,
    chain of responsibility, decorator, or proxy. Hell, even the NullObject
    is generally more useful. If you could name and explain these I'd be
    more confident that you actually know and understand patterns rather
    than just learning enough to pass the basic pattern exam.

    I do run into people like you and have accepted them in interviews so
    long as they are not hostile to patterns. I, perhaps unlike many,
    realize that patterns are consequences of the problem and expose
    themselves so obviously that anyone good is going to come upon them
    independently. When I first learned them I found I'd used many before.
    If you don't know the language I might push a bit to see if you might
    recognize one or two if I describe them. One very important part of
    this though is that you're not too stubborn to accept their usefulness,
    or at the very least accept the fact that you'd be required to learn
    them.

    The problem I'd see in your sample code and your position of not knowing
    patterns is that you have some bad habbits to unlearn and some new stuff
    that you need to learn. I'd probably hit you hard to see what your
    reaction is. People with 16 years of experience are often too britile
    and stubborn to adapt and can be, in many ways, a worse hire than an
    intern. Frankly, I'd rather hire a green programmer hands down in
    almost every case.
    Noah Roberts, Sep 25, 2009
    #5
  6. On Sep 25, 1:05 am, Michael Doubez <> wrote:
    > You can use a Meyer singleton which solve the initialisation order
    > issue:
    >
    > static CSingleton& GetInstance()
    > {
    >  CSingleton static_instance;
    >
    >  return static_instance;
    >
    > }
    >
    > And the cleanup is made at termination. The cleanup of a singleton is
    > delicate because you don't known how is currently using it (it is even
    > worse when in a DLL); you should let the system decide when it is no
    > longer needed.


    Suffice to say, actually suggesting the simplest Meyer's singleton is
    bad advice. Frankly, I've made so many mistakes on this topic recently
    that I'll just point you to the thread where someone more
    knowledgeable than me suggests more correct ways to do this.

    http://groups.google.com/group/comp.lang.c /browse_thread/thread/bca4044f40befc6a#

    1- Your singleton may cause static deinit issues. If you can leak it,
    just leak it. Otherwise, it'll work correctly if all other statics
    call getSingleton in their constructors. This will guarantee correct
    destruction order, Last In First Out.

    2- It's not thread-safe. There's the simple ways to do this correctly
    which come with the caveat that "No nontrivial threads during static
    init". Alternatively, use the more complex designs of Chris M.
    Thomasson, which just guarantee single correct construction with
    minimal overhead. There are several, depending on platform, and
    exactly what guarantees you want.

    Short version: Actually doing a correct singleton in C++ is hard (tm).
    It requires you to understand many nuances of the language, and things
    outside the language, like static initialization order fiasco, static
    de-initialization order fiasco, deep knowledge of thread-safety, etc.

    As long as I'm here, I might as well suggest this excellent paper as
    well, which covers the more common pitfall I've seen regarding
    singletons, and more generally a lack of understanding of modern real-
    world threading.

    http://www.aristeia.com/Papers/DDJ_Jul_Aug_2004_revised.pdf
    Joshua Maurice, Sep 25, 2009
    #6
  7. "Joshua Maurice" <> wrote in message
    news:...
    On Sep 25, 1:05 am, Michael Doubez <> wrote:
    > > You can use a Meyer singleton which solve the initialisation order
    > > issue:
    > >
    > > static CSingleton& GetInstance()
    > > {
    > > CSingleton static_instance;
    > >
    > > return static_instance;
    > >
    > > }
    > >
    > > And the cleanup is made at termination. The cleanup of a singleton is
    > > delicate because you don't known how is currently using it (it is even
    > > worse when in a DLL); you should let the system decide when it is no
    > > longer needed.

    >
    > Suffice to say, actually suggesting the simplest Meyer's singleton is
    > bad advice. Frankly, I've made so many mistakes on this topic recently
    > that I'll just point you to the thread where someone more
    > knowledgeable than me suggests more correct ways to do this.
    >
    > http://groups.google.com/group/comp.lang.c /browse_thread/thread/bca4044f40befc6a#
    >
    > 1- Your singleton may cause static deinit issues. If you can leak it,
    > just leak it. Otherwise, it'll work correctly if all other statics
    > call getSingleton in their constructors. This will guarantee correct
    > destruction order, Last In First Out.
    >
    > 2- It's not thread-safe. There's the simple ways to do this correctly
    > which come with the caveat that "No nontrivial threads during static
    > init". Alternatively, use the more complex designs of Chris M.
    > Thomasson, which just guarantee single correct construction with
    > minimal overhead. There are several, depending on platform, and
    > exactly what guarantees you want.


    FWIW, the "minimal" techniques do have there overheads, which usually
    present themselves in the form of atomic RMW instructions and
    acquire/release semantics. Unfortunately, these operations can be fairly
    expensive. However, using strongly-thread safe atomic reference counting can
    greatly simplify creating robust singletons. Yes, that type of reference
    counting may, or may not, involve all the overheads I mentioned, and perhaps
    more; so be it. It's all a mess of tradeoffs and benefits anyway. You will
    simply have to dig deep and find the scheme which can work well within the
    framework presented by you're specific application.




    > Short version: Actually doing a correct singleton in C++ is hard (tm).


    IMVHO, it sure as heck simplifies things if your program is single-threaded
    or you guarantee that no threads will ever be created before `main()'!!!

    Yikes!

    ;^O




    > It requires you to understand many nuances of the language, and things
    > outside the language, like static initialization order fiasco, static
    > de-initialization order fiasco, deep knowledge of thread-safety, etc.
    >
    > As long as I'm here, I might as well suggest this excellent paper as
    > well, which covers the more common pitfall I've seen regarding
    > singletons, and more generally a lack of understanding of modern real-
    > world threading.


    > http://www.aristeia.com/Papers/DDJ_Jul_Aug_2004_revised.pdf
    Chris M. Thomasson, Sep 28, 2009
    #7
  8. Somebody

    Krice Guest

    On 25 syys, 20:44, Noah Roberts <> wrote:  
    > Patterns ARE central to solid development.


    Patterns are like templates, they have become a trend
    that everyone has to use, even there is no reason.
    It's no wonder that programming has become non-productive,
    generating programs that are buggy and slow. But I guess
    programmers love complicated and fancy stuff. Maybe they
    even get paid more to write more source code and spend
    longer time doing that. Maybe patterns were invented just
    because of that.
    Krice, Sep 28, 2009
    #8
  9. Somebody

    James Kanze Guest

    On Sep 28, 2:37 am, "Chris M. Thomasson" <> wrote:
    > "Joshua Maurice" <> wrote in message

    [...]
    > > Short version: Actually doing a correct singleton in C++ is
    > > hard (tm).


    > IMVHO, it sure as heck simplifies things if your program is
    > single-threaded or you guarantee that no threads will ever be
    > created before `main()'!!!


    Yes. Except that you can extend it a little: you have to
    guarantee that no threads which use the singleton will ever be
    created before main. That's an important difference---when
    third party libraries are involved, you can't make many
    guarantees concerning what happens before main. (Sybase, for
    example, does start threads from the constructors of static
    objects, at least in some configurations.) On the other hand,
    it's a pretty good bet that those libraries don't use a
    singleton that you write.

    --
    James Kanze
    James Kanze, Sep 28, 2009
    #9
  10. Somebody

    James Kanze Guest

    On Sep 28, 8:15 am, Krice <> wrote:
    > On 25 syys, 20:44, Noah Roberts <> wrote:


    > > Patterns ARE central to solid development.


    > Patterns are like templates, they have become a trend
    > that everyone has to use, even there is no reason.


    Patterns are totally unlike templates; they aren't so much a
    software development technique per se, as a means of
    communication (including communicating with yourself). And
    until someone suggests something better... Communication is
    essential to well written programs, and using a recognized
    pattern make the code far easier to understand (and thus more
    likely correct) than it would be if you reinvented the wheel
    each time around.

    Note that in any real program, there will be lots of use of
    patterns. I've never seen a GUI interface that didn't use at
    least one of the template method pattern, the strategy pattern
    or the decorator pattern. (Most will use all of them at
    different points.) So the real question is: does the
    documentation just say that such and such a pattern is used, or
    does the documentation describe all of the nitty gritty details
    each time, leaving the client wondering if somewhere in the
    three or four pages of documentation, there isn't a subtle
    difference in the pattern this time around.

    --
    James Kanze
    James Kanze, Sep 28, 2009
    #10
  11. "James Kanze" <> wrote in message
    news:...
    > On Sep 28, 2:37 am, "Chris M. Thomasson" <> wrote:
    >> "Joshua Maurice" <> wrote in message

    > [...]
    >> > Short version: Actually doing a correct singleton in C++ is
    >> > hard (tm).

    >
    >> IMVHO, it sure as heck simplifies things if your program is
    >> single-threaded or you guarantee that no threads will ever be
    >> created before `main()'!!!

    >
    > Yes. Except that you can extend it a little: you have to
    > guarantee that no threads which use the singleton will ever be
    > created before main. That's an important difference---when
    > third party libraries are involved, you can't make many
    > guarantees concerning what happens before main.


    That is a very good point James.

    Thanks.




    > (Sybase, for
    > example, does start threads from the constructors of static
    > objects, at least in some configurations.) On the other hand,
    > it's a pretty good bet that those libraries don't use a
    > singleton that you write.
    Chris M. Thomasson, Sep 29, 2009
    #11
  12. On 25 sep, 20:45, Joshua Maurice <> wrote:
    > On Sep 25, 1:05 am, Michael Doubez <> wrote:
    >
    > > You can use a Meyer singleton which solve the initialisation order
    > > issue:

    >
    > > static CSingleton& GetInstance()
    > > {
    > >  CSingleton static_instance;

    >
    > >  return static_instance;

    >
    > > }

    >
    > > And the cleanup is made at termination. The cleanup of a singleton is
    > > delicate because you don't known how is currently using it (it is even
    > > worse when in a DLL); you should let the system decide when it is no
    > > longer needed.

    >
    > Suffice to say, actually suggesting the simplest Meyer's singleton is
    > bad advice. Frankly, I've made so many mistakes on this topic recently
    > that I'll just point you to the thread where someone more
    > knowledgeable than me suggests more correct ways to do this.
    >
    > http://groups.google.com/group/comp.lang.c /browse_thread/thread/bca...
    >
    > 1- Your singleton may cause static deinit issues. If you can leak it,
    > just leak it. Otherwise, it'll work correctly if all other statics
    > call getSingleton in their constructors. This will guarantee correct
    > destruction order, Last In First Out.


    You mean if a static gets latter on (after its initialisation) a
    reference on the singleton ? This is not limited to singleton but to
    every storage management; have seen some case where the singleton is
    resetable causing that kind of problem but it is more related to the
    logic of the program(er).

    Betting on a singleton with the longest lifetime does guarantee your
    program doesn't crash for this reason but it is IMHO at best a patch.

    > 2- It's not thread-safe. There's the simple ways to do this correctly
    > which come with the caveat that "No nontrivial threads during static
    > init".


    That is alas true. The next standard does provide atomic operations
    which will ease that pain (I hope).

    > Alternatively, use the more complex designs of Chris M.
    > Thomasson, which just guarantee single correct construction with
    > minimal overhead. There are several, depending on platform, and
    > exactly what guarantees you want.


    I have seen the code mentioned and it supposes that initialisation of
    the mutex is atomic.

    If I replace in the header:
    typedef HANDLE pthread_mutex_t;
    #define PTHREAD_MUTEX_INITIALIZER CreateMutex(/* params */)
    You see the problem with:
    static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;

    In fact, it is possible that two mutex will be created and the mutex
    is then useless.

    In practice, IIRC it does work with the usual libpthread.

    > Short version: Actually doing a correct singleton in C++ is hard (tm).


    It is hard and not really useful in most cases.

    Unless you are paid per "pattern-point". :)

    --
    Michael
    Michael Doubez, Sep 29, 2009
    #12
  13. On 25 Sep, 06:40, karthik <> wrote:
    > Hi,
    >
    > Idea of a singleton class is to have a common instance which can be
    > used in other objects. If someone creates or gets an object, he has to
    > delete or release it also.
    >
    > > 1) what is the interview approved way to clean up the created object? Having
    > > a static "clean up" method that the user is responsible for calling seems
    > > completely retarded and anti-encapsulation.

    >
    > I couldn't really understand what does the above mean by retarded and
    > anti-encapsulation method. If some user creates an object, he should
    > delete it somehow. Since interface of the class suggests the person to
    > use "GetInstance", it should have reverse method like
    > "ReleaseInstance" which makes sure deletion of instance will happen if
    > no one is using the instance currently.
    >
    > * Initially there will be no instance.
    >
    > * Some user calls "GetInstance", static userCount variable will be
    > one, hence an object will be created. Further calls to "GetInstance"
    > will simply
    >   increase userCount.
    >
    > * "ReleaseInstance" decrements userCount and deletes the object, if
    > userCount is zero.
    >
    > Missing of calling "ReleaseInstance" will lead to Memory leak,
    > obviously. Static "userCount" variable is un-avoidable. But It won't
    > cause memory leak.


    that's an unusual form of the singleton pattern. I've never seen
    one where each user had to do a ReleaseInstance(). The GoF one doesn't
    Nick Keighley, Sep 29, 2009
    #13
  14. "Michael Doubez" <> wrote in message
    news:...
    On 25 sep, 20:45, Joshua Maurice <> wrote:
    [...]

    > > Alternatively, use the more complex designs of Chris M.
    > > Thomasson, which just guarantee single correct construction with
    > > minimal overhead. There are several, depending on platform, and
    > > exactly what guarantees you want.


    > I have seen the code mentioned and it supposes that initialisation of
    > the mutex is atomic.


    > If I replace in the header:
    > typedef HANDLE pthread_mutex_t;
    > #define PTHREAD_MUTEX_INITIALIZER CreateMutex(/* params */)
    > You see the problem with:
    > static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;


    > In fact, it is possible that two mutex will be created and the mutex
    > is then useless.


    > In practice, IIRC it does work with the usual libpthread.


    Yes. The code I posted assumes that it will always be run under a POSIX
    compliant platform. However, since you bring up Windows, well, there is a
    hack one can use to dynamically and safely create a mutex in an atomic
    fashion:
    ____________________________________________________________________
    class win_dcl_mutex
    {
    HANDLE m_mutex;


    private:
    static std::string prv_get_name()
    {
    std::eek:stringstream name;

    name << "DCL_MUTEX_" << GetCurrentProcessId();

    return name.str();
    }


    public:
    win_dcl_mutex() throw()
    : m_mutex(CreateMutex(NULL, TRUE, prv_get_name().c_str()))
    {
    if (! m_mutex)
    {
    assert(m_mutex);
    std::unexpected();
    }

    else if (GetLastError() == ERROR_ALREADY_EXISTS)
    {
    if (WaitForSingleObject(m_mutex, INFINITE) !=
    WAIT_OBJECT_0)
    {
    assert(m_mutex);
    CloseHandle(m_mutex);
    std::unexpected();
    }
    }
    }

    ~win_dcl_mutex() throw()
    {
    if (! ReleaseMutex(m_mutex))
    {
    assert(m_mutex);
    CloseHandle(m_mutex);
    std::unexpected();
    }

    if (! CloseHandle(m_mutex))
    {
    assert(m_mutex);
    std::unexpected();
    }
    }
    };
    ____________________________________________________________________




    You would use this hack in the slow path of the DCL algorithm. You can make
    this technique more fine grain by adding something to the constructor which
    would further identify this mutex beyond using the current process id.
    Something like:
    ____________________________________________________________________
    class win_dcl_mutex
    {
    HANDLE m_mutex;


    private:
    template<typename T>
    static std::string prv_get_name(T const& id)
    {
    std::eek:stringstream name;

    name << "DCL_MUTEX_" << GetCurrentProcessId() << "_" << id;

    return name.str();
    }


    public:
    template<typename T>
    win_dcl_mutex(T const& id) throw()
    : m_mutex(CreateMutex(NULL, TRUE, prv_get_name(id).c_str()))
    {
    if (! m_mutex)
    {
    assert(m_mutex);
    std::unexpected();
    }

    else if (GetLastError() == ERROR_ALREADY_EXISTS)
    {
    if (WaitForSingleObject(m_mutex, INFINITE) !=
    WAIT_OBJECT_0)
    {
    assert(m_mutex);
    CloseHandle(m_mutex);
    std::unexpected();
    }
    }
    }

    ~win_dcl_mutex() throw()
    {
    if (! ReleaseMutex(m_mutex))
    {
    assert(m_mutex);
    CloseHandle(m_mutex);
    std::unexpected();
    }

    if (! CloseHandle(m_mutex))
    {
    assert(m_mutex);
    std::unexpected();
    }
    }
    };
    ____________________________________________________________________




    [...]
    Chris M. Thomasson, Sep 30, 2009
    #14
  15. On Sep 29, 4:21 am, Michael Doubez <> wrote:
    > On 25 sep, 20:45, Joshua Maurice <> wrote:
    > > On Sep 25, 1:05 am, Michael Doubez <> wrote:
    > > > You can use a Meyer singleton which solve the initialisation order
    > > > issue:
    > > >
    > > > static CSingleton& GetInstance()
    > > > {
    > > >  CSingleton static_instance;
    > > >  return static_instance;
    > > > }
    > > >
    > > > And the cleanup is made at termination. The cleanup of a singleton is
    > > > delicate because you don't known how is currently using it (it is even
    > > > worse when in a DLL); you should let the system decide when it is no
    > > > longer needed.

    > >
    > > Suffice to say, actually suggesting the simplest Meyer's singleton is
    > > bad advice. Frankly, I've made so many mistakes on this topic recently
    > > that I'll just point you to the thread where someone more
    > > knowledgeable than me suggests more correct ways to do this.
    > >
    > > http://groups.google.com/group/comp.lang.c /browse_thread/thread/bca....
    > >
    > > 1- Your singleton may cause static deinit issues. If you can leak it,
    > > just leak it. Otherwise, it'll work correctly if all other statics
    > > call getSingleton in their constructors. This will guarantee correct
    > > destruction order, Last In First Out.

    >
    > You mean if a static gets latter on (after its initialisation) a
    > reference on the singleton ?


    Yes.

    > This is not limited to singleton but to
    > every storage management; have seen some case where the singleton is
    > resetable causing that kind of problem but it is more related to the
    > logic of the program(er).
    >
    > Betting on a singleton with the longest lifetime does guarantee your
    > program doesn't crash for this reason but it is IMHO at best a patch.


    Agreed.

    > > 2- It's not thread-safe. There's the simple ways to do this correctly
    > > which come with the caveat that "No nontrivial threads during static
    > > init".

    >
    > That is alas true. The next standard does provide atomic operations
    > which will ease that pain (I hope).


    IIRC: Even better: all initializors of namespace-scope variables and
    static-local variables will have pthread_once semantics. It'll also
    give basic atomic operations as well.

    > > Alternatively, use the more complex designs of Chris M.
    > > Thomasson, which just guarantee single correct construction with
    > > minimal overhead. There are several, depending on platform, and
    > > exactly what guarantees you want.

    >
    > I have seen the code mentioned and it supposes that initialisation of
    > the mutex is atomic.
    >
    > If I replace in the header:
    > typedef HANDLE pthread_mutex_t;
    > #define PTHREAD_MUTEX_INITIALIZER CreateMutex(/* params */)
    > You see the problem with:
    > static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
    >
    > In fact, it is possible that two mutex will be created and the mutex
    > is then useless.
    >
    > In practice, IIRC it does work with the usual libpthread.


    I got this very wrong in the aforementioned thread. Chris does a good
    job correcting me there. You are right that PTHREAD_MUTEX_INITIALIZER
    has no (easy) windows equivalent. Check out the code Chris posted in
    the aforementioned link. He covers this case as well.

    Although, honestly, at this point I would just strongly suggest using
    Boost's pthread_once wrapper, which basically uses Chris's windows
    implementation for windows IIRC.
    Joshua Maurice, Sep 30, 2009
    #15
  16. On 30 sep, 01:48, "Chris M. Thomasson" <> wrote:
    > "Michael Doubez" <> wrote in message
    >
    > news:...
    > On 25 sep, 20:45, Joshua Maurice <> wrote:
    > [...]
    >
    > > > Alternatively, use the more complex designs of Chris M.
    > > > Thomasson, which just guarantee single correct construction with
    > > > minimal overhead. There are several, depending on platform, and
    > > > exactly what guarantees you want.

    > > I have seen the code mentioned and it supposes that initialisation of
    > > the mutex is atomic.
    > > If I replace in the header:
    > > typedef HANDLE pthread_mutex_t;
    > > #define PTHREAD_MUTEX_INITIALIZER CreateMutex(/* params */)
    > > You see the problem with:
    > > static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
    > > In fact, it is possible that two mutex will be created and the mutex
    > > is then useless.
    > > In practice, IIRC it does work with the usual libpthread.

    >
    > Yes. The code I posted assumes that it will always be run under a POSIX
    > compliant platform. However, since you bring up Windows, well, there is a
    > hack one can use to dynamically and safely create a mutex in an atomic
    > fashion:
    >[snip]
    >     :   m_mutex(CreateMutex(NULL, TRUE, prv_get_name().c_str()))
    > [snip]


    Yes, that solves the issue. It looks to me like creating a system wide
    semaphore; well, not a worry really since the number of singleton
    should be low.

    --
    Michael
    Michael Doubez, Sep 30, 2009
    #16
  17. On 30 sep, 01:48, "Chris M. Thomasson" <> wrote:
    [snip]
    >         if (! m_mutex)
    >         {
    >             assert(m_mutex);
    >             std::unexpected();
    >         }

    [snip]

    I wondered about this usage of assert() + unexpected(): what is the
    rational of using both ?

    To tell the truth, I never use std::unexpected(). How and when do you
    use it ?

    --
    Michael
    Michael Doubez, Sep 30, 2009
    #17
  18. "Michael Doubez" <> wrote in message
    news:...
    On 30 sep, 01:48, "Chris M. Thomasson" <> wrote:
    [snip]
    > > if (! m_mutex)
    > > {
    > > assert(m_mutex);
    > > std::unexpected();
    > > }

    > [snip]


    > I wondered about this usage of assert() + unexpected(): what is the
    > rational of using both ?


    I made several *mistakes in the "hard" error handling code. Sorry about
    that.




    > To tell the truth, I never use std::unexpected(). How and when do you
    > use it ?


    Quite frankly, I personally do not know which exception to throw as I am not
    a C++ expert. I decorated the constructor/destructor and `prv_get_name()'
    functions with the `throw()' clause. IMVHO, if the ctor of a singleton
    fails, then end user program is in peril. Should the singleton ctor throw or
    not?




    (*)
    BTW, here is corrected code:
    _______________________________________________________________________
    #define WIN32_LEAN_AND_MEAN
    #include <windows.h>
    #include <sstream>
    #include <iostream>
    #include <cstdio>




    #if ! defined (WIN_DCL_MUTEX_UNEXPECTED)
    # include <cassert>
    # include <exception>
    # define WIN_DCL_MUTEX_UNEXPECTED assert(false), std::unexpected
    #endif




    class win_dcl_mutex
    {
    HANDLE m_mutex;


    private:
    template<typename T>
    static std::string prv_get_name(T const& id) throw()
    {
    std::eek:stringstream name;

    name << "DCL_MUTEX_" << GetCurrentProcessId() << "_" << id;

    // std::cout << name.str() << std::endl;

    return name.str();
    }


    public:
    template<typename T>
    win_dcl_mutex(T const& id) throw()

    : m_mutex(CreateMutex(NULL, TRUE, prv_get_name(id).c_str()))

    {
    if (! m_mutex)
    {
    WIN_DCL_MUTEX_UNEXPECTED();
    }

    else if (GetLastError() == ERROR_ALREADY_EXISTS)
    {
    if (WaitForSingleObject(m_mutex, INFINITE) !=
    WAIT_OBJECT_0)
    {
    CloseHandle(m_mutex);
    WIN_DCL_MUTEX_UNEXPECTED();
    }
    }
    }

    ~win_dcl_mutex() throw()
    {
    if (! ReleaseMutex(m_mutex))
    {
    CloseHandle(m_mutex);
    WIN_DCL_MUTEX_UNEXPECTED();
    }

    if (! CloseHandle(m_mutex))
    {
    WIN_DCL_MUTEX_UNEXPECTED();
    }
    }
    };




    int
    main()
    {
    {
    win_dcl_mutex mutex(12345);
    }

    return 0;
    }

    _______________________________________________________________________
    Chris M. Thomasson, Oct 2, 2009
    #18
  19. * Chris M. Thomasson:
    > "Michael Doubez" <> wrote in message
    > news:...
    > On 30 sep, 01:48, "Chris M. Thomasson" <> wrote:
    > [snip]
    >> > if (! m_mutex)
    >> > {
    >> > assert(m_mutex);
    >> > std::unexpected();
    >> > }

    >> [snip]

    >
    >> I wondered about this usage of assert() + unexpected(): what is the
    >> rational of using both ?

    >
    > I made several *mistakes in the "hard" error handling code. Sorry about
    > that.
    >
    >
    >
    >
    >> To tell the truth, I never use std::unexpected(). How and when do you
    >> use it ?

    >
    > Quite frankly, I personally do not know which exception to throw as I am
    > not a C++ expert.


    You can invoke std::terminate.

    Or if you don't want a possible termination handler to execute, just abort().


    > I decorated the constructor/destructor and
    > `prv_get_name()' functions with the `throw()' clause. IMVHO, if the ctor
    > of a singleton fails, then end user program is in peril. Should the
    > singleton ctor throw or not?


    Consider a singleton that represents a late-loaded (dynamically loaded) shared
    library. In that case, if the library isn't present on the system then it might
    be OK to continue with some fallback solution or reduced functionality. If that
    singleton just aborts then it's rather difficult to continue...

    But equally, there might be some singleton where the only sensible choice is to
    abort no matter what, ensuring the same failure behavior in all cases (whether
    the singleton is constructed from within a caller's code try-block or not).

    So, I guess it's again Niels Bohr's statement, "The number of tails of a dog
    depends on the dog".


    Cheers,

    - Alf
    Alf P. Steinbach, Oct 2, 2009
    #19
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Yevgeny Menaker

    C++ singletons and .NET AppDomains

    Yevgeny Menaker, Jan 10, 2004, in forum: ASP .Net
    Replies:
    0
    Views:
    313
    Yevgeny Menaker
    Jan 10, 2004
  2. Yevgeny Menaker

    C++ singletons and .NET AppDomains

    Yevgeny Menaker, Jan 10, 2004, in forum: ASP .Net
    Replies:
    0
    Views:
    280
    Yevgeny Menaker
    Jan 10, 2004
  3. Yevgeny Menaker

    C++ singletons and .NET AppDomains

    Yevgeny Menaker, Jan 10, 2004, in forum: ASP .Net
    Replies:
    1
    Views:
    2,925
    Alvin Bruney
    Jan 17, 2004
  4. Replies:
    10
    Views:
    536
  5. Murali
    Replies:
    2
    Views:
    542
    Jerry Coffin
    Mar 9, 2006
Loading...

Share This Page