C++ 实现跨平台线程

1.不同平台线程的使用

1.1 windows平台线程示例
#include <windows.h>
#include <process.h>
#include <iostream>

// 线程函数,参数和返回值必须符合要求
DWORD WINAPI print_hello(LPVOID p)
{
    std::cout << "hello\n" << std::endl;
    return 0;
}

DWORD WINAPI print_world(LPVOID p)
{
    std::cout << "world\n" << std::endl;
    return 0;
}

int main() {
    HANDLE hThread1, hThread2;
    unsigned threadId1, threadId2;

    hThread1 = CreateThread(nullptr, 0, print_hello, nullptr, 0, nullptr);
    if (hThread1 == nullptr) {
        std::cerr << "线程创建失败" << std::endl;
        return 1;
    }

    hThread2 = CreateThread(nullptr, 0, print_world, nullptr, 0, nullptr);
    if (hThread2 == nullptr) {
        std::cerr << "线程创建失败" << std::endl;
        return 1;
    }

    // 等待线程结束
    WaitForSingleObject(hThread1, INFINITE);
    WaitForSingleObject(hThread2, INFINITE);

    // 关闭线程句柄
    CloseHandle(hThread1);
    CloseHandle(hThread2);

    return 0;
}
1.2 linux平台线程示例
//pthread创建线程
#include <pthread.h>
#include <iostream>
using namespace std;

void* print_hello(void* arg)
{
    cout << "hello" << endl;
}

void* print_world(void* arg)
{
    cout << "world" << endl;
}


int main()
{
    cout << "start" << endl;

    pthread_t t1;
    pthread_t t2;

    pthread_create(&t1, NULL, print_hello, NULL);
    pthread_create(&t2, NULL, print_world, NULL);

    pthread_join(t1, nullptr);
    //pthread_join(t2, nullptr);
    pthread_detach(t2);


    //cout << "end" << endl;

    return 0;
}

2.C++11线程库的使用

#include <thread>
#include <iostream>
using namespace std;

void print_hello()
{   
  cout << "hello" << endl;
}

void print_chenglin()
{
  cout << "chenglin" << endl;
}

int main()
{
  cout << "test start" << endl;

  cout << "main thread id:" << this_thread::get_id() << endl;
	
  thread t1(print_hello);
  cout << "hello thread id:" << t1.get_id() << endl;
  t1.detach();
	
	
  thread t2(print_chenglin);
  cout << "chenglin thread id:" << t2.get_id() << endl;
  t2.detach();
	
	//this_thread::sleep_for(chrono::seconds(5));

  if(t1.joinable())
  {
    cout << "t1 thread running ...." << endl;
    t1.join();
  }
  else
  {
    cout << "t1 thread end" << endl;
  }
    
  if(t2.joinable())
  {
    cout << "t2 thread running ...." << endl;
    t2.join();
  }
  else
  {
    cout << "t2 thread end" << endl;
  }
  
  cout << "test end" << endl;

  return 0;
}

3.定义头文件

//thread.h
#ifndef __THREAD_H__
#define __THREAD_H__

#include <iostream>
#include <functional>
#include <memory>

// 线程函数包装器(在头文件中声明,因为模板中使用)
#ifdef _WIN32
DWORD WINAPI threadFunction(LPVOID arg);
#else
void* threadFunction(void* arg);
#endif

#endif

// 用于存储线程函数和参数的结构体(在头文件中定义,因为模板中使用)
struct ThreadData {
    std::function<void()> func;
    ThreadData(std::function<void()>&& f) : func(std::move(f)) {}
};

class thread {
public:
    thread() noexcept;
    template< class F, class... Args >
    explicit thread( F&& f, Args&&... args );
    ~thread();

    void join();
    void detach();
    bool joinable() const noexcept;
    uint64_t get_id() const noexcept;

private:
    uint64_t m_threadID;
};

template< class F, class... Args >
thread::thread( F&& f, Args&&... args ) : m_threadID(0) {
    auto func = std::bind(std::forward<F>(f), std::forward<Args>(args)...);
    std::unique_ptr<struct ThreadData> data(new struct ThreadData(std::move(func)));
#ifdef _WIN32
    HANDLE hThread = CreateThread(nullptr, 0, &threadFunction, data.release(), 0, nullptr);
    if (hThread!= nullptr) {
        m_threadID = reinterpret_cast<uint64_t>(hThread);
    }
#else
    pthread_t pthread;
    pthread_create(&pthread, nullptr, &threadFunction, data.release());
    m_threadID = reinterpret_cast<uint64_t>(pthread);
#endif
}

4.定义不同平台源文件

4.1 windows平台
//thread_win.cpp
#ifdef _WIN32
#include "thread.h"
#include <windows.h>
#include <cstdint>

// 线程函数包装器定义
DWORD WINAPI threadFunction(LPVOID arg) {
    std::unique_ptr<ThreadData> data(static_cast<ThreadData*>(arg));
    data->func();
    return 0;
}

thread::thread() noexcept : m_threadID(0) {
}

thread::~thread() {
    // 如果线程还未分离且可连接,进行清理
    if (joinable()) {
        HANDLE hThread = reinterpret_cast<HANDLE>(m_threadID);
        CloseHandle(hThread);
    }
}

void thread::join() {
    if (joinable()) {
        HANDLE hThread = reinterpret_cast<HANDLE>(m_threadID);
        WaitForSingleObject(hThread, INFINITE);
        CloseHandle(hThread);
        m_threadID = 0;
    }
}

void thread::detach() {
    if (joinable()) {
        HANDLE hThread = reinterpret_cast<HANDLE>(m_threadID);
        CloseHandle(hThread);
        m_threadID = 0;
    }
}

bool thread::joinable() const noexcept {
    return m_threadID!= 0;
}

uint64_t thread::get_id() const noexcept {
    return m_threadID;
}

#endif
4.2 linux平台
//thread_posix.cpp
#ifndef _WIN32
#include "thread.h"
#include <pthread.h>
#include <cstdint>

// 线程函数包装器定义
void* threadFunction(void* arg) {
    std::unique_ptr<ThreadData> data(static_cast<ThreadData*>(arg));
    data->func();
    return nullptr;
}

thread::thread() noexcept : m_threadID(0) {
}

thread::~thread() {
    // 如果线程还未分离且可连接,进行清理
    if (joinable()) {
        pthread_t pthread = reinterpret_cast<pthread_t>(m_threadID);
        pthread_detach(pthread);
    }
}

void thread::join() {
    if (joinable()) {
        pthread_t pthread = reinterpret_cast<pthread_t>(m_threadID);
        pthread_join(pthread, nullptr);
        m_threadID = 0;
    }
}

void thread::detach() {
    if (joinable()) {
        pthread_t pthread = reinterpret_cast<pthread_t>(m_threadID);
        pthread_detach(pthread);
        m_threadID = 0;
    }
}

bool thread::joinable() const noexcept {
    return m_threadID!= 0;
}

uint64_t thread::get_id() const noexcept {
    return m_threadID;
}

#endif

5.测试程序

//main.cpp
#include "thread.h"
#include <iostream>
using namespace std;

void print_hello()
{
    cout << "hello" << endl;
}

void print_world()
{
    cout << "world" << endl;
}


int main()
{
    cout << "start" << endl;

    thread t1(print_hello);
    thread t2(print_world);

    //t1.join();
    //t2.join();
    t1.detach();
    t2.detach();


    cout << "end" << endl;

    return 0;
}

6.编译运行

//CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
set(EXECUTABLE_NAME "thread")
project(${EXECUTABLE_NAME})

set(CMAKE_CXX_STANDARD 11)


# 根据操作系统添加源文件
if(WIN32)
    add_executable(${EXECUTABLE_NAME} main.cpp thread_win.cpp)
else()
    add_executable(${EXECUTABLE_NAME} main.cpp thread_posix.cpp)
endif()

# 链接库
if(WIN32)
    # Windows下无需额外链接库
else()
    target_link_libraries(${EXECUTABLE_NAME} pthread)
endif()

编译:

mkdir build
cd build
cmake ../
make

运行输出:

chenglin@ubuntu:~/work/Thread/Project/MyThread/build$ ./thread
start
hello
end
world

7.源码链接

源码链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值