1. Thread.h
Thread類是對線程的封裝,指定了線程狀態,要運行的任務(函數),名字,id等信息。調用start()->創建線程->構建ThreadData對象->傳入任務->運行。
class Thread : noncopyable
{
public:
// 指定thread運行函數類型
typedef std::function<void ()> ThreadFunc;
// 構造函數,指定運行函數與名字
explicit Thread(ThreadFunc, const string& name = string());
// FIXME: make it movable in C++11
~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:
void setDefaultName();
bool started_; // 是否已啓動
bool joined_; // 是否已調用join()函數
pthread_t pthreadId_;
pid_t tid_;
ThreadFunc func_; // 運行函數
string name_; // 名字
CountDownLatch latch_; // 倒數計時,倒計時爲0時會通知所有等待現場
static AtomicInt32 numCreated_; // 記錄創建的線程數
};
AtomicInt32 Thread::numCreated_;
Thread::Thread(ThreadFunc func, const string& n)
: started_(false),
joined_(false),
pthreadId_(0),
tid_(0),
func_(std::move(func)),
name_(n),
latch_(1)
{
setDefaultName();
}
Thread::~Thread()
{
if (started_ && !joined_)
{
pthread_detach(pthreadId_);
}
}
void Thread::setDefaultName()
{
int num = numCreated_.incrementAndGet();
if (name_.empty())
{
char buf[32];
snprintf(buf, sizeof buf, "Thread%d", num);
name_ = buf;
}
}
// 運行線程,線程
void Thread::start()
{
assert(!started_);
started_ = true;
// FIXME: move(func_)
// 創建線程,指定運行函數爲startThread,傳入ThreadData作爲參數
// 真實運行的任務傳遞到了ThreadData中
detail::ThreadData* data = new detail::ThreadData(func_, name_, &tid_, &latch_);
if (pthread_create(&pthreadId_, NULL, &detail::startThread, data))
{
started_ = false;
delete data; // or no delete?
LOG_SYSFATAL << "Failed in pthread_create";
}
else // pthread_create = 0 創建成功
{
// 等待打開門栓
latch_.wait();
assert(tid_ > 0);
}
}
int Thread::join()
{
assert(started_);
assert(!joined_);
joined_ = true;
return pthread_join(pthreadId_, NULL);
}
struct ThreadData
{
typedef muduo::Thread::ThreadFunc ThreadFunc;
ThreadFunc func_; // 要運行的任務
string name_; // 線程名字
pid_t* tid_; // 線程id
CountDownLatch* latch_; // 門栓
ThreadData(ThreadFunc func,
const string& name,
pid_t* tid,
CountDownLatch* latch)
: func_(std::move(func)),
name_(name),
tid_(tid),
latch_(latch)
{ }
// 真正線程運行的函數
void runInThread()
{
*tid_ = muduo::CurrentThread::tid();
tid_ = NULL;
latch_->countDown();
latch_ = NULL;
muduo::CurrentThread::t_threadName = name_.empty() ? "muduoThread" : name_.c_str();
::prctl(PR_SET_NAME, muduo::CurrentThread::t_threadName);
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
}
}
};
// 創建現場傳入的運行函數
void* startThread(void* obj)
{
// 接收在thread.start()中傳入的參數
ThreadData* data = static_cast<ThreadData*>(obj);
data->runInThread();
delete data;
return NULL;
}