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> 13cd139dc7SShuo Chen#include <sys/syscall.h> 14cd139dc7SShuo Chen#include <sys/types.h> 15b9b67c9bSShuo Chen 16b9b67c9bSShuo Chen#if __FreeBSD__ 17b9b67c9bSShuo Chen#include <pthread_np.h> 18b9b67c9bSShuo Chen#else 19b9b67c9bSShuo Chen#include <sys/prctl.h> 20cd139dc7SShuo Chen#include <linux/unistd.h> 21b9b67c9bSShuo Chen#endif 22cd139dc7SShuo Chen 23cd139dc7SShuo Chennamespace muduo 24cd139dc7SShuo Chen{ 25cd139dc7SShuo Chennamespace CurrentThread 26cd139dc7SShuo Chen{ 27b9b67c9bSShuo Chen __thread const char* t_threadName = "unnamedThread"; 28cd139dc7SShuo Chen} 29cd139dc7SShuo Chen} 30cd139dc7SShuo Chen 31cd139dc7SShuo Chennamespace 32cd139dc7SShuo Chen{ 33cd139dc7SShuo Chen__thread pid_t t_cachedTid = 0; 34cd139dc7SShuo Chen 35b9b67c9bSShuo Chen#if __FreeBSD__ 36b9b67c9bSShuo Chenpid_t gettid() 37b9b67c9bSShuo Chen{ 38b9b67c9bSShuo Chen return pthread_getthreadid_np(); 39b9b67c9bSShuo Chen} 40b9b67c9bSShuo Chen#else 41cc4062ffSShuo Chen#if !__GLIBC_PREREQ(2,30) 42cd139dc7SShuo Chenpid_t gettid() 43cd139dc7SShuo Chen{ 44cd139dc7SShuo Chen return static_cast<pid_t>(::syscall(SYS_gettid)); 45cd139dc7SShuo Chen} 46cc4062ffSShuo Chen#endif 47b9b67c9bSShuo Chen#endif 48cd139dc7SShuo Chen 4950da4f87SShuo Chenvoid afterFork() 5050da4f87SShuo Chen{ 5150da4f87SShuo Chen t_cachedTid = gettid(); 5250da4f87SShuo Chen muduo::CurrentThread::t_threadName = "main"; 5350da4f87SShuo Chen // no need to call pthread_atfork(NULL, NULL, &afterFork); 5450da4f87SShuo Chen} 5550da4f87SShuo Chen 56cd139dc7SShuo Chenclass ThreadNameInitializer 57cd139dc7SShuo Chen{ 58cd139dc7SShuo Chen public: 59cd139dc7SShuo Chen ThreadNameInitializer() 60cd139dc7SShuo Chen { 61cd139dc7SShuo Chen muduo::CurrentThread::t_threadName = "main"; 6250da4f87SShuo Chen pthread_atfork(NULL, NULL, &afterFork); 63cd139dc7SShuo Chen } 64cd139dc7SShuo Chen}; 65cd139dc7SShuo Chen 66cd139dc7SShuo ChenThreadNameInitializer init; 672b2bf878SShuo Chen 682b2bf878SShuo Chenstruct ThreadData 692b2bf878SShuo Chen{ 702b2bf878SShuo Chen typedef muduo::Thread::ThreadFunc ThreadFunc; 712b2bf878SShuo Chen ThreadFunc func_; 722b2bf878SShuo Chen std::string name_; 732b2bf878SShuo Chen boost::weak_ptr<pid_t> wkTid_; 742b2bf878SShuo Chen 752b2bf878SShuo Chen ThreadData(const ThreadFunc& func, 762b2bf878SShuo Chen const std::string& name, 772b2bf878SShuo Chen const boost::shared_ptr<pid_t>& tid) 782b2bf878SShuo Chen : func_(func), 792b2bf878SShuo Chen name_(name), 802b2bf878SShuo Chen wkTid_(tid) 812b2bf878SShuo Chen { } 822b2bf878SShuo Chen 832b2bf878SShuo Chen void runInThread() 842b2bf878SShuo Chen { 85ac2f0106SShuo Chen pid_t tid = muduo::CurrentThread::tid(); 86ac2f0106SShuo Chen boost::shared_ptr<pid_t> ptid = wkTid_.lock(); 87ac2f0106SShuo Chen 88ac2f0106SShuo Chen if (ptid) 892b2bf878SShuo Chen { 90ac2f0106SShuo Chen *ptid = tid; 91ac2f0106SShuo Chen ptid.reset(); 922b2bf878SShuo Chen } 932b2bf878SShuo Chen 94b9b67c9bSShuo Chen if (!name_.empty()) 95b9b67c9bSShuo Chen muduo::CurrentThread::t_threadName = name_.c_str(); 96b9b67c9bSShuo Chen#if __FreeBSD__ 97b9b67c9bSShuo Chen // setname_np() costs as much as creating a thread on FreeBSD 13. 98b9b67c9bSShuo Chen pthread_setname_np(pthread_self(), muduo::CurrentThread::t_threadName); 99b9b67c9bSShuo Chen#else 100926c960eSShuo Chen ::prctl(PR_SET_NAME, muduo::CurrentThread::t_threadName); 101b9b67c9bSShuo Chen#endif 1022b2bf878SShuo Chen func_(); // FIXME: surround with try-catch, see muduo 1032b2bf878SShuo Chen muduo::CurrentThread::t_threadName = "finished"; 1042b2bf878SShuo Chen } 1052b2bf878SShuo Chen}; 1062b2bf878SShuo Chen 1072b2bf878SShuo Chenvoid* startThread(void* obj) 1082b2bf878SShuo Chen{ 1092b2bf878SShuo Chen ThreadData* data = static_cast<ThreadData*>(obj); 1102b2bf878SShuo Chen data->runInThread(); 1112b2bf878SShuo Chen delete data; 1122b2bf878SShuo Chen return NULL; 1132b2bf878SShuo Chen} 1142b2bf878SShuo Chen 115cd139dc7SShuo Chen} 116cd139dc7SShuo Chen 117cd139dc7SShuo Chenusing namespace muduo; 118cd139dc7SShuo Chen 119cd139dc7SShuo Chenpid_t CurrentThread::tid() 120cd139dc7SShuo Chen{ 121cd139dc7SShuo Chen if (t_cachedTid == 0) 122cd139dc7SShuo Chen { 123cd139dc7SShuo Chen t_cachedTid = gettid(); 124cd139dc7SShuo Chen } 125cd139dc7SShuo Chen return t_cachedTid; 126cd139dc7SShuo Chen} 127cd139dc7SShuo Chen 128cd139dc7SShuo Chenconst char* CurrentThread::name() 129cd139dc7SShuo Chen{ 130cd139dc7SShuo Chen return t_threadName; 131cd139dc7SShuo Chen} 132cd139dc7SShuo Chen 133cd139dc7SShuo Chenbool CurrentThread::isMainThread() 134cd139dc7SShuo Chen{ 135cd139dc7SShuo Chen return tid() == ::getpid(); 136cd139dc7SShuo Chen} 137cd139dc7SShuo Chen 138cd139dc7SShuo ChenAtomicInt32 Thread::numCreated_; 139cd139dc7SShuo Chen 140cd139dc7SShuo ChenThread::Thread(const ThreadFunc& func, const std::string& n) 141cd139dc7SShuo Chen : started_(false), 1422b2bf878SShuo Chen joined_(false), 143cd139dc7SShuo Chen pthreadId_(0), 1442b2bf878SShuo Chen tid_(new pid_t(0)), 145cd139dc7SShuo Chen func_(func), 146cd139dc7SShuo Chen name_(n) 147cd139dc7SShuo Chen{ 148cd139dc7SShuo Chen numCreated_.increment(); 149cd139dc7SShuo Chen} 150cd139dc7SShuo Chen 151cd139dc7SShuo ChenThread::~Thread() 152cd139dc7SShuo Chen{ 1532b2bf878SShuo Chen if (started_ && !joined_) 1542b2bf878SShuo Chen { 1552b2bf878SShuo Chen pthread_detach(pthreadId_); 1562b2bf878SShuo Chen } 157cd139dc7SShuo Chen} 158cd139dc7SShuo Chen 159cd139dc7SShuo Chenvoid Thread::start() 160cd139dc7SShuo Chen{ 161cd139dc7SShuo Chen assert(!started_); 162cd139dc7SShuo Chen started_ = true; 1632b2bf878SShuo Chen 1642b2bf878SShuo Chen ThreadData* data = new ThreadData(func_, name_, tid_); 1652b2bf878SShuo Chen if (pthread_create(&pthreadId_, NULL, &startThread, data)) 1662b2bf878SShuo Chen { 1672b2bf878SShuo Chen started_ = false; 1682b2bf878SShuo Chen delete data; 1692b2bf878SShuo Chen abort(); 1702b2bf878SShuo Chen } 171cd139dc7SShuo Chen} 172cd139dc7SShuo Chen 173cd139dc7SShuo Chenvoid Thread::join() 174cd139dc7SShuo Chen{ 175cd139dc7SShuo Chen assert(started_); 1762b2bf878SShuo Chen assert(!joined_); 1772b2bf878SShuo Chen joined_ = true; 178cd139dc7SShuo Chen pthread_join(pthreadId_, NULL); 179cd139dc7SShuo Chen} 180