1.Chromium源码分析一:基础知识2.Chromium源码分析二:LifeofaPixel.pdf3.Chromium源码分析三:Chromium中用到的设计模式
4.Chromium源码分析四:RunLoop、Bind、scoped_refptr
5.Chromium源码分析五:写一个利用ipc+protobuf通信的demo在阅读代码过程中,学到的东西很多,但是仔细想想看值得记下来的却没有几个。下面是几个chromium相对具有特色的代码片段。
一、RunLoop
扒掉层层继承和实现,RunLoop相关的基本逻辑代码如下:
class TaskRunner {
public:
bool PostDelayedTask(const Location& from_here,
OnceClosure task,
base::TimeDelta delay){
if (delay > base::TimeDelta())
return false;
AutoLock auto_lock(tasks_lock_);
pending_tasks_.push(std::move(task));
return true;
}
bool ProcessTask(){
OnceClosure task;
{
AutoLock auto_lock(tasks_lock_);
if (pending_tasks_.empty())
return false;
task = std::move(pending_tasks_.front());
pending_tasks_.pop();
}
std::move(task).Run();
return true;
}
private:
base::queue<OnceClosure> pending_tasks_;
}
class Delegate {
void Run(bool application_tasks_allowed) {
while (!should_quit_) {
simple_task_runner_->ProcessTask();
PlatformThread::YieldCurrentThread();
}
}
private:
scoped_refptr<TaskRunner> simple_task_runner_ = MakeRefCounted<TaskRunner>();
}
class BASE_EXPORT RunLoop {
public:
void RunLoop::Run(){
if (!BeforeRun())
return;
delegate_->Run(application_tasks_allowed);
AfterRun();
}
private:
bool RunLoop::BeforeRun();
void RunLoop::AfterRun();
Delegate* delegate_;
}
int main() {
ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, BindOnce(&ShouldNotRunTask), TimeDelta::FromDays(1));
RunLoop main_loop;
main_loop.Run();
return 0;
}
从上述代码中看出,chromium的事件处理逻辑与其他的开源项目并无不同。都是相同的几步:
- 通过类似PostDelayedTask之类的函数,把待执行的任务入队;
- 有一个Run函数循环读取任务队列,逐个执行队列中的任务;
- 操作任务队列的时候通过加锁来保证多线程场景下的数据一致性;
二、BindOnce和Bind
auto bf2 = std::bind(&A::Func, a, std::placeholders::_1, std::placeholders::_2);
base::Bind([](base::WeakPtr<A> a) {}, weak_ptr_factory_.GetWeakPtr()));
base::BindOnce([](){}),
在Chromium中,BindOnce
和Bind
是用于绑定函数和成员函数的工具,它们与C++标准库中的std::bind
在概念上有相似之处,但也存在显著的区别,特别是在设计目的、使用场景和实现细节上。
相同点
- 功能相似:
BindOnce
、Bind
和std::bind
都允许你创建一个新的可调用对象,这个对象可以是绑定了一些参数的函数或成员函数的结果。这样做的好处是可以将函数与特定的数据或上下文关联起来,便于在不同的上下文中使用。
不同点
-
设计目的:
std::bind
:主要设计为C++标准库的一部分,旨在提供一种通用的绑定机制,可以用于各种函数和成员函数,以及支持部分参数绑定。BindOnce
和Bind
:在Chromium中,Bind
和BindOnce
是专门设计用于异步编程和回调处理的。它们更专注于在异步环境中绑定和调用函数,尤其是与线程调度、任务队列等紧密相关。
-
异步支持:
std::bind
:不直接支持异步调用或回调处理。虽然你可以使用std::bind
创建的可调用对象在异步环境中,但它本身不提供异步相关的特性。BindOnce
和Bind
:BindOnce
和Bind
在设计时考虑了异步环境,它们可以很容易地与Chromium的异步任务队列和线程池集成,使得异步回调的创建和处理更加方便。
-
参数绑定方式:
std::bind
:允许绑定函数的任意参数,甚至可以绑定多个参数,支持复杂的绑定逻辑。BindOnce
:顾名思义,它主要用于绑定那些只需要调用一次的函数。BindOnce
绑定的参数是固定的,意味着一旦创建了绑定对象,就不能再次修改绑定的参数。Bind
:在Chromium中,Bind
提供了比BindOnce
更灵活的绑定选项,允许在创建时绑定部分参数,而其余参数在调用时再传入。
-
性能和资源管理:
std::bind
:在某些实现中,std::bind
可能引入额外的开销,因为它需要在调用时动态解析绑定的参数和函数。BindOnce
和Bind
:Chromium的BindOnce
和Bind
通常在设计时考虑了性能优化,尤其是针对异步调用场景,它们通常更高效,更少的运行时开销。
-
使用场景:
std::bind
:适用于需要通用绑定机制的场景,如在算法中传递预设参数的函数。BindOnce
和Bind
:更适合用于异步编程、回调处理和线程调度等场景,尤其是在需要与Chromium的异步基础设施集成时。
综上所述,虽然std::bind
、BindOnce
和Bind
在功能上有所重叠,但它们的设计目标和使用场景各有侧重。std::bind
更偏向于通用性,而BindOnce
和Bind
则更加专注于异步编程和资源管理,特别是在Chromium这样的高性能和多线程环境中。
三、scoped_refptr
scoped_refptr类似c++11之后支持的shared_ptr,重载了一些运算符,增加了引用计数。
区别在于scoped_refptr更注重于在高并发环境下的性能和线程安全性,而std::shared_ptr则提供了一个更通用、更灵活的解决方案,适用于广泛的使用场景。
template <class T>
class scoped_refptr {
public:
typedef T element_type;
scoped_refptr() {}
scoped_refptr(T* p) : ptr_(p) {
if (ptr_)
AddRef(ptr_);
}
// Copy constructor.
scoped_refptr(const scoped_refptr<T>& r) : ptr_(r.ptr_) {
if (ptr_)
AddRef(ptr_);
}
// Copy conversion constructor.
template <typename U,
typename = typename std::enable_if<
std::is_convertible<U*, T*>::value>::type>
scoped_refptr(const scoped_refptr<U>& r) : ptr_(r.get()) {
if (ptr_)
AddRef(ptr_);
}
// Move constructor. This is required in addition to the conversion
// constructor below in order for clang to warn about pessimizing moves.
scoped_refptr(scoped_refptr&& r) : ptr_(r.get()) { r.ptr_ = nullptr; }
// Move conversion constructor.
template <typename U,
typename = typename std::enable_if<
std::is_convertible<U*, T*>::value>::type>
scoped_refptr(scoped_refptr<U>&& r) : ptr_(r.get()) {
r.ptr_ = nullptr;
}
~scoped_refptr() {
static_assert(!base::subtle::IsRefCountPreferenceOverridden(
static_cast<T*>(nullptr), static_cast<T*>(nullptr)),
"It's unsafe to override the ref count preference."
" Please remove REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE"
" from subclasses.");
if (ptr_)
Release(ptr_);
}
T* get() const { return ptr_; }
T& operator*() const {
DCHECK(ptr_);
return *ptr_;
}
T* operator->() const {
DCHECK(ptr_);
return ptr_;
}
scoped_refptr<T>& operator=(T* p) {
// AddRef first so that self assignment should work
if (p)
AddRef(p);
T* old_ptr = ptr_;
ptr_ = p;
if (old_ptr)
Release(old_ptr);
return *this;
}
scoped_refptr<T>& operator=(const scoped_refptr<T>& r) {
return *this = r.ptr_;
}
template <typename U>
scoped_refptr<T>& operator=(const scoped_refptr<U>& r) {
return *this = r.get();
}
scoped_refptr<T>& operator=(scoped_refptr<T>&& r) {
scoped_refptr<T> tmp(std::move(r));
tmp.swap(*this);
return *this;
}
template <typename U>
scoped_refptr<T>& operator=(scoped_refptr<U>&& r) {
// We swap with a temporary variable to guarantee that |ptr_| is released
// immediately. A naive implementation which swaps |this| and |r| would
// unintentionally extend the lifetime of |ptr_| to at least the lifetime of
// |r|.
scoped_refptr<T> tmp(std::move(r));
tmp.swap(*this);
return *this;
}
void swap(scoped_refptr<T>& r) {
T* tmp = ptr_;
ptr_ = r.ptr_;
r.ptr_ = tmp;
}
explicit operator bool() const { return ptr_ != nullptr; }
template <typename U>
bool operator==(const scoped_refptr<U>& rhs) const {
return ptr_ == rhs.get();
}
template <typename U>
bool operator!=(const scoped_refptr<U>& rhs) const {
return !operator==(rhs);
}
template <typename U>
bool operator<(const scoped_refptr<U>& rhs) const {
return ptr_ < rhs.get();
}
protected:
T* ptr_ = nullptr;
private:
template <typename U>
friend scoped_refptr<U> base::AdoptRef(U*);
scoped_refptr(T* p, base::subtle::AdoptRefTag) : ptr_(p) {}
// Friend required for move constructors that set r.ptr_ to null.
template <typename U>
friend class scoped_refptr;
// Non-inline helpers to allow:
// class Opaque;
// extern template class scoped_refptr<Opaque>;
// Otherwise the compiler will complain that Opaque is an incomplete type.
static void AddRef(T* ptr);
static void Release(T* ptr);
};
// static
template <typename T>
void scoped_refptr<T>::AddRef(T* ptr) {
ptr->AddRef();
}
// static
template <typename T>
void scoped_refptr<T>::Release(T* ptr) {
ptr->Release();
}
template <typename T, typename U>
bool operator==(const scoped_refptr<T>& lhs, const U* rhs) {
return lhs.get() == rhs;
}
template <typename T, typename U>
bool operator==(const T* lhs, const scoped_refptr<U>& rhs) {
return lhs == rhs.get();
}
template <typename T>
bool operator==(const scoped_refptr<T>& lhs, std::nullptr_t null) {
return !static_cast<bool>(lhs);
}
template <typename T>
bool operator==(std::nullptr_t null, const scoped_refptr<T>& rhs) {
return !static_cast<bool>(rhs);
}
template <typename T, typename U>
bool operator!=(const scoped_refptr<T>& lhs, const U* rhs) {
return !operator==(lhs, rhs);
}
template <typename T, typename U>
bool operator!=(const T* lhs, const scoped_refptr<U>& rhs) {
return !operator==(lhs, rhs);
}
template <typename T>
bool operator!=(const scoped_refptr<T>& lhs, std::nullptr_t null) {
return !operator==(lhs, null);
}
template <typename T>
bool operator!=(std::nullptr_t null, const scoped_refptr<T>& rhs) {
return !operator==(null, rhs);
}
template <typename T>
std::ostream& operator<<(std::ostream& out, const scoped_refptr<T>& p) {
return out << p.get();
}
template <typename T>
void swap(scoped_refptr<T>& lhs, scoped_refptr<T>& rhs) {
lhs.swap(rhs);
}
转载请注明来源:https://www.cnblogs.com/bugutian/
合集:
chromium
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)
· AI 智能体引爆开源社区「GitHub 热点速览」