typedefboost::function
__threadstring t_obj1(“cppcourse”); //错误,不能调用对象的构造函数
__threadstring* t_obj2 = new string; //错误,初始化只能是编译期常量
__threadstring* t_obj3 = NULL; //正确
线程特定属性tsd,可以修饰非POD类型
boost::is_same判断类型是否为同一类型
// 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_THREAD_H
#define MUDUO_BASE_THREAD_H
#include
#include
#include
#include
#include
namespace muduo
{
class Thread : boost::noncopyable
{
public:
typedef boost::function ThreadFunc;
explicit Thread(const ThreadFunc&, const string& name = string());
~Thread();
void start();
int join(); // return pthread_join()
bool started() const { return started_; }
// pthread_t pthreadId() const { return pthreadId_; }
pid_t tid() const { return tid_; }
const string& name() const { return name_; }
static int numCreated() { return numCreated_.get(); }
private:
static void* startThread(void* thread);
void runInThread();
bool started_;
pthread_t pthreadId_;
pid_t tid_;
ThreadFunc func_;
string name_;
static AtomicInt32 numCreated_;
};
}
#endif
// 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_CURRENTTHREAD_H
#define MUDUO_BASE_CURRENTTHREAD_H
namespace muduo
{
namespace CurrentThread
{
// internal
extern __thread int t_cachedTid;
extern __thread char t_tidString[32];
extern __thread const char* t_threadName;
void cacheTid();
inline int tid()
{
if (t_cachedTid == 0)
{
cacheTid();
}
return t_cachedTid;
}
inline const char* tidString() // for logging
{
return t_tidString;
}
inline const char* name()
{
return t_threadName;
}
bool isMainThread();
}
}
#endif
// 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)
#include
#include
#include
//#include
#include
#include
#include
#include
#include
#include
#include
#include
namespace muduo
{
namespace CurrentThread
{
// __thread修饰的变量是线程局部存储的。
__thread int t_cachedTid = 0; // 线程真实pid(tid)的缓存,
// 是为了减少::syscall(SYS_gettid)系统调用的次数
// 提高获取tid的效率
__thread char t_tidString[32]; // 这是tid的字符串表示形式
__thread const char* t_threadName = "unknown";
const bool sameType = boost::is_same::value;
BOOST_STATIC_ASSERT(sameType);
}
namespace detail
{
pid_t gettid()
{
return static_cast(::syscall(SYS_gettid));
}
void afterFork()
{
muduo::CurrentThread::t_cachedTid = 0;
muduo::CurrentThread::t_threadName = "main";
CurrentThread::tid();
// no need to call pthread_atfork(NULL, NULL, &afterFork);
}
class ThreadNameInitializer
{
public:
ThreadNameInitializer()
{
muduo::CurrentThread::t_threadName = "main";
CurrentThread::tid();
pthread_atfork(NULL, NULL, &afterFork);
}
};
ThreadNameInitializer init;
}
}
using namespace muduo;
void CurrentThread::cacheTid()
{
if (t_cachedTid == 0)
{
t_cachedTid = detail::gettid();
int n = snprintf(t_tidString, sizeof t_tidString, "%5d ", t_cachedTid);
assert(n == 6); (void) n;
}
}
bool CurrentThread::isMainThread()
{
return tid() == ::getpid();
}
AtomicInt32 Thread::numCreated_;
Thread::Thread(const ThreadFunc& func, const string& n)
: started_(false),
pthreadId_(0),
tid_(0),
func_(func),
name_(n)
{
numCreated_.increment();
}
Thread::~Thread()
{
// no join
}
void Thread::start()
{
assert(!started_);
started_ = true;
errno = pthread_create(&pthreadId_, NULL, &startThread, this);
if (errno != 0)
{
//LOG_SYSFATAL << "Failed in pthread_create";
}
}
int Thread::join()
{
assert(started_);
return pthread_join(pthreadId_, NULL);
}
void* Thread::startThread(void* obj)
{
Thread* thread = static_cast(obj);
thread->runInThread();
return NULL;
}
void Thread::runInThread()
{
tid_ = CurrentThread::tid();
muduo::CurrentThread::t_threadName = name_.c_str();
try
{
func_();
muduo::CurrentThread::t_threadName = "finished";
}
catch (const Exception& ex)
{
muduo::CurrentThread::t_threadName = "crashed";
fprintf(stderr, "exception caught in Thread %s\n", name_.c_str());
fprintf(stderr, "reason: %s\n", ex.what());
fprintf(stderr, "stack trace: %s\n", ex.stackTrace());
abort();
}
catch (const std::exception& ex)
{
muduo::CurrentThread::t_threadName = "crashed";
fprintf(stderr, "exception caught in Thread %s\n", name_.c_str());
fprintf(stderr, "reason: %s\n", ex.what());
abort();
}
catch (...)
{
muduo::CurrentThread::t_threadName = "crashed";
fprintf(stderr, "unknown exception caught in Thread %s\n", name_.c_str());
throw; // rethrow
}
}
#include
#include
#include
#include
#include
void threadFunc()
{
printf("tid=%d\n", muduo::CurrentThread::tid());
}
void threadFunc2(int x)
{
printf("tid=%d, x=%d\n", muduo::CurrentThread::tid(), x);
}
class Foo
{
public:
explicit Foo(double x)
: x_(x)
{
}
void memberFunc()
{
printf("tid=%d, Foo::x_=%f\n", muduo::CurrentThread::tid(), x_);
}
void memberFunc2(const std::string& text)
{
printf("tid=%d, Foo::x_=%f, text=%s\n", muduo::CurrentThread::tid(), x_, text.c_str());
}
private:
double x_;
};
int main()
{
printf("pid=%d, tid=%d\n", ::getpid(), muduo::CurrentThread::tid());
muduo::Thread t1(threadFunc);
t1.start();
t1.join();
muduo::Thread t2(boost::bind(threadFunc2, 42),
"thread for free function with argument");
t2.start();
t2.join();
Foo foo(87.53);
muduo::Thread t3(boost::bind(&Foo::memberFunc, &foo),
"thread for member function without argument");
t3.start();
t3.join();
muduo::Thread t4(boost::bind(&Foo::memberFunc2, boost::ref(foo), std::string("Shuo Chen")));
t4.start();
t4.join();
printf("number of created threads %d\n", muduo::Thread::numCreated());
}
// 一个在多线程程序里fork造成死锁的例子
// 一个输出示例:
/*
pid = 19445 Entering main ...
pid = 19445 begin doit ...
pid = 19447 begin doit ...
pid = 19445 end doit ...
pid = 19445 Exiting main ...
父进程在创建了一个线程,并对mutex加锁,
父进程创建一个子进程,在子进程中调用doit,由于子进程会复制父进程的内存,这时候mutex处于锁的状态,
父进程在复制子进程的时候,只会复制当前线程的执行状态,其它线程不会复制。因此子进程会处于死锁的状态。
*/
#include
#include
#include
#include
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void* doit(void* arg)
{
printf("pid = %d begin doit ...\n",static_cast(getpid()));
pthread_mutex_lock(&mutex);
struct timespec ts = {2, 0};
nanosleep(&ts, NULL);
pthread_mutex_unlock(&mutex);
printf("pid = %d end doit ...\n",static_cast(getpid()));
return NULL;
}
int main(void)
{
printf("pid = %d Entering main ...\n", static_cast(getpid()));
pthread_t tid;
pthread_create(&tid, NULL, doit, NULL);
struct timespec ts = {1, 0};
nanosleep(&ts, NULL);
if (fork() == 0)
{
doit(NULL);
}
pthread_join(tid, NULL);
printf("pid = %d Exiting main ...\n",static_cast(getpid()));
return 0;
}
#include
#include
#include
#include
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void* doit(void* arg)
{
printf("pid = %d begin doit ...\n",static_cast(getpid()));
pthread_mutex_lock(&mutex);
struct timespec ts = {2, 0};
nanosleep(&ts, NULL);
pthread_mutex_unlock(&mutex);
printf("pid = %d end doit ...\n",static_cast(getpid()));
return NULL;
}
void prepare(void)
{
pthread_mutex_unlock(&mutex);
}
void parent(void)
{
pthread_mutex_lock(&mutex);
}
int main(void)
{
pthread_atfork(prepare, parent, NULL);
printf("pid = %d Entering main ...\n", static_cast(getpid()));
pthread_t tid;
pthread_create(&tid, NULL, doit, NULL);
struct timespec ts = {1, 0};
nanosleep(&ts, NULL);
if (fork() == 0)
{
doit(NULL);
}
pthread_join(tid, NULL);
printf("pid = %d Exiting main ...\n",static_cast(getpid()));
return 0;
}
#include
#include
#include
#include
void prepare(void)
{
printf("pid = %d prepare ...\n", static_cast(getpid()));
}
void parent(void)
{
printf("pid = %d parent ...\n", static_cast(getpid()));
}
void child(void)
{
printf("pid = %d child ...\n", static_cast(getpid()));
}
int main(void)
{
printf("pid = %d Entering main ...\n", static_cast(getpid()));
pthread_atfork(prepare, parent, child);
fork();
printf("pid = %d Exiting main ...\n",static_cast(getpid()));
return 0;
}