C++跨平台技术 - 线程Thread

跨平台是什么意思呢?先了解一下平台的概念以及平台的差异。我们知道一个VC编译出来的*.exe是不能在Linux运行的,不能运行的原因可以概括为以下几个方面:

1. 文件的结构与格式

可执行程序是按定义好的格式来组织的, Microsoft 他 GNU对程序文件的定义是不一样的,如GNU使用 ELF格式定义。也就是说,当操作系统(Windows/Linux)试图把一个程序文件加载到内存里准备运行的时候,它可能会发现这个文件格式不对。

2. 依赖库

程序的最基本的运行库是C runtime,比如你调用的printf就是C库的接口,这间味着你发布的程序是依赖C的动态库的, Linux上叫libc.so

3. 指令集与大小端

最常见的指令集用Intel, ARM 指令集,如果你的程序是为Intel PC编译的,那么这个程序就不可能在ARM平台上运行。(也许它们都是运行着Linux)。但是指令集都不一样的话,怎么能够运行呢?

 

通过上面的讨论,可以发现跨平台好像是一件不能完成的任务。那么为什么我们还能经常见到跨平台这个词呢,JAVA, ACE ,QT等等,它们都是跨平台的。那么它们是怎么跨平台的呢?

 

第一种跨平台的方式:JAVA

首先说JAVA。JAVA这个东西跨平台最彻底,同时也可以说它最“不跨平台”。JAVA编译出来的class文件并不能直接在目标平台上运行,它必须由一个叫java.exe /java的程序解释执行。显然,在不同的平台上这个java解释程序是完全不一样的。最基本的,windows上的解释程序叫java.exe,linux上的叫java,是完全不的两个文件。这件事说白了就是,你写一个脚本,交给2个不同的程序去运行,运行结果一致。

 

如果对比一下,连perl, python这种脚本语言也是跨平台的。它们和JAVA“跨”的方式本质上一样。Java跨的方式更隐蔽一些,它是先把 .java文件编译成了中间指令集.class,再解释执行这个中间指令集的。

 

第二种跨平台的方式: 仿QT

我就直接说我们可以怎么跨平台吧。简单地说,就是写2个平台相关的代码,屏蔽了平台差异。在业务代码里,完全不要用平台相关的代码。

以线程为例,windows/linux下实现线程的方式是完全不一样的。于是我们先定义一个线程类。

#ifndef _OSAPI_THREAD_H
#define _OSAPI_THREAD_H

/* presented by 阿发你好 */
class OS_Thread
{
public:
	OS_Thread();
	virtual ~OS_Thread();

	// 创建并启动
	virtual int Run();

	// 等待和收回资源
	static void Join(OS_Thread* thrd);

	// Sleep函数
	static void Msleep(int ms);
	static void Sleep(int s);

public:
	virtual int Routine() = 0;

private:
	void* m_Priv;
};


#endif


 

也就是说,无论你是XXX平台还是YYY平台,总该是有线程支持的。所以麻烦你先按照上述接口实现一个线程类吧。我在业务代码里要使用线程的时候,就使用线程接口,完全不使用平台相关的接口了。

#include "../osapi/Thread.h"


class MyThread : public OS_Thread
{
public:
	int Create()
	{
		m_quitflag = false;
		run();
		return 0;
	}
	
	void Destroy()
	{
		m_quitflag = true;
		Join(this);
	}

private:
	/* 线程函数 */
	virtual int Routine()
	{
		while(!m_quitflag)
		{
		    printf("helloafa!\n");
			OS_Thread::msleep(500);
		}
		return 0;
	}
	
private:
	bool m_quitflag;
};


在Windows上,我们写一份实现Thread_Win32.cpp


 

#ifdef _WIN32

#include <windows.h>
#include <process.h> 

#include "Thread.h"

struct OS_Thread_Priv
{
	HANDLE hThread;
};

OS_Thread::OS_Thread() 
: m_Priv(NULL)
{
}

OS_Thread::~OS_Thread()
{
	if(m_Priv)
	{
		OS_Thread_Priv* priv = (OS_Thread_Priv*) m_Priv;
		delete priv;
	}
}

static DWORD WINAPI OS_Thread_Proc_Win32_1(LPVOID param)
{
	OS_Thread* thrd = (OS_Thread*) param;
	thrd->Routine();

	return 0;
}

static void OS_Thread_Proc_Win32_2(void* param)
{
	OS_Thread* thrd = (OS_Thread*) param;
	thrd->Routine();
}

static unsigned int WINAPI OS_Thread_Proc_Win32_3(void* param)
{
	OS_Thread* thrd = (OS_Thread*) param;
	thrd->Routine();
	return 0;
}

int OS_Thread::Run()
{
	// 创建私有结构
	OS_Thread_Priv* priv = new OS_Thread_Priv;
	if(!priv) return -1;

	m_Priv = priv;

	// 创建线程
// 	DWORD nTheadId;
// 	priv->hThread = _beginthreadex(NULL, NULL, OS_Thread_Proc_Win32, this,  0, &nTheadId);
// 	priv->hThread = (HANDLE) _beginthread(OS_Thread_Proc_Win32, 0, this);
	unsigned int thrdaddr ;
	priv->hThread = (HANDLE) _beginthreadex(NULL, 0, OS_Thread_Proc_Win32_3, this, 0, &thrdaddr);
	if(priv->hThread == NULL)
	{
		delete priv;
		m_Priv = NULL;
		return -1;
	}

	return 0;
}

void OS_Thread::Join(OS_Thread* thrd)
{
	OS_Thread_Priv* priv = (OS_Thread_Priv*) thrd->m_Priv;
	if(priv)
	{
		WaitForSingleObject(priv->hThread, INFINITE);
// 		CloseHandle(priv->hThread);
		// 删除资源
		delete priv;
		thrd->m_Priv = NULL;
	}
}

void OS_Thread::Msleep(int ms)
{
	::Sleep(ms);
}

void OS_Thread::Sleep(int s)
{
	::Sleep(s * 1000);
}

int OS_Thread::Routine()
{
	return 0;
}

#endif  //_WIN32


在Linux上的实现Thread_Linux.cpp (注间Thread_Linux.cpp和Thread_Win32.cpp是同时存在于你的项目里的,上面已经用#ifndef _WIN32给隔开了,不影响你的编译)

#ifndef _WIN32
//#if 1
#include <pthread.h>
#include <unistd.h>
#include <time.h>
#include "Thread.h"


struct OS_Thread_Priv
{
	pthread_t hThread;
};

OS_Thread::OS_Thread() 
: m_Priv(NULL)
{
}

OS_Thread::~OS_Thread()
{
	if(m_Priv)
	{
		OS_Thread_Priv* priv = (OS_Thread_Priv*) m_Priv;
		delete priv;
	}
}

static void* OS_Thread_Proc_Linux(void* param)
{
	OS_Thread* thrd = (OS_Thread*) param;
	thrd->Routine();
	return NULL;
}

int OS_Thread::Run()
{
	// 创建私有结构
	OS_Thread_Priv* priv = new OS_Thread_Priv;
	if(!priv) return -1;

	m_Priv = priv;

	// 创建线程
	if(pthread_create(&priv->hThread, NULL, OS_Thread_Proc_Linux, this) < 0)
	{
		delete priv;
		m_Priv = NULL;
		return -1;
	}

	return 0;
}

void OS_Thread::Join(OS_Thread* thrd)
{
	OS_Thread_Priv* priv = (OS_Thread_Priv*) thrd->m_Priv;
	if(priv)
	{
		pthread_join(priv->hThread, NULL);

		// 删除资源
		delete priv;
		thrd->m_Priv = NULL;
	}
}

void OS_Thread::Msleep(int ms)
{
	//::usleep(ms * 1000);
	// 好像使用nanosleep更好

	timespec ts;
	ts.tv_sec = ms / 1000;
	ts.tv_nsec = (ms % 1000) * 1000000;
	nanosleep(&ts, NULL);
}

void OS_Thread::Sleep(int s)
{
	::sleep(s);
}

int OS_Thread::Routine()
{
	return 0;
}




#endif // ! _WIN32



怎么样,如果觉得这种思路不错的话就点赞吧。(其实是参考QT的设计思路的)

 

 

C++跨平台技术 - 线程Thread,布布扣,bubuko.com

C++跨平台技术 - 线程Thread

上一篇:HTML5 调用手机摄像头拍照


下一篇:Java Swing打猎射击游戏编程代码下载