用模板实现单例模式(线程安全)、模板方式实现动态创建对象

一、用模板实现单例模式

前面的文章中,用过多种方法实现单例模式,现在用模板方式来实现:

为了实现线程安全,需要在linux 下使用pthread_mutex_t 加锁,请使用g++ 编译并需要链接 -lpthread

使用的是double-check lock, 指针instance_ 最好声明为volatile,防止优化。

Singleton.h:

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
 
/*************************************************************************
    > File Name: Singleton.h
    > Author: Simba
    > Mail: dameng34@163.com
    > Created Time: Wed 02 Apr 2014 01:33:39 AM PDT
 ************************************************************************/

#ifndef _SINGLETON_H_
#define _SINGLETON_H_

#include <iostream>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>

using namespace std;

template < typename T > class Singleton
{

public:
    static T &GetInstance()
    {
        Init();
        return *instance_;
    }

private:
    static void Init()
    {
        if (instance_ == 0)
        {

            pthread_mutex_lock(&g_mutex);
            if (instance_ == 0)
            {
                instance_ = new T;
                atexit(Destroy);    //程序结束时调用注册的函数
            }
            pthread_mutex_unlock(&g_mutex);
        }
    }

    static void Destroy()
    {
        delete instance_;
    }

    Singleton(const Singleton &other);
    Singleton &operator=(const Singleton &other);
    Singleton();
    ~Singleton();

    static T * volatile instance_;
    static pthread_mutex_t g_mutex;
};

template < typename T >
T * volatile Singleton < T >::instance_ = 0;

template < typename T >
pthread_mutex_t Singleton<T> ::g_mutex = PTHREAD_MUTEX_INITIALIZER;

#endif              // _SINGLETON_H_

main.cpp:

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
 
/*************************************************************************
    > File Name: main.cpp
    > Author: Simba
    > Mail: dameng34@163.com
    > Created Time: Wed 02 Apr 2014 01:30:13 AM PDT
 ************************************************************************/

#include "Singleton.h"

class ApplicationImpl
{

public:
    ApplicationImpl()
    {
        cout << "ApplicationImpl ..." << endl;
    }

    ~ApplicationImpl()
    {
        cout << "~ApplicationImpl ..." << endl;
    }

    void Run()
    {
        cout << "Run ..." << endl;
    }
};

typedef Singleton < ApplicationImpl > Application;

void *routine(void *arg)
{
    Application::GetInstance().Run();
}

int main(void)
{
    Application::GetInstance().Run();

    pthread_t tid;
    int ret;
    if ((ret = pthread_create(&tid, NULL, routine, NULL)) != 0)
    {
        fprintf(stderr, "pthread create: %s\n", strerror(ret));
        exit(EXIT_FAILURE);
    }

    Application::GetInstance().Run();

    pthread_join(tid, NULL);

    return 0;
}


即 将Singleton 实现为模板类,将ApplicationImpl 类包装成单例模式类,可以看到构造函数和析构函数都只调用了一次。程序使用一个小技巧,用axexit 函数注册了程序结束时需要调用的函数。


二、模板方式实现动态创建对象

前面的文章曾经使用宏定义的方式实现动态创建对象,现在在 DynBase.h 中用模板类将宏定义替换掉,其他代码不变:

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
 
//class Register
//{
//public:
//    Register(const string &name, CREATE_FUNC func)
//    {
//        DynObjectFactory::Register(name, func);
//    }
//};
//
//#define REGISTER_CLASS(class_name) \
//class class_name##Register { \
//public: \
//    static void* NewInstance() \
//    { \
//        return new class_name; \
//    } \
//private: \
//    static Register reg_; \
//}; \
//Register class_name##Register::reg_(#class_name, class_name##Register::NewInstance)

template <typename T>
class DelegatingClass
{
public:
    DelegatingClass(const string &name)
    {
        DynObjectFactory::Register(name, &(DelegatingClass::NewInstance));
    }

    static void *NewInstance()
    {
        return new T;
    }
};

#define REGISTER_CLASS(class_name) DelegatingClass<class_name> class##class_name(#class_name)

即 REGISTER_CLASS(class_name) 宏定义展开会构造一个模板类实例对象,调用3次宏定义即3个模板类实例对象,调用构造函数

const string &name),进而调用Register 完成注册,接下去的流程与以前的程序一样,不再赘述。输出如下:

 

 

参考:

C++ primer 第四版
Effective C++ 3rd
C++编程规范

posted on 2018-02-26 08:43  AlanTu  阅读(999)  评论(0编辑  收藏  举报

导航