前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Chromium】Base库的PlatformThread

【Chromium】Base库的PlatformThread

原创
作者头像
lealc
发布2024-03-19 09:27:02
1530
发布2024-03-19 09:27:02
举报
文章被收录于专栏:Chromium学习

源码

先附上可用于学习的开源代码:Base库

喜欢可以帮忙Star一下

前言

编译:参考Base库即可

环境:Visual Studio 2022 - 17.8.3 + v143 + 10.0.22621.0 + C++17

PlatformThread

Base库的跨平台线程类,PlatformThread是一个用于跨平台线程操作的工具类或接口。

在多线程编程中,不同的操作系统提供了不同的线程管理机制和API。PlatformThread 提供了一个抽象层,使得开发者可以在不同的操作系统上使用统一的接口来创建、启动、等待和管理线程。

PlatformThread 提供了一些静态方法,例如 Create()、Start()、Join() 和 Sleep(),用于创建线程、启动线程、等待线程完成和线程休眠等操作。这些方法会根据不同的操作系统调用相应的底层线程API来执行相应的操作。

使用 PlatformThread 可以方便地进行跨平台的线程操作,而不需要直接操作底层的线程句柄或API。这样可以提高代码的可移植性和可维护性。

需要注意的是,虽然 PlatformThread 提供了跨平台的线程操作接口,但在使用时仍然需要遵循各个操作系统的线程编程规范和最佳实践,以确保线程的正确性和可靠性。

PlatformThreadRef

代码语言:C++
复制
// 用于线程检查和调试。 
// 旨在尽可能快速。 
// 这些是由 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_;
};

PlatformThreadHandle

代码语言:C++
复制
// 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_;
};

跨平台工具函数

代码语言:C++
复制
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);
}

Delegate接口

统一线程接口

代码语言:C++
复制
// 实现此接口以在后台线程上运行代码。您的 ThreadMain 方法将在新创建的线程上调用。
class BASE_EXPORT Delegate {
public:
    virtual void ThreadMain() = 0;

protected:
    virtual ~Delegate() = default;
};

Delegate提供线程运行接口,可以通过实现自定义的线程逻辑来启动跨平台线程

代码语言:C++
复制
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更多的是提供对当前线程的一些操控

代码语言:C++
复制
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 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 源码
  • 前言
  • PlatformThread
  • PlatformThreadRef
  • PlatformThreadHandle
  • 跨平台工具函数
  • Delegate接口
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档