Chromium源码—base基础库说明

本文介绍了Chromium基础库,重点讲解了容器类型,包括STL容器和Chromium特有的LinkedList、MRUCache。此外,还阐述了智能指针的使用,如scoped_ptr、ScopedVector、WeakPtr和scoped_refptr,以及它们在多线程环境下的应用和选择建议。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Chromium 基础库概览

Chromium 基础库包括的内容十分繁杂,我把其中的主要部分大致分为以下几类:

1. 容器类型
Chromium 的代码主要使用 STL 容器类型,比如 std::vector,std::list,另外 GCC 和 MSVC 提供的 STL 扩展容器类型 hash_map 和 hash_set 也在 Chromium 中使用,不过统一放在 base 名字空间里面,通过 base::hash_map,base_hash_set 使用。

在 STL 外,Chromium 基础库还提供了一些额外的容器类型比如 base::LinkedList,base::MRUCache 等。

容器类型代码位于 containers 子目录下。

2. 智能指针
Chromium 提供了一篇官方的文档 Smart Pointer Guidelines讲解了在 Chromium 里面常见的几种智能指针,最常见的包括 base::scoped_ptr,base::ScopedVector,base::WeakPtr 和 base::scoped_refptr。

智能指针代码位于 memory 子目录下。

3. 回调函数
Chromium 基础库提供了 base::Bind 机制,可以将全局函数和成员函数,跟它的调用上下文绑定在一起,构成一个回调函数对象。这个回调函数对象可以被传递,被保存,被当做消息发送到线程的消息循环里面,最后我们可以通过这个回调函数对象的 Run 方法调用跟它关联的函数。

回调函数代码位于基础库的根目录下。

4. 线程相关
Chromium 基础库提供了大量跟线程相关的设施,包括平台线程的封装类型 base::Thread,线程本地存储 base::ThreadLocalPointer,消息循环 base::MessageLoop,线程同步设施 base::Lock,base::WaitableEvent 等等,还有原子操作和内存屏障的支持。

线程相关的代码位于 threading,message_loop,synchronization 子目录下,原子操作和内存屏障位于根目录的 atomicops.h。

5. 字符串处理
Chromium 使用 std::string 作为字串容器,官方文档 Chromium String usage 提供了在 Chromium 里面字串使用的一些说明。另外 strings 子目录下提供了一些针对字串的辅助操作设施。

6. 文件操作
Chromium 基础库的 base::File 提供了文件相关的操作,相关的代码位于根目录和 files 子目录下;

7. 计时器
Chromium 基础库的 base::Timer 提供了计时器相关的操作,相关的代码位于 timer 子目录下;

8. 日志和调试
Chromium 基础库提供了通用的日志输出和各种调试辅助等机制,相关的代码位于根目录, debug 和 profile 子目录下;

9. 系统监控
包括系统状态监控,电池状态监控和内存监控,分别位于 system_monitor,power_monitor,和 memory 子目录下;

10. Android 相关
基础库的 android 子目录下是 Android 平台相关的代码,除了包括其它基础类型的 Android 适配代码外,还有一些 Android 平台特有的类型,像一些用于 JNI 支持的辅助类型。

11. 工具类型
基础库还包括的一些设施有进程,内存分配器,国际化支持,随机数生成,Base64编码,Sha1编码等等,还有一些难以归类的工具类型。


基础库详解
一、容器类型

LinkedList

base::LinkedList 是 std::list 的一个替代品,优点是当你拥有一个节点对象时,要删除这个节点只需要 O(1) 的复杂度,并且插入节点不需要新增分配内存。能够做到这一点是因为 LinkedList 要求节点类型必须以 LinkNode 作为基类,而 LinkNode 本身已经包含了指向前/后节点的指针。下面的代码演示了 LinkedList 的常见用法:

class MyNodeType : public LinkNode<MyNodeType> {
    ...
};

LinkedList<MyNodeType> list;

LinkNode<MyNodeType>* n1 = ...;
LinkNode<MyNodeType>* n2 = ...;
LinkNode<MyNodeType>* n3 = ...;

list.Append(n1);
list.Append(n3);
n2->InsertBefore(n3);

for (LinkNode<MyNodeType>* node = list.head();
    node != list.end();
    node = node->next()) {
    MyNodeType* value = node->value();
    ...
}

MRU 是 most recently used 的缩写,MRUCache 提供了一个类似 Map 的容器类型,主要的区别是可以设定容器的最大容纳个数,如果超过则自动移除最久不被使用的那个对象。

MRUCache 实际上还存在几种不同的变种:

  1. MRUCache 是最常用的,它假设自身不拥有对象,当移除对象时不执行删除操作;
  2. OwningMRUCache 假设自己拥有对象,并要求存储对象是使用指针类型,在移除对象时会执行删除操作;
  3. HashingMRUCache 跟 MRUCache 的区别是,它内部使用 base::hash_map 而不是 std::map 存储对象,所以也要求键值对象支持 hash 操作;
二、智能指针

按照官方文档的说明,什么时候我们应该使用什么类型的智能指针:

拥有对象的时候
使用 scoped_ptr 或者 ScopedVector,它们可以使用来管理所拥有的非引用计数的堆分配对象。

不拥有对象的时候
使用 raw pointer 或者 WeakPtr。如果其它代码拥有对象,但是你需要知道这个对象是否已经被销毁,就使用 WeakPtr,当所关联的对象被销毁的时候 WeakPtr 会自动被置空。你可以通过 WeakPtr.get 方法获得关联对象的指针,如果返回值为空则说明对象已经被销毁。

使用引用计数对象的时候
使用 scoped_refptr,不过 Chromium 不鼓励使用引用计数对象,特别是在多线程场景下,引用计数对象会使对象的拥有权难以确定和对象销毁的顺序和时机难以确定。

scoped_ptr

base::scoped_ptr 是 Chromium 里面最常用的智能指针,一些常见的用法:

// We put a pointer into a smart pointer at construction time.
scoped_ptr<base::Value> value(base::JSONReader::Read(data));
scoped_ptr<Foo> foo_ptr(new Foo(...));
// ...Or by using reset().
scoped_ptr<Bar> bar_ptr;  // Like "Bar* bar_ptr = NULL;".
bar_ptr.reset(new Bar(...));  // Now |bar_ptr| is non-NULL and owns the object.
// We can test the smart pointer directly or use get() to see the raw pointer underneath.
if (!value)
  return false;
Foo* raw_ptr = foo_ptr.get();
// We can call through the smart pointer as if it were a pointer.
DictionaryValue* dict = NULL;
if (!value->GetAsDictionary(&dict))
  return false;

当 scoped_ptr 作为函数参数使用时,这意味着函数的代码会获得参数对象的所有权,函数的调用者如果不是使用一个临时的 scoped_ptr 的话,它需要使用 Pass() 方法来放弃自己的 scoped_ptr 对对象的所有权,例程如下:

// Foo() takes ownership of |bar|.
void Foo(scoped_ptr<Bar> bar);
...
scoped_ptr<Bar> bar_ptr(new Bar());
Foo(bar_ptr.Pass());              // Pass() makes |bar_ptr| NULL.
Foo(scoped_ptr<Bar>(new Bar()));  // No need to use Pass() on temporaries.

如果函数返回一个 scoped_ptr,这意味着函数的调用者获得返回对象的所有权,例程如下:

// Foo takes ownership of |bar|, and the caller takes ownership of the returned
// object.
scoped_ptr<Bar> Foo(scoped_ptr<Bar> bar) {
  if (cond) {
    return bar.Pass();                 // Transfers ownership of |bar| back to
                                       // the caller.
  }
  return scoped_ptr<Bar>(new Bar()));  // No Pass() necessary on temporaries.
  // Note that on this codepath, |bar| gets deleted here.
}

最后需要注意的是不应该在函数的参数和返回值中使用 scoped_ptr 的指针或者引用形式(scoped_ptr<>* scoped_ptr<>&),它会模糊所有权的转移,使最终谁拥有对象的所有权难以理解。

ScopedVector

在 STL 容器里面存储 scoped_ptr, 类似 std::vector

std::vector<scoped_ptr<T> > vec;
...
// 对象的所有权会从 vec 转移到 scoped_ptr p,并随着 p 被销毁而销毁!!!
scoped_ptr<T> p = vec[0];

因为上述代码的危险性,所以 Chromium 不支持通过 STL 容器存储 scoped_ptr,它提供了 base::ScopedVector 来满足大部分这种需求,ScopedVector 拥有存储在它内部的对象,并在移除对象的时候负责销毁对象,如果 ScopedVector 本身被销毁,它会销毁它所存储的所有对象。因为 ScopedVector 内部存储的是 raw pointer,就不存在像 std::vector

base::ScopedVector<T> vec;
...
// 通过 raw pointer p 使用对象,不会有所有权的转移
T* p = vec[0];

如果需要在其它 STL 容器里面使用智能指针,希望在容器被销毁或者移除元素时自动销毁容器存储的对象,可以考虑使用 linked_ptr。

WeakPtr

base::WeakPtr 是所谓的弱指针,Chromium 鼓励更多使用 WeakPtr 而不是滥用需要引用计数的 scoped_refptr,因为 WeakPtr 明确不会拥有对象的所有权,也不会影响对象的销毁顺序。

base::WeakPtr 需要通过 base::WeakPtrFactory 创建,一般情况下它们使用的方式是这样的:

 class Controller {
   public:
    void SpawnWorker() { Worker::StartNew(weak_factory_.GetWeakPtr()); }
    void WorkComplete(const Result& result) { ... }
   private:
    // Member variables should appear before the WeakPtrFactory, to ensure
    // that any WeakPtrs to Controller are invalidated before its members
    // variable's destructors are executed, rendering them invalid.
    WeakPtrFactory<Controller> weak_factory_;
  };
  class Worker {
   public:
    static void StartNew(const WeakPtr<Controller>& controller) {
      Worker* worker = new Worker(controller);
      // Kick off asynchronous processing...
    }
   private:
    Worker(const WeakPtr<Controller>& controller)
        : controller_(controller) {}
    void DidCompleteAsynchronousProcessing(const Result& result) {
      if (controller_)
        controller_->WorkComplete(result);
    }
    WeakPtr<Controller> controller_;
  };

1.需要支持 WeakPtr 的类型 Controller 拥有一个 WeakPtrFactory 的成员变量,外部获取的 WeakPtr 都是通过这个 WeakPtrFactory 创建的;
2.当 Controller 对象被销毁时,它的 WeakPtrFactory 成员变量也会同时被销毁,WeakPtrFactory 被销毁的同时会将所有通

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值