Boost C++ 库

...世界上最受推崇和设计最精良的 C++ 库项目之一。 Herb SutterAndrei Alexandrescu, C++ 编码标准

PrevUpHomeNext

线程局部存储

thread_specific_ptr

概要

线程局部存储允许多线程应用程序为每个线程拥有给定数据项的单独实例。在单线程应用程序中使用静态或全局数据的情况下,这可能导致多线程应用程序中的争用、死锁或数据损坏。一个例子是 C errno 变量,用于存储与标准 C 库函数相关的错误代码。对于支持多线程应用程序的编译器来说,为每个线程提供单独的 errno 实例是一种常见的做法(POSIX 要求),以避免不同线程竞争读取或更新该值。

尽管编译器通常以声明语法的扩展形式提供此功能(例如 __declspec(thread)threadstatic 或命名空间范围变量声明的注解),但这种支持是非可移植的,并且通常在某些方面受到限制,例如仅支持 POD 类型。

使用 boost::thread_specific_ptr 的可移植线程局部存储

boost::thread_specific_ptr 为线程局部存储提供了一种可移植的机制,该机制适用于 Boost.Thread 支持的所有编译器。boost::thread_specific_ptr 的每个实例都表示一个指向对象的指针(例如 errno),其中每个线程都必须具有不同的值。可以使用 get() 成员函数或使用 *-> 指针解引用运算符来获取当前线程的值。最初,指针在每个线程中都具有 NULL 值,但是可以使用 reset() 成员函数设置当前线程的值。

如果使用 reset() 更改了当前线程的指针值,则通过调用清理例程来销毁先前的值。或者,可以通过调用 release() 成员函数将存储的值重置为 NULL 并返回先前的值,从而允许应用程序重新负责销毁该对象。

线程退出时清理

当线程退出时,将销毁与每个 boost::thread_specific_ptr 实例关联的对象。默认情况下,指向指针 p 的对象通过调用 delete p 销毁,但是可以通过为构造函数提供清理例程来为 boost::thread_specific_ptr 的特定实例覆盖此操作。在这种情况下,通过调用 func(p) 销毁对象,其中 func 是提供给构造函数的清理例程。清理函数的调用顺序未指定。如果清理例程设置了与已清理的 boost::thread_specific_ptr 实例关联的值,则该值将添加到清理列表。当没有具有值的 boost::thread_specific_ptr 的未完成实例时,清理完成。

注意:在某些平台上,对于使用平台原生 API 创建的线程,不执行线程特定数据的清理。在这些平台上,除非从该线程手动调用 boost::on_thread_exit(),否则此类清理仅针对使用 boost::thread 启动的线程完成。

关于键性质的基本原理

Boost.Thread 使用 thread_specific_ptr 实例的地址作为线程特定指针的键。这避免了创建/销毁需要锁来防止竞争条件的键。这有一点性能责任,因为必须使用关联容器来完成访问。

//  #include <boost/thread/tss.hpp>

namespace boost
{
  template <typename T>
  class thread_specific_ptr
  {
  public:
      thread_specific_ptr();
      explicit thread_specific_ptr(void (*cleanup_function)(T*));
      ~thread_specific_ptr();

      T* get() const;
      T* operator->() const;
      T& operator*() const;

      T* release();
      void reset(T* new_value=0);
  };
}

要求

delete this->get() 是良构的。

效果

构造一个 thread_specific_ptr 对象,用于存储指向类型为 T 的对象的指针,该对象特定于每个线程。默认的基于 delete 的清理函数将用于在调用 reset() 或线程退出时销毁任何线程局部对象。

抛出

如果发生错误,则抛出 boost::thread_resource_error

要求

cleanup_function(this->get()) 不会抛出任何异常。

效果

构造一个 thread_specific_ptr 对象,用于存储指向类型为 T 的对象的指针,该对象特定于每个线程。当调用 reset() 或线程退出时,将使用提供的 cleanup_function 销毁任何线程局部对象。

抛出

如果发生错误,则抛出 boost::thread_resource_error

要求

与此 thread_specific_ptr 关联的所有线程特定实例(可能除了与此线程关联的实例之外)都必须为空。

效果

调用 this->reset() 以清理当前线程的关联值,并销毁 *this

抛出

无。

备注

此要求是由于为了删除所有这些实例,实现应被迫维护具有关联特定 ptr 的所有线程的列表,这与线程特定数据的目标背道而驰。

[Note] 注意

需要注意确保在 boost::thread_specific_ptr 的实例被销毁后仍在运行的任何线程都不会在该实例上调用任何成员函数。

返回值

与当前线程关联的指针。

抛出

无。

[Note] 注意

对于每个线程,与 boost::thread_specific_ptr 实例关联的初始值为 NULL

返回值

this->get()

抛出

无。

要求

this->get 不为 NULL

返回值

*(this->get())

抛出

无。

效果

如果 this->get()!=new_valuethis->get() 不为 NULL,则根据需要调用 delete this->get()cleanup_function(this->get())。将 new_value 存储为与当前线程关联的指针。

后置条件

this->get()==new_value

抛出

如果发生错误,则抛出 boost::thread_resource_error

效果

返回 this->get() 并存储 NULL 作为与当前线程关联的指针,而不调用清理函数。

后置条件

this->get()==0

抛出

无。


PrevUpHomeNext