先附上可用于学习的开源代码:Base库
喜欢可以帮忙Star一下
编译:参考Base库即可
环境:Visual Studio 2022 - 17.8.3 + v143 + 10.0.22621.0 + C++17
Base库的跨平台线程类,PlatformThread是一个用于跨平台线程操作的工具类或接口。
在多线程编程中,不同的操作系统提供了不同的线程管理机制和API。PlatformThread 提供了一个抽象层,使得开发者可以在不同的操作系统上使用统一的接口来创建、启动、等待和管理线程。
PlatformThread 提供了一些静态方法,例如 Create()、Start()、Join() 和 Sleep(),用于创建线程、启动线程、等待线程完成和线程休眠等操作。这些方法会根据不同的操作系统调用相应的底层线程API来执行相应的操作。
使用 PlatformThread 可以方便地进行跨平台的线程操作,而不需要直接操作底层的线程句柄或API。这样可以提高代码的可移植性和可维护性。
需要注意的是,虽然 PlatformThread 提供了跨平台的线程操作接口,但在使用时仍然需要遵循各个操作系统的线程编程规范和最佳实践,以确保线程的正确性和可靠性。
// 用于线程检查和调试。
// 旨在尽可能快速。
// 这些是由 PlatformThread::CurrentRef() 生成的,稍后可以使用 == 操作符检查是否在同一线程上。
// 这些可以在线程之间安全地复制,但不能复制到另一个进程,因为在那里它们没有意义。
// 此外,内部标识符在线程终止后可以被重新使用,因此 PlatformThreadRef 不能可靠地用于区分新线程和旧线程。
class PlatformThreadRef {
public:
#if defined(OS_WIN)
typedef DWORD RefType;
#else // OS_POSIX
typedef pthread_t RefType;
#endif
constexpr PlatformThreadRef() : id_(0) {}
explicit constexpr PlatformThreadRef(RefType id) : id_(id) {}
bool operator==(PlatformThreadRef other) const {
return id_ == other.id_;
}
bool operator!=(PlatformThreadRef other) const { return id_ != other.id_; }
bool is_null() const {
return id_ == 0;
}
private:
RefType id_;
};
// Used to operate on threads.
class PlatformThreadHandle {
public:
#if defined(OS_WIN)
typedef void* Handle;
#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
typedef pthread_t Handle;
#endif
constexpr PlatformThreadHandle() : handle_(0) {}
explicit constexpr PlatformThreadHandle(Handle handle) : handle_(handle) {}
bool is_equal(const PlatformThreadHandle& other) const {
return handle_ == other.handle_;
}
bool is_null() const {
return !handle_;
}
Handle platform_handle() const {
return handle_;
}
private:
Handle handle_;
};
class BASE_EXPORT PlatformThread {
public:
// 实现此接口以在后台线程上运行代码。您的 ThreadMain 方法将在新创建的线程上调用。
class BASE_EXPORT Delegate {
public:
virtual void ThreadMain() = 0;
protected:
virtual ~Delegate() = default;
};
// 获取当前线程的线程ID,可用于日志记录等目的。
static PlatformThreadId CurrentId();
// 获取当前线程的线程引用,可用于快速检查是否在正确的线程上。
static PlatformThreadRef CurrentRef();
// 获取表示当前线程的句柄。在Windows上,这是一个伪句柄常量,始终表示使用它的线程,因此不应与其他线程共享,也不应用于区分当前线程和其他线程。
static PlatformThreadHandle CurrentHandle();
// 让出当前线程的执行,以便其他线程可以被调度。
static void YieldCurrentThread();
// 休眠指定的持续时间。注意:休眠持续时间可能是 base::Time 或 base::TimeTicks,具体取决于平台。如果您想在测试延迟任务时使用它,这将是不可靠的
// 相反,请使用带有 MOCK_TIME 模式的 base::test::ScopedTaskEnvironment。
static void Sleep(base::TimeDelta duration);
// 设置线程名称,可在调试器/工具中可见。这将尝试初始化当前线程的上下文,除非它是一个 WorkerThread。
static void SetName(const std::string& name);
// 获取线程名称,如果之前通过 SetName 设置过。
static const char* GetName();
// 创建一个新线程。stack_size 参数可以为 0,表示使用默认的堆栈大小。成功后,thread_handle 将被赋予新创建线程的句柄,delegate 的 ThreadMain 方法将在新创建的线程上执行。
// 注意:当你使用完线程句柄后,必须调用 Join 来释放与线程相关的系统资源。你必须确保 Delegate 对象的生命周期超过线程的生命周期。
static bool Create(size_t stack_size,
Delegate* delegate,
PlatformThreadHandle* thread_handle) {
return CreateWithPriority(stack_size, delegate, thread_handle,
ThreadPriority::NORMAL);
}
// CreateWithPriority() 和 Create() 的功能相同,只是线程的优先级基于 priority 参数进行设置。
static bool CreateWithPriority(size_t stack_size, Delegate* delegate,
PlatformThreadHandle* thread_handle,
ThreadPriority priority);
// CreateNonJoinable() 和 Create() 的功能相同,只是该线程无法进行 Join()。因此,它也不会输出 PlatformThreadHandle。
static bool CreateNonJoinable(size_t stack_size, Delegate* delegate);
// CreateNonJoinableWithPriority() 和 CreateNonJoinable() 的功能相同,只是线程的优先级基于 priority 参数进行设置。
static bool CreateNonJoinableWithPriority(size_t stack_size,
Delegate* delegate,
ThreadPriority priority);
// 通过 Create 函数创建的线程进行 Join。该函数会阻塞调用者,直到指定的线程退出。这将使 thread_handle 无效。
static void Join(PlatformThreadHandle thread_handle);
// 分离并释放线程句柄。线程不再可连接,调用此函数后,thread_handle 将无效。
static void Detach(PlatformThreadHandle thread_handle);
// 如果 SetCurrentThreadPriority() 能够将线程的优先级提高到 priority,则返回 true。
static bool CanIncreaseThreadPriority(ThreadPriority priority);
// 在运行时切换当前线程的优先级。
//
// 如果进程没有适当的权限(例如在 Linux 上的 CAP_SYS_NICE),则线程可能无法在降低优先级后再次提高优先级。
// 如果将优先级提高到 REALTIME_AUDIO,则线程可能无法再次降低优先级。
//
// 在 Mac 上,不得从主线程调用此函数,以避免性能下降(https://crbug.com/601270)。
//
// 由于出于安全考虑,不允许更改其他线程的优先级,因此此接口仅限于更改当前线程的优先级(https://crbug.com/399473)。
static void SetCurrentThreadPriority(ThreadPriority priority);
static ThreadPriority GetCurrentThreadPriority();
#if defined(OS_LINUX)
// 在运行时切换特定线程的优先级。这可用于更改不同进程中线程的优先级,如果调用进程没有适当的权限,则操作将失败。
// 在安全性方面,优先考虑使用上面的 SetCurrentThreadPriority() 函数,但在不允许沙箱进程更改优先级的平台上,此函数存在以允许非沙箱进程更改沙箱线程的优先级,以提高性能。
// 警告:不要将此函数用于主线程,因为这将更改整个线程组(即进程)的优先级。
static void SetThreadPriority(PlatformThreadId thread_id,
ThreadPriority priority);
#endif
// 返回由 Chrome 设置的默认线程堆栈大小。如果没有显式设置默认大小,则返回 0。
static size_t GetDefaultThreadStackSize();
private:
static void SetCurrentThreadPriorityImpl(ThreadPriority priority);
DISALLOW_IMPLICIT_CONSTRUCTORS(PlatformThread);
}
统一线程接口
// 实现此接口以在后台线程上运行代码。您的 ThreadMain 方法将在新创建的线程上调用。
class BASE_EXPORT Delegate {
public:
virtual void ThreadMain() = 0;
protected:
virtual ~Delegate() = default;
};
Delegate提供线程运行接口,可以通过实现自定义的线程逻辑来启动跨平台线程
class TrivialThread : public base::PlatformThread::Delegate {
public:
TrivialThread() : run_event_(base::WaitableEvent::ResetPolicy::MANUAL,
base::WaitableEvent::InitialState::NOT_SIGNALED) {
}
void ThreadMain() override {
L_TRACE(L"%s", __FUNCTIONW__);
run_event_.Signal();
}
base::WaitableEvent& run_event() { return run_event_; }
private:
base::WaitableEvent run_event_;
DISALLOW_COPY_AND_ASSIGN(TrivialThread);
};
TrivialThread thread;
base::PlatformThreadHandle handle;
base::PlatformThread::Create(0, &thread, &handle);
base::PlatformThread::Detach(handle);
thread.run_event().Wait();
注意结合base::Threed笔记
可以知道base::Thread是继承自PlatformThread::Delegate的子类
这样就可以轻松结合base::Thread的强大管理线程能力和任务执行能力以及PlatformThread提供的跨平台线程操作接口,来实现完美的线程控制体系
注意:base::Thread主要提供的是线程外对于此线程的管控能力,而PlatformThread更多的是提供对当前线程的一些操控
base::Thread t("TestPlatformThread");
t.Start();
// 让线程执行500ms
t.task_runner()->PostTask(
FROM_HERE,
base::BindOnce(&base::PlatformThread::Sleep, base::TimeDelta::FromMilliseconds(500)));
t.task_runner()->PostTask(
FROM_HERE,
base::BindOnce([]() {
L_TRACE("GetCurrentThreadPriority = [%d]", base::PlatformThread::GetCurrentThreadPriority());
base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(1));
L_TRACE("GetName = [%s]", base::PlatformThread::GetName());
}));
L_TRACE(L"%s thread wait", __FUNCTIONW__);
t.FlushForTesting();
L_TRACE(L"%s thread end", __FUNCTIONW__);
t.Stop();
L_TRACE(L"%s thread running= [%d]", __FUNCTIONW__, t.IsRunning());
谢谢各位,如果有感兴趣的模块或者代码需要攻略,也可以留言,会不定时更新。喜欢可以去github点点赞,再次感谢🙏
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。