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下实现线程的方式是完全不一样的。于是我们先定义一个线程类。

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #ifndef _OSAPI_THREAD_H  
  2. #define _OSAPI_THREAD_H  
  3.   
  4. /* presented by 阿发你好 */  
  5. class OS_Thread  
  6. {  
  7. public:  
  8.     OS_Thread();  
  9.     virtual ~OS_Thread();  
  10.   
  11.     // 创建并启动  
  12.     virtual int Run();  
  13.   
  14.     // 等待和收回资源  
  15.     static void Join(OS_Thread* thrd);  
  16.   
  17.     // Sleep函数  
  18.     static void Msleep(int ms);  
  19.     static void Sleep(int s);  
  20.   
  21. public:  
  22.     virtual int Routine() = 0;  
  23.   
  24. private:  
  25.     void* m_Priv;  
  26. };  
  27.   
  28.   
  29. #endif  


 

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

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #include "../osapi/Thread.h"  
  2.   
  3.   
  4. class MyThread : public OS_Thread  
  5. {  
  6. public:  
  7.     int Create()  
  8.     {  
  9.         m_quitflag = false;  
  10.         run();  
  11.         return 0;  
  12.     }  
  13.       
  14.     void Destroy()  
  15.     {  
  16.         m_quitflag = true;  
  17.         Join(this);  
  18.     }  
  19.   
  20. private:  
  21.     /* 线程函数 */  
  22.     virtual int Routine()  
  23.     {  
  24.         while(!m_quitflag)  
  25.         {  
  26.             printf("helloafa!\n");  
  27.             OS_Thread::msleep(500);  
  28.         }  
  29.         return 0;  
  30.     }  
  31.       
  32. private:  
  33.     bool m_quitflag;  
  34. };  


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


 

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #ifdef _WIN32  
  2.   
  3. #include <windows.h>  
  4. #include <process.h>   
  5.   
  6. #include "Thread.h"  
  7.   
  8. struct OS_Thread_Priv  
  9. {  
  10.     HANDLE hThread;  
  11. };  
  12.   
  13. OS_Thread::OS_Thread()   
  14. : m_Priv(NULL)  
  15. {  
  16. }  
  17.   
  18. OS_Thread::~OS_Thread()  
  19. {  
  20.     if(m_Priv)  
  21.     {  
  22.         OS_Thread_Priv* priv = (OS_Thread_Priv*) m_Priv;  
  23.         delete priv;  
  24.     }  
  25. }  
  26.   
  27. static DWORD WINAPI OS_Thread_Proc_Win32_1(LPVOID param)  
  28. {  
  29.     OS_Thread* thrd = (OS_Thread*) param;  
  30.     thrd->Routine();  
  31.   
  32.     return 0;  
  33. }  
  34.   
  35. static void OS_Thread_Proc_Win32_2(void* param)  
  36. {  
  37.     OS_Thread* thrd = (OS_Thread*) param;  
  38.     thrd->Routine();  
  39. }  
  40.   
  41. static unsigned int WINAPI OS_Thread_Proc_Win32_3(void* param)  
  42. {  
  43.     OS_Thread* thrd = (OS_Thread*) param;  
  44.     thrd->Routine();  
  45.     return 0;  
  46. }  
  47.   
  48. int OS_Thread::Run()  
  49. {  
  50.     // 创建私有结构  
  51.     OS_Thread_Priv* priv = new OS_Thread_Priv;  
  52.     if(!priv) return -1;  
  53.   
  54.     m_Priv = priv;  
  55.   
  56.     // 创建线程  
  57. //  DWORD nTheadId;  
  58. //  priv->hThread = _beginthreadex(NULL, NULL, OS_Thread_Proc_Win32, this,  0, &nTheadId);  
  59. //  priv->hThread = (HANDLE) _beginthread(OS_Thread_Proc_Win32, 0, this);  
  60.     unsigned int thrdaddr ;  
  61.     priv->hThread = (HANDLE) _beginthreadex(NULL, 0, OS_Thread_Proc_Win32_3, this, 0, &thrdaddr);  
  62.     if(priv->hThread == NULL)  
  63.     {  
  64.         delete priv;  
  65.         m_Priv = NULL;  
  66.         return -1;  
  67.     }  
  68.   
  69.     return 0;  
  70. }  
  71.   
  72. void OS_Thread::Join(OS_Thread* thrd)  
  73. {  
  74.     OS_Thread_Priv* priv = (OS_Thread_Priv*) thrd->m_Priv;  
  75.     if(priv)  
  76.     {  
  77.         WaitForSingleObject(priv->hThread, INFINITE);  
  78. //      CloseHandle(priv->hThread);  
  79.         // 删除资源  
  80.         delete priv;  
  81.         thrd->m_Priv = NULL;  
  82.     }  
  83. }  
  84.   
  85. void OS_Thread::Msleep(int ms)  
  86. {  
  87.     ::Sleep(ms);  
  88. }  
  89.   
  90. void OS_Thread::Sleep(int s)  
  91. {  
  92.     ::Sleep(s * 1000);  
  93. }  
  94.   
  95. int OS_Thread::Routine()  
  96. {  
  97.     return 0;  
  98. }  
  99.   
  100. #endif  //_WIN32  


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

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #ifndef _WIN32  
  2. //#if 1  
  3. #include <pthread.h>  
  4. #include <unistd.h>  
  5. #include <time.h>  
  6. #include "Thread.h"  
  7.   
  8.   
  9. struct OS_Thread_Priv  
  10. {  
  11.     pthread_t hThread;  
  12. };  
  13.   
  14. OS_Thread::OS_Thread()   
  15. : m_Priv(NULL)  
  16. {  
  17. }  
  18.   
  19. OS_Thread::~OS_Thread()  
  20. {  
  21.     if(m_Priv)  
  22.     {  
  23.         OS_Thread_Priv* priv = (OS_Thread_Priv*) m_Priv;  
  24.         delete priv;  
  25.     }  
  26. }  
  27.   
  28. static void* OS_Thread_Proc_Linux(void* param)  
  29. {  
  30.     OS_Thread* thrd = (OS_Thread*) param;  
  31.     thrd->Routine();  
  32.     return NULL;  
  33. }  
  34.   
  35. int OS_Thread::Run()  
  36. {  
  37.     // 创建私有结构  
  38.     OS_Thread_Priv* priv = new OS_Thread_Priv;  
  39.     if(!priv) return -1;  
  40.   
  41.     m_Priv = priv;  
  42.   
  43.     // 创建线程  
  44.     if(pthread_create(&priv->hThread, NULL, OS_Thread_Proc_Linux, this) < 0)  
  45.     {  
  46.         delete priv;  
  47.         m_Priv = NULL;  
  48.         return -1;  
  49.     }  
  50.   
  51.     return 0;  
  52. }  
  53.   
  54. void OS_Thread::Join(OS_Thread* thrd)  
  55. {  
  56.     OS_Thread_Priv* priv = (OS_Thread_Priv*) thrd->m_Priv;  
  57.     if(priv)  
  58.     {  
  59.         pthread_join(priv->hThread, NULL);  
  60.   
  61.         // 删除资源  
  62.         delete priv;  
  63.         thrd->m_Priv = NULL;  
  64.     }  
  65. }  
  66.   
  67. void OS_Thread::Msleep(int ms)  
  68. {  
  69.     //::usleep(ms * 1000);  
  70.     // 好像使用nanosleep更好  
  71.   
  72.     timespec ts;  
  73.     ts.tv_sec = ms / 1000;  
  74.     ts.tv_nsec = (ms % 1000) * 1000000;  
  75.     nanosleep(&ts, NULL);  
  76. }  
  77.   
  78. void OS_Thread::Sleep(int s)  
  79. {  
  80.     ::sleep(s);  
  81. }  
  82.   
  83. int OS_Thread::Routine()  
  84. {  
  85.     return 0;  
  86. }  
  87.   
  88.   
  89.   
  90.   
  91. #endif // ! _WIN32  


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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值