muduo也对线程进行了封装,下面看一下实现。
Thread.h
// 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 "muduo/base/Atomic.h"
#include "muduo/base/CountDownLatch.h"
#include "muduo/base/Types.h"
#include <functional>
#include <memory>
#include <pthread.h>
namespace muduo
{
class Thread : noncopyable
{
public:
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_; //线程是否回收
pthread_t pthreadId_;//线程ID
pid_t tid_; //进程id
ThreadFunc func_;//线程回调函数
string name_; //线程名称
CountDownLatch latch_;
static AtomicInt32 numCreated_;//原子操作
};
} // namespace muduo
#endif // MUDUO_BASE_THREAD_H
Thread.cc
// 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 "muduo/base/Thread.h"
#include "muduo/base/CurrentThread.h"
#include "muduo/base/Exception.h"
#include "muduo/base/Logging.h"
#include <type_traits>
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/prctl.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <linux/unistd.h>
namespace muduo
{
namespace detail
{
pid_t gettid() //获取线程的进程ID
{
return static_cast<pid_t>(::syscall(SYS_gettid)); //真实的线程ID(不同进程中的线程ID可能相同)tid
}
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);
/*pthread_atfork(void (*prepare)(void),void (*parent)(void), void(*child)(void))
prepare在父进程fork创建子进程之前调用,这里可以获取父进程定义的所有锁;
child fork返回之前在子进程环境中调用,在这里unlock prepare获得的锁;
parent fork创建了子进程以后,但在fork返回之前在父进程的进程环境中调用的,在这里对prepare获得的锁进行解锁*/
}
};
ThreadNameInitializer init;
//C++中class和struct一样,只是权限的区别
struct ThreadData //一个中间结构用来存放线程的数据
{
typedef muduo::Thread::ThreadFunc ThreadFunc;
ThreadFunc func_;
string name_;
pid_t* tid_;
CountDownLatch* latch_;
ThreadData(ThreadFunc func,
const string& name,
pid_t* tid,
CountDownLatch* latch)
: func_(std::move(func)),
name_(name),
tid_(tid), //将tid缓存起来
latch_(latch)
{ }
void runInThread()
{
*tid_ = muduo::CurrentThread::tid();//调用tid()该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);//prctl设置线程的名字
try
{
func_();//运行线程运行函数
muduo::CurrentThread::t_threadName = "finished";
}
catch (const Exception& ex)//Exception异常
{
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)
{
ThreadData* data = static_cast<ThreadData*>(obj);
data->runInThread();
delete data;
return NULL;
}
} // namespace detail
void CurrentThread::cacheTid()
{
if (t_cachedTid == 0)
{
t_cachedTid = detail::gettid();
t_tidStringLength = snprintf(t_tidString, sizeof t_tidString, "%5d ", t_cachedTid);
}
}
bool CurrentThread::isMainThread()
{
return tid() == ::getpid();//通过线程的pid和进程的pid做比较如果相同说明是主线程
}
void CurrentThread::sleepUsec(int64_t usec)
{
struct timespec ts = { 0, 0 };
ts.tv_sec = static_cast<time_t>(usec / Timestamp::kMicroSecondsPerSecond);
ts.tv_nsec = static_cast<long>(usec % Timestamp::kMicroSecondsPerSecond * 1000);
::nanosleep(&ts, NULL);
}
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_)
detail::ThreadData* data = new detail::ThreadData(func_, name_, &tid_, &latch_);
if (pthread_create(&pthreadId_, NULL, &detail::startThread, data))//pthread_create成功返回0
{
started_ = false;
delete data; // or no delete?
LOG_SYSFATAL << "Failed in pthread_create";
}
else
{
//如果线程创建成功,主线程阻塞在这里,等待子线程执行threadFunc之前被唤醒
latch_.wait();
assert(tid_ > 0);
}
}
int Thread::join()
{
assert(started_);
assert(!joined_);
joined_ = true;
return pthread_join(pthreadId_, NULL);
}
} // namespace muduo