Boost logo

Boost :

From: Petr Kocmid (pkocmid_at_[hidden])
Date: 2000-05-26 21:10:59


Hi all,

current discussion about singletons and nonconstructible reminds me
I already made similar stuff some time ago.

Just didn't found time to test it and forgot to post it to boost
this year's spring. See the date at history :-)

The singleton's are implemented with kind of smart pointer and
constructed automatically at runtime (when needed) which is more
flexible than static singleton 'memory eaters' and 'before app
start must all knowers'.
(That was the main goal of this implementation)

Please consider this post to be 'fire and forget', since I am
very busy now.

Petr Kocmid
pkocmid_at_[hidden]

here's the proposal:

// ====================================================================
// Project: boost/singleton
// File: singleton.hpp
// --------------------------------------------------------------------
// (c) 1999-2000 Copyright by Petr Kocmid, pkocmid_at_[hidden]
// ====================================================================
// History:
// 27.2.2000 Petr Kocmid
// prepared proposal for boost contribution
// ====================================================================
// notes:
// Triple slash and '/**' comments are for automatic documentation
// processing with doc++, doxygen or similar tools, so as '@'-tags.
// Member documentation is defaulted to create user-style
// documentation (private members are not documented).
// --------------------------------------------------------------------

#ifndef __boost_singleton_included__
#define __boost_singleton_included__

#include <stdexcept> // for exception handling
#include <string> // for exception handling

using namespace std;

#include <boost/config.hpp>
#include <boost/utility.hpp>

namespace boost {

/**
        @name class noncreatable
        @memo Suppresses default construction and destruction of a derived class.
        @doc Noncreatable class is no nonsense, as it appears to be for the first
look.
        It's usefull for templated static wrapper class having no instance at all.
        It strictly forbids using both default constructor and destructor for the
class.

        (Hope it'll find it's way into <boost/utility.hpp>)
        note: msvc6 kindly uses private destructor via delete, but can't use it
implicitly.
        */
class noncreatable: private noncopyable {
private:
        explicit noncreatable();
        ~noncreatable();
};

/**
        @name template <typename T> class singleton_factory
        @memo Represents a factory producing and owning single instance object,
        where an only one instance per process is desired.
        @doc It operates through static members and methods only, no instance
        of the factory itself is allowed to be created, thus maintaining
uniqueness.
        Static members themselves are magically generated by template expansion,
        having boost namespace as their plane of incarnation.
        Normally, there is no need to instantiate factory template explicitly, it
        is done automatically by singleton_ptr<T> template.
        However, it is possible to access factory directly for example in
        case of housekeepeng after exception catched (ever needed in correct app
        architecture?).
        @param T Type of an object to be a singleton. This version presumes the T
        type has a default constructor (initializers needed?).
        @see "template <typename T> class singleton_ptr"
        */

template <typename T> class singleton_factory: public noncreatable {

public:
        /// naming template argument. just a discipline.
        typedef T element_type;

        /// if the instance is being used by someone else, confirm that fact
        static bool in_use () throw();

        /// instance grabbing. creates an instance of T if called the first time
        static T* instance();

        /*
        msvc has a hard day with member templates. I'll make the T-initializers
        available after gcc and bcb55 tests.
        /// instance grabbing with optional initialization. creates an instance
with initializer if called the first time
        template<typename I=int> static T* instance(const I& initializer);
        */

        /// instance releasing. for usage of reference counting. destroys the
instance on the last release.
        static void release();

private:
        // pointer to singleton instance
        static T* instance_ptr;
        // keeps the usage
        static int refcount;
};

// here comes the implementation

template<typename T> T* singleton_factory<T>::instance_ptr = 0;
template<typename T> int singleton_factory<T>::refcount = 0;

template<typename T> T* singleton_factory<T>::instance () {
        if (!refcount) { // creates an instance if asked the first time
                instance_ptr = new T;
        }
        refcount++;
        return instance_ptr;
}

/*
template<typename T, typename I> T* singleton_factory<T>::instance (const I&
initializer) {
        if (!refcount) { // creates an instance if asked the first time
                instance_ptr = new T(initializer);
        }
        refcount++;
        return instance_ptr;
}
*/

template<typename T> bool singleton_factory<T>::in_use() throw() {
        return refcount ? true : false; // not a lame: avoid warnings on some
compilers
}

template<typename T> void singleton_factory<T>::release()

        if (refcount==1) // 'tis the last one, put it away
                delete instance_ptr; // of type T
        refcount--;
}

/**
        @name template<typename T> class singleton_ptr
        @memo This is a kind of smart pointer to singleton instance.
        @doc It points to the one and only instance of T, helping T's factory keep
        the reference counting. Singleton T type could be any composite type, no
need
        for having its members static. This is a great feature for reusability.
        This cannot be achieved with traditional static singleton pattern.
        @param T Type of an object to be a singleton. Presumes the T has default
constructor.
        @see "template <typename T> class singleton_factory"
        */
template<typename T> class singleton_ptr: noncopyable {
  T* ptr;

public:
        /// naming template argument. just a discipline.
  typedef T element_type;

        /// default constructor attaches an instance from it's factory
        explicit singleton_ptr() { ptr = singleton_factory<T>::instance(); }
        /// destructor releases an instance
        ~singleton_ptr() { singleton_factory<T>::release(); }

        // any dereferencig pointer operation should ask factory if instance
        // is still present. normally non-presence cannot happen, but in
        // cases when some exception handler destroys the instance for some
        // reason. Also, there are other strategies to handle that case:
        // recreate an instance for example. To be discussed.

        /// dereference access operator
  T& operator*() const { return *(get()); }
        /// pointer access operator
  T* operator->() const { return get(); }
        /// pointer access method
  T* get() const

                if (singleton_factory<T>::in_use())
                        return ptr;
                else
                        throw (runtime_error(string("singleton_factory owns no instance")) );
        }

        // let's make it boost-friendly
#ifdef BOOST_SMART_PTR_CONVERSION
  // get() is safer! Define BOOST_SMART_PTR_CONVERSION at your own risk!
        /// conversion operator
  operator T*() const throw() { return ptr; }
        // note there is no throwing here
#endif
}; // singleton_ptr

}; // napespace boost

#endif // __boost_singleton_included__


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk