muduo库学习笔记十三:base库之ThreadLocalSingleton

 

线程本地存储单例类针对“每个结构”每个线程仅有一个线程本地存储类对象

muduo库学习笔记十三:base库之ThreadLocalSingletonmuduo库学习笔记十三:base库之ThreadLocalSingleton

t_value_:类型为T的指针是pod类型可以用__thread修饰,每个线程一份

deleter:Deleter类对象

instance():返回T引用

pointer():返回T指针

destructor():借助Deleter才能被调用

Deleter类:嵌套在ThreadLocalSingleton类中,借助于TSD实现线程本地存储机制

Show Me The Code

// Use of this source code is governed by a BSD-style license
// that can be found in the License file.
//
// Author: Shuo Chen (chenshuo at chenshuo dot com)

#ifndef MUDUO_BASE_THREADLOCALSINGLETON_H
#define MUDUO_BASE_THREADLOCALSINGLETON_H

#include <boost/noncopyable.hpp>
#include <assert.h>
#include <pthread.h>

namespace muduo
{

template<typename T>
class ThreadLocalSingleton : boost::noncopyable
{
 public:

  static T& instance()
  {
    if (!t_value_)
    {
      t_value_ = new T();
      deleter_.set(t_value_);
    }
    return *t_value_;//每个线程都有一份自己的指针,因此不需要按照线程安全的方式实现
  }

  static T* pointer()
  {
    return t_value_;
  }

 private:

  static void destructor(void* obj)
  {
    assert(obj == t_value_);
    typedef char T_must_be_complete_type[sizeof(T) == 0 ? -1 : 1];
    delete t_value_;//销毁key对应的值
    t_value_ = 0;
  }

  class Deleter//主要为了能够回调destructor--动态销毁key对应的值
  {
   public:
    Deleter()
    {
      pthread_key_create(&pkey_, &ThreadLocalSingleton::destructor);
    }

    ~Deleter()
    {
      pthread_key_delete(pkey_);
    }

    void set(T* newObj)
    {
      assert(pthread_getspecific(pkey_) == NULL);
      pthread_setspecific(pkey_, newObj);
    }

    pthread_key_t pkey_;
  };

  static __thread T* t_value_;//线程本地存储--类型为T的指针,每个线程有一份
  static Deleter deleter_;//Deleter是线程本地存储类,deleter_每个线程一份,用于销毁t_value_指针所指向的对象
};

template<typename T>
__thread T* ThreadLocalSingleton<T>::t_value_ = 0;//静态类成员定义

template<typename T>
typename ThreadLocalSingleton<T>::Deleter ThreadLocalSingleton<T>::deleter_;//静态类成员定义

}
#endif

说明:ThreadLocalSingleton类的作用与 muduo库学习笔记十二:base库之threadLocal 中 使用示例2 

#define STL muduo::Singleton<muduo::ThreadLocal<Test> >::instance().value()

的作用效果一样,但是一般使用前者。

使用示例

#include <muduo/base/ThreadLocalSingleton.h>
#include <muduo/base/CurrentThread.h>
#include <muduo/base/Thread.h>

#include <boost/bind.hpp>
#include <boost/noncopyable.hpp>
#include <stdio.h>

class Test : boost::noncopyable
{
 public:
  Test()
  {
    printf("tid=%d, constructing %p\n", muduo::CurrentThread::tid(), this);
  }

  ~Test()
  {
    printf("tid=%d, destructing %p %s\n", muduo::CurrentThread::tid(), this, name_.c_str());
  }

  const std::string& name() const { return name_; }
  void setName(const std::string& n) { name_ = n; }

 private:
  std::string name_;
};

void threadFunc(const char* changeTo)
{
  printf("tid=%d, %p name=%s\n",
         muduo::CurrentThread::tid(),
         &muduo::ThreadLocalSingleton<Test>::instance(),
         muduo::ThreadLocalSingleton<Test>::instance().name().c_str());
  muduo::ThreadLocalSingleton<Test>::instance().setName(changeTo);
  printf("tid=%d, %p name=%s\n",
         muduo::CurrentThread::tid(),
         &muduo::ThreadLocalSingleton<Test>::instance(),
         muduo::ThreadLocalSingleton<Test>::instance().name().c_str());

  // no need to manually delete it
  // muduo::ThreadLocalSingleton<Test>::destroy();
}

int main()
{
  muduo::ThreadLocalSingleton<Test>::instance().setName("main one");
  /*
  与 muduo库学习笔记十二:base库之threadLocal 使用示例1:
  相比较进行说明
	muduo::ThreadLocal<Test> testObj1;//线程本地存储类对象1
	muduo::ThreadLocal<Test> testObj2;//线程本地存储类对象2

  ThreadLocalSingleton类使用针对“每个结构”每个线程仅有一个线程本地存储类对象
  */
  muduo::Thread t1(boost::bind(threadFunc, "thread1"));
  muduo::Thread t2(boost::bind(threadFunc, "thread2"));
  t1.start();
  t2.start();
  t1.join();
  printf("tid=%d, %p name=%s\n",
         muduo::CurrentThread::tid(),
         &muduo::ThreadLocalSingleton<Test>::instance(),
         muduo::ThreadLocalSingleton<Test>::instance().name().c_str());
  t2.join();

  pthread_exit(0);
}

结果

muduo库学习笔记十三:base库之ThreadLocalSingleton

muduo库学习笔记十三:base库之ThreadLocalSingletonmuduo库学习笔记十三:base库之ThreadLocalSingleton 麻子来了 发布了109 篇原创文章 · 获赞 79 · 访问量 27万+ 私信 关注
上一篇:muduo源码解析30-网络库8:tcpserver类


下一篇:muduo网络库学习--封装