Namespaces

Variants
Actions

Please note that as of October 24, 2014, the Nokia Developer Wiki will no longer be accepting user contributions, including new entries, edits and comments, as we begin transitioning to our new home, in the Windows Phone Development Wiki. We plan to move over the majority of the existing entries over the next few weeks. Thanks for all your past and future contributions.

Simple Reference Counting Singleton

From Wiki
Jump to: navigation, search
Article Metadata
Article
Created: Macoshark (26 Jun 2007)
Last edited: hamishwillee (25 Jul 2012)

Contents

What is a singleton?

Singleton is a design-pattern originally described by the Gang of Four (GoF). The basic idea is to ensure that only one instance of the class will ever exist. The class will typically have a static function that can be used to get the instance and the class will internally keep track of itself and either create the single instance or return a pointer to it.

Why won't the typical C++ implementation work in Symbian?

The simplest singleton example shown in most C++ books uses a static pointer to store the instance. A static pointer will continue to exist for the duration of the process so it is a very convenient way to implement a singleton. This however doesn't work in a Symbian DLL because the static pointer is writable static data (Writeable Static Data) and it is not allowed in Symbian DLLs. (It can be enabled with EPOCALLOWDLLDATA but it is not recommended).

The CCoeStatic solution

In application code that has access to CCoeEnv the simplest way to implement a singleton is to derive the class from CCoeStatic.

Example of this can be found Implementing a Singleton using Symbian CCoeStatic class

More generic solution using TLS

If the code needs to work also in non-UI processes, the easiest way is to use TLS. The approach doesn't differ much from the C++ book example except that the static pointer is replaced with TLS.

This example will create a reference counted singleton that manages its own lifetime. The users are only required to call Release() on it when they no longer use it.

RefCountingSingleton.h

#ifndef CREFCOUNTINGSINGLETON_H
#define CREFCOUNTINGSINGLETON_H
 
#include <e32base.h>
 
/**
* Simple reference counting singleton example
*/

class CRefCountingSingleton : public CBase
{
 
public:
 
/**
* Returns the singleton instance.
* @return Instance of class CRefCountingSingleton
*/

static CRefCountingSingleton* InstanceL();
 
/**
* Returns the singleton instance. Pushes it on the cleanup stack
* @return Instance of class CRefCountingSingleton
*/

static CRefCountingSingleton* InstanceLC();
 
/**
* Releases the singleton instance.
*/

void Release();
 
private:
 
CRefCountingSingleton();
 
/**
* Private destructor so users can't directly delete this instance.
* They must call Release()
*/

virtual ~CRefCountingSingleton();
 
void ConstructL();
 
private: // data
 
/**
* Amount of references to the singleton instance.
* Instance will be deleted when count reaches zero.
*/

TInt iReferenceCount;
 
};
 
#endif // CREFCOUNTINGSINGLETON_H

RefCountingSingleton.cpp

#include "simplesingleton.h"
 
 
// ---------------------------------------------------------------------------
// Returns the singleton instance.
// ---------------------------------------------------------------------------
//
CRefCountingSingleton* CRefCountingSingleton::InstanceL()
{
CRefCountingSingleton* self = NULL;
 
TAny* tlsPtr = Dll::Tls();
if ( tlsPtr == NULL )
{
self = new( ELeave ) CRefCountingSingleton;
CleanupStack::PushL( self );
self->ConstructL();
User::LeaveIfError( Dll::SetTls( self ) );
CleanupStack::Pop( self );
}
else
{
self = static_cast<CRefCountingSingleton*>( tlsPtr );
++self->iReferenceCount;
}
 
return self;
}
 
 
// ---------------------------------------------------------------------------
// Returns the singleton instance. Pushes it in the cleanup stack
// ---------------------------------------------------------------------------
//
CRefCountingSingleton* CRefCountingSingleton::InstanceLC()
{
CRefCountingSingleton* self = InstanceL();
CleanupReleasePushL( *self );
return self;
}
 
 
// ---------------------------------------------------------------------------
// Releases the singleton instance.
// ---------------------------------------------------------------------------
//
void CRefCountingSingleton::Release()
{
TAny* tlsPtr = Dll::Tls();
__ASSERT_DEBUG( tlsPtr != NULL, User::Panic(
_L( "CRefCountingSingleton" ), KErrNotFound ) );
 
CRefCountingSingleton* self = static_cast<CRefCountingSingleton*>( tlsPtr );
if ( --self->iReferenceCount == 0 )
{
Dll::FreeTls();
delete self;
}
}
 
 
// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
CRefCountingSingleton::CRefCountingSingleton()
: iReferenceCount( 1 )
{
}
 
 
// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
void CRefCountingSingleton::ConstructL()
{
// Perform any necessary initialization
}
 
 
// ---------------------------------------------------------------------------
// Destructor
// ---------------------------------------------------------------------------
//
CRefCountingSingleton::~CRefCountingSingleton()
{
}

Note

The above code will work only work in a DLL because it accesses TLS through the Dll class that is provided for every DLL. See here for instructions on how to access TLS from an EXE project.

This page was last modified on 25 July 2012, at 02:08.
43 page views in the last 30 days.

Was this page helpful?

Your feedback about this content is important. Let us know what you think.

 

Thank you!

We appreciate your feedback.

×