Thread.cc revision cc4062ff
1cd139dc7SShuo Chen// excerpts from http://code.google.com/p/muduo/ 2cd139dc7SShuo Chen// 3cd139dc7SShuo Chen// Use of this source code is governed by a BSD-style license 4cd139dc7SShuo Chen// that can be found in the License file. 5cd139dc7SShuo Chen// 6cd139dc7SShuo Chen// Author: Shuo Chen (giantchen at gmail dot com) 7cd139dc7SShuo Chen 8cd139dc7SShuo Chen#include "Thread.h" 9cd139dc7SShuo Chen 102b2bf878SShuo Chen#include <boost/weak_ptr.hpp> 112b2bf878SShuo Chen 12cd139dc7SShuo Chen#include <unistd.h> 13926c960eSShuo Chen#include <sys/prctl.h> 14cd139dc7SShuo Chen#include <sys/syscall.h> 15cd139dc7SShuo Chen#include <sys/types.h> 16cd139dc7SShuo Chen#include <linux/unistd.h> 17cd139dc7SShuo Chen 18cd139dc7SShuo Chennamespace muduo 19cd139dc7SShuo Chen{ 20cd139dc7SShuo Chennamespace CurrentThread 21cd139dc7SShuo Chen{ 22cd139dc7SShuo Chen __thread const char* t_threadName = "unknown"; 23cd139dc7SShuo Chen} 24cd139dc7SShuo Chen} 25cd139dc7SShuo Chen 26cd139dc7SShuo Chennamespace 27cd139dc7SShuo Chen{ 28cd139dc7SShuo Chen__thread pid_t t_cachedTid = 0; 29cd139dc7SShuo Chen 30cc4062ffSShuo Chen#if !__GLIBC_PREREQ(2,30) 31cd139dc7SShuo Chenpid_t gettid() 32cd139dc7SShuo Chen{ 33cd139dc7SShuo Chen return static_cast<pid_t>(::syscall(SYS_gettid)); 34cd139dc7SShuo Chen} 35cc4062ffSShuo Chen#endif 36cd139dc7SShuo Chen 3750da4f87SShuo Chenvoid afterFork() 3850da4f87SShuo Chen{ 3950da4f87SShuo Chen t_cachedTid = gettid(); 4050da4f87SShuo Chen muduo::CurrentThread::t_threadName = "main"; 4150da4f87SShuo Chen // no need to call pthread_atfork(NULL, NULL, &afterFork); 4250da4f87SShuo Chen} 4350da4f87SShuo Chen 44cd139dc7SShuo Chenclass ThreadNameInitializer 45cd139dc7SShuo Chen{ 46cd139dc7SShuo Chen public: 47cd139dc7SShuo Chen ThreadNameInitializer() 48cd139dc7SShuo Chen { 49cd139dc7SShuo Chen muduo::CurrentThread::t_threadName = "main"; 5050da4f87SShuo Chen pthread_atfork(NULL, NULL, &afterFork); 51cd139dc7SShuo Chen } 52cd139dc7SShuo Chen}; 53cd139dc7SShuo Chen 54cd139dc7SShuo ChenThreadNameInitializer init; 552b2bf878SShuo Chen 562b2bf878SShuo Chenstruct ThreadData 572b2bf878SShuo Chen{ 582b2bf878SShuo Chen typedef muduo::Thread::ThreadFunc ThreadFunc; 592b2bf878SShuo Chen ThreadFunc func_; 602b2bf878SShuo Chen std::string name_; 612b2bf878SShuo Chen boost::weak_ptr<pid_t> wkTid_; 622b2bf878SShuo Chen 632b2bf878SShuo Chen ThreadData(const ThreadFunc& func, 642b2bf878SShuo Chen const std::string& name, 652b2bf878SShuo Chen const boost::shared_ptr<pid_t>& tid) 662b2bf878SShuo Chen : func_(func), 672b2bf878SShuo Chen name_(name), 682b2bf878SShuo Chen wkTid_(tid) 692b2bf878SShuo Chen { } 702b2bf878SShuo Chen 712b2bf878SShuo Chen void runInThread() 722b2bf878SShuo Chen { 73ac2f0106SShuo Chen pid_t tid = muduo::CurrentThread::tid(); 74ac2f0106SShuo Chen boost::shared_ptr<pid_t> ptid = wkTid_.lock(); 75ac2f0106SShuo Chen 76ac2f0106SShuo Chen if (ptid) 772b2bf878SShuo Chen { 78ac2f0106SShuo Chen *ptid = tid; 79ac2f0106SShuo Chen ptid.reset(); 802b2bf878SShuo Chen } 812b2bf878SShuo Chen 82926c960eSShuo Chen muduo::CurrentThread::t_threadName = name_.empty() ? "muduoThread" : name_.c_str(); 83926c960eSShuo Chen ::prctl(PR_SET_NAME, muduo::CurrentThread::t_threadName); 842b2bf878SShuo Chen func_(); // FIXME: surround with try-catch, see muduo 852b2bf878SShuo Chen muduo::CurrentThread::t_threadName = "finished"; 862b2bf878SShuo Chen } 872b2bf878SShuo Chen}; 882b2bf878SShuo Chen 892b2bf878SShuo Chenvoid* startThread(void* obj) 902b2bf878SShuo Chen{ 912b2bf878SShuo Chen ThreadData* data = static_cast<ThreadData*>(obj); 922b2bf878SShuo Chen data->runInThread(); 932b2bf878SShuo Chen delete data; 942b2bf878SShuo Chen return NULL; 952b2bf878SShuo Chen} 962b2bf878SShuo Chen 97cd139dc7SShuo Chen} 98cd139dc7SShuo Chen 99cd139dc7SShuo Chenusing namespace muduo; 100cd139dc7SShuo Chen 101cd139dc7SShuo Chenpid_t CurrentThread::tid() 102cd139dc7SShuo Chen{ 103cd139dc7SShuo Chen if (t_cachedTid == 0) 104cd139dc7SShuo Chen { 105cd139dc7SShuo Chen t_cachedTid = gettid(); 106cd139dc7SShuo Chen } 107cd139dc7SShuo Chen return t_cachedTid; 108cd139dc7SShuo Chen} 109cd139dc7SShuo Chen 110cd139dc7SShuo Chenconst char* CurrentThread::name() 111cd139dc7SShuo Chen{ 112cd139dc7SShuo Chen return t_threadName; 113cd139dc7SShuo Chen} 114cd139dc7SShuo Chen 115cd139dc7SShuo Chenbool CurrentThread::isMainThread() 116cd139dc7SShuo Chen{ 117cd139dc7SShuo Chen return tid() == ::getpid(); 118cd139dc7SShuo Chen} 119cd139dc7SShuo Chen 120cd139dc7SShuo ChenAtomicInt32 Thread::numCreated_; 121cd139dc7SShuo Chen 122cd139dc7SShuo ChenThread::Thread(const ThreadFunc& func, const std::string& n) 123cd139dc7SShuo Chen : started_(false), 1242b2bf878SShuo Chen joined_(false), 125cd139dc7SShuo Chen pthreadId_(0), 1262b2bf878SShuo Chen tid_(new pid_t(0)), 127cd139dc7SShuo Chen func_(func), 128cd139dc7SShuo Chen name_(n) 129cd139dc7SShuo Chen{ 130cd139dc7SShuo Chen numCreated_.increment(); 131cd139dc7SShuo Chen} 132cd139dc7SShuo Chen 133cd139dc7SShuo ChenThread::~Thread() 134cd139dc7SShuo Chen{ 1352b2bf878SShuo Chen if (started_ && !joined_) 1362b2bf878SShuo Chen { 1372b2bf878SShuo Chen pthread_detach(pthreadId_); 1382b2bf878SShuo Chen } 139cd139dc7SShuo Chen} 140cd139dc7SShuo Chen 141cd139dc7SShuo Chenvoid Thread::start() 142cd139dc7SShuo Chen{ 143cd139dc7SShuo Chen assert(!started_); 144cd139dc7SShuo Chen started_ = true; 1452b2bf878SShuo Chen 1462b2bf878SShuo Chen ThreadData* data = new ThreadData(func_, name_, tid_); 1472b2bf878SShuo Chen if (pthread_create(&pthreadId_, NULL, &startThread, data)) 1482b2bf878SShuo Chen { 1492b2bf878SShuo Chen started_ = false; 1502b2bf878SShuo Chen delete data; 1512b2bf878SShuo Chen abort(); 1522b2bf878SShuo Chen } 153cd139dc7SShuo Chen} 154cd139dc7SShuo Chen 155cd139dc7SShuo Chenvoid Thread::join() 156cd139dc7SShuo Chen{ 157cd139dc7SShuo Chen assert(started_); 1582b2bf878SShuo Chen assert(!joined_); 1592b2bf878SShuo Chen joined_ = true; 160cd139dc7SShuo Chen pthread_join(pthreadId_, NULL); 161cd139dc7SShuo Chen} 162