一切从0开始,小小的手机网游服务端教程,其实我只是一个初学者。【四】Thread线程类和Mutex类

先写一个nocopy类吧,这样只要继承了这个类就可以防止子类复制,赋值。(类似于boost里面的noncopyable)

至少我是不希望线程类可以复制或者赋值吧。

//nocopy.h
#ifndef __NOCOPY_H__
#define __NOCOPY_H__

class NoCopy
{
public:
	NoCopy(){}
	~NoCopy(){}
private:
	NoCopy(const NoCopy &);
	NoCopy &operator=(const NoCopy &);
};

#endif

原理:父类的赋值和复制函数没有实现并且是私有的,因此子类在复制或赋值的时候会执行父类的复制或赋值构造函数(子类没有写赋值或复制函数),这时会出现编译错误,这是一个好技巧,很多时候很有用,可以减少工作量,要防止赋值或复制的时候只要继承它即可,so easy。


接下来写线程类Thread:

//thread.h
#ifndef __THREAD_H__
#define __THREAD_H__

#include <pthread.h>
#include <unistd.h>
#include <sys/time.h>

#include "nocopy.h"
#include "runnable.h"


class Thread: public NoCopy
{
public:
	Thread()
	{
		m_started = false;
		m_pid = 0;
		m_runner = NULL;
	}
	//开始
    bool start(Runnable *runner)
    {
    	m_runner = runner;m_runner->set_thread(this);
    	return (0 == pthread_create(&m_pid, NULL, _worker, this)); 
    }
    //退出
    void join()
    {
    	if (m_started)
		{
			pthread_join(m_pid, NULL);
		}
    }
    //使线程睡眠x毫秒
    static void sleep(int ms)
    {
    	timeval tv;
    	tv.tv_sec = ms / 1000;
    	tv.tv_usec = (ms % 1000) * 1000;
    	select(0, NULL, NULL, NULL, &tv);
    }

    pthread_t get_thread_id() const { return m_pid; }

private:
	static void *_worker(void *arg)
	{
		Thread *thread = (Thread *)arg;
		thread->m_started = true;
		//TODO:这里没有做失败处理诶,lazy.
		thread->m_runner->init();
		thread->m_runner->run();
		thread->m_runner->retire();
		return NULL;
	}
private:
	bool m_started;
        pthread_t m_pid;
        Runnable *m_runner;
};
#endif

为什么start函数中传了this呢?线程执行的函数必须是全局函数,所以只能执行类中得静态函数,而通过静态函数传入this,就可以操作对象中的成员了。

看到m_runner成员,在start函数执行的时候会对其进行赋值,线程启动_worker函数并会执行m_runner的init, run, retire函数,这样在前面一节的game_app.cpp中的

m_game_thread.start(&m_game);

就会启动一个新线程m_game。


写了那么多现在编译运行看看,程序跑起来了。显示game run, 只要按ctrl+c会结束程序运行。


再写一个Mutex类吧,在消息队列中,互斥区可是必须的,嘿嘿,当然这只是个示例,所以很简单:

//mutex.h
#ifndef MUTEX_H
#define MUTEX_H

#include <pthread.h>

class Mutex
{
public:
	Mutex()
	{
		pthread_mutex_init(&m_mutex, NULL);
	}
	~Mutex()
	{
		pthread_mutex_destroy(&m_mutex);
	}
	void lock()
	{
		pthread_mutex_lock(&m_mutex);
	}
	void unlock()
	{
		pthread_mutex_unlock(&m_mutex);
	}
private:
	pthread_mutex_t m_mutex;
};

class ScopedMutex
{
public:
	ScopedMutex()
	{
		m_mutex.lock();
	}
	~ScopedMutex()
	{
		m_mutex.unlock();
	}
private:
	Mutex m_mutex;
};


#endif

这里有两个类(Mutex, ScopedMutex),Mutex类很简单,只有lock,unlock两个方法,很容易看懂吧,当然这个类不支持递归加锁,千万不要那么做!

ScopedMutex类类似于boost里面的scoped_ptr,C++里面的auto_ptr,属于自动释放锁,或许叫smart lock更合适,在构造函数的时候上锁,析构的时候解锁,这样就可以不用再释放了,很方便,减少出错。

好了,暂时写到这里吧,下次写消息队列吧,这些都要用到就先写写了。


郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。