Implementation of C ++ Singleton in asp.net

Source: Internet
Author: User

Implementation of C ++ Singleton in asp.net

Solution 1

The Code is as follows:  
Class QMManager
{
Public:
Static QMManager & instance ()
{
Static QMManager instance _;
Return instance _;
}
}

This is the simplest version. There is no problem in a single thread (or C ++ 0X), but it won't work in multiple threads, because static QMManager instance _; this statement is not thread-safe.

When a static variable in a local scope is compiled, the compiler creates an additional variable to identify whether the static variable is initialized, And the compiler changes it to something like the following (pseudo code ):

The Code is as follows:  
Static QMManager & instance ()
{
Static bool constructed = false;
Static uninitialized QMManager instance _;
If (! Constructed ){
Constructed = true;
New (& s) QMManager; // construct it
}
Return instance _;
}

There is a race condition. When two threads call instance () at the same time, a constructed value has not been set after a thread runs the if statement. At this time, the constructed value is switched to another thread, and the constructed value is false, the initialization variable in the if statement is also entered. The initialization of this Singleton class is executed by both threads and is no longer a singleton.

Solution 2

One solution is locking:

The Code is as follows:  
Static QMManager & instance ()
{
Lock (); // implement the Lock yourself
Static QMManager instance _;
UnLock ();
Return instance _;
}

However, each call to instance () requires locking and unlocking at a slightly higher cost.

Solution 3

Next, change the internal static instance to a static member of the class and initialize the instance externally, that is, the file is included, and the instance is initialized before the main function is executed, there will be no thread re-entry problem:

The Code is as follows:  
Class QMManager
{
Protected:
Static QMManager instance _;
QMManager ();
~ QMManager (){};
Public:
Static QMManager * instance ()
{
Return & instance _;
}
Void do_something ();
};
QMManager: instance _; // external Initialization

This is called the hunger mode. The program is initialized as soon as it is loaded, whether or not it is called.

It seems that there is no problem, but there is still a pitfall. In A 2B case, there will be a problem: there may be problems in calling methods of another Singleton class in this Singleton class constructor.

Example:

The Code is as follows:  

//. H
Class QMManager
{
Protected:
Static QMManager instance _;
QMManager ();
~ QMManager (){};
Public:
Static QMManager * instance ()
{
Return & instance _;
}
};

Class QMSqlite
{
Protected:
Static QMSqlite instance _;
QMSqlite ();
~ QMSqlite (){};
Public:
Static QMSqlite * instance ()
{
Return & instance _;
}
Void do_something ();
};

QMManager: instance _;
QMSqlite: instance _;
//. Cpp
QMManager: QMManager ()
{
Printf ("QMManager constructorn ");
QMSqlite: instance ()-> do_something ();
}

QMSqlite: QMSqlite ()
{
Printf ("QMSqlite constructorn ");
}
Void QMSqlite: do_something ()
{
Printf ("QMSqlite do_somethingn ");
}

Here, the QMManager constructor calls the QMSqlite instance function, but QMSqlite: instance _ may not be initialized yet.

The execution process here: after the program starts, execute the following code before executing main: QMManager: instance _; to initialize the static variable of instance _ in QMManager, call the constructor of QMManager and call QMSqlite: instance () in the constructor to obtain the static variable "instance _" in QMSqlite. However, QMSqlite: instance _ has not been initialized yet, the problem arises.

Will it crash here, and the test result will not, which should be related to the compiler. The static data zone space should be allocated first. Before calling the QMManager constructor, the QMSqlite member function already exists in the memory, but it has not been tuned to its constructor, so the output is as follows:

QMManager constructor

QMSqlite do_something

QMSqlite constructor

Solution 4

So how can this problem be solved? There is a thread security problem with the singleton object as a static local variable, and the class static global variable is initialized at the beginning. The above 2B problems exist, the above two methods can solve these two problems. The boost implementation method is: the singleton object acts as a static local variable, but a helper class is added so that the singleton object can be initialized at the beginning. As follows:

The Code is as follows:  

//. H
Class QMManager
{
Protected:
Struct object_creator
{
Object_creator ()
{
QMManager: instance ();
}
Inline void do_nothing () const {}
};
Static object_creator create_object _;

QMManager ();
~ QMManager (){};
Public:
Static QMManager * instance ()
{
Static QMManager instance;
Return & instance;
}
};
QMManager: object_creator QMManager: create_object _;

Class QMSqlite
{
Protected:
QMSqlite ();
~ QMSqlite (){};
Struct object_creator
{
Object_creator ()
{
QMSqlite: instance ();
}
Inline void do_nothing () const {}
};
Static object_creator create_object _;
Public:
Static QMSqlite * instance ()
{
Static QMSqlite instance;
Return & instance;
}
Void do_something ();
};

QMManager: object_creator QMManager: create_object _;
QMSqlite: object_creator QMSqlite: create_object _;

Combined with. cpp in solution 3, we can see the correct output and call:

QMManager constructor

QMSqlite constructor

QMSqlite do_something

Let's take a look at the execution process here:

Initialize the Global static variable create_object _ Of The QMManager class _

-> Call the object_creator constructor.

-> Call the QMManager: instance () method to initialize the Singleton.

-> Execute the constructor of QMManager.

-> Call QMSqlite: instance ()

-> Initialize the local static variable QMSqlite instance

-> Execute the constructor of QMSqlite and return the Singleton.

The difference with solution 3 is that when QMManager calls the QMSqlite Singleton, solution 3 obtains the Global static variable. At this time, this variable is not initialized, and solution 4 Singleton is a static local variable, the call is initialized.

The difference from solution 1 is that the Singleton is initialized before the main function, so there will be no thread security issues.

Final boost

The template is removed for the sake of clarity. The template is used instead of writing so much repeated code. This is the template Implementation of the boost Library:

The Code is as follows:  

Template <typename T>
Struct Singleton
{
Struct object_creator
{
Object_creator () {Singleton <T>: instance ();}
Inline void do_nothing () const {}
};

Static object_creator create_object;

Public:
Typedef T object_type;
Static object_type & instance ()
{
Static object_type obj;
// It is said that this do_nothing is used to ensure that the create_object constructor is called.
// This is related to template compilation.
Create_object.do_nothing ();
Return obj;
}

};
Template <typename T> typename Singleton <T >:: object_creator Singleton <T >:: create_object;

Class QMManager
{
Protected:
QMManager ();
~ QMManager (){};
Friend class Singleton <QMManager>;
Public:
Void do_something (){};
};

Int main ()
{
Singleton <QMManager >:: instance ()-> do_something ();
Return 0;
}

In fact, the implementation of the Boost library is like a few patches, and some tricks are used. Although it does bypass the pitfalls to achieve the demand, it feels quite bad.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.