码迷,mamicode.com
首页 > 其他好文 > 详细

Google之Chromium浏览器源码学习——base公共通用库(三)

时间:2015-09-09 22:37:31      阅读:317      评论:0      收藏:0      [点我收藏+]

标签:

  本节将介绍base公共通用库中的containers,其包含堆栈、列表、集合、以及Most Recently Used cache(最近使用缓存模板)。

  linked_list.h:一个简单的列表类型,通过模板实现,内部采用双链表的形式,有区别于c++标准模板库的std::list<T*>,它的使用方式为:base::LinkedList<T>;

  相对std::list<T*>,其优点有:

  1. 删除一个元素,操作复杂度为O(1),而std::list<T*>为O(n),因其内部需要获取一个T*的元素的迭代器;

  2. 插入一个元素不需要堆分配器。

  该模板链表其内置节点:base::LinkNode<T>;链表:base::LinkedList<T>

  节点示例:

  class MyNodeType : public base::LinkNode<MyNodeType>

  {

  };

  创建链表实例示例:LinkedList<MyNodeType> list;

  具体使用示例:

 1 class Node : public LinkNode<Node> 
 2 {
 3  public:
 4 
 5   explicit Node(int id) : id_(id) {}
 6 
 7   int id() const { return id_; }
 8 
 9  private:
10 
11   int id_;
12 };

  

 1 LinkedList<Node> list;
 2 Node n1(1);
 3 Node n2(2);
 4 Node n3(3);
 5 Node n4(4);
 6 Node n5(5);
 7 list.Append(&n1);
 8 list.Append(&n2);
 9 list.Append(&n3);
10 list.Append(&n4);
11 list.Append(&n5);
12 
13 n3.RemoveFromList();
14 
15 list.Append(&n3);
16 n3.InsertBefore(&n2);
17 n4.InsertAfter(&n1);
18 
19 for (const LinkNode<Node>* node = list.head(); node != list.end(); node = node->next() )
20  {
21        printf("id = %d," ,node->value()->id() );
22   }
23 
24 for (const LinkNode<Node>* node = list.tail(); node != list.end(); node = node->previous() )
25  {
26        printf("id = %d," ,node->value()->id() );
27   }

  以上代码包含,节点自定义类型、链表对象定义、创建,节点追加、节点移除、节点再追加、节点插入、移动、前向遍历、后向遍历;
  执行到第12行时,链表内容为:1,2,3,4,5;执行13行后:1,2,4,5;执行15行后:1,2,4,5,3;执行16行后:1,3,2,4,5(暂不执行该行);执行17行后:1,4,3,2,5;

  前向遍历:id = 1,id = 4,id = 3,id = 2,id = 5;后向遍历:id = 5,id = 2,id = 3,id = 4,id = 1.;

  似乎实际上与预计结果不一致,请注意:第15行、16行其实会引入BUG,导致遍历产生无限循环,使用时避免出现相同元素地址被写入链表的情况;

  总结链表:

  节点LinkNode<T>含LinkNode<T>* previous_和LinkNode<T>* next_指针成员,分别保存指向当前元素的前一个和后一个元素地址,base::LinkedList<T>中含成员LinkNode<T> root_,为整个链表的根节点,也作为遍历中最后一个节点的指示灯;维护链表,并采用后向插值的方式追加元素至链表。

  基本上实现比较简单,相对std::list更快速且基于元素地址,但也可能因不谨慎的操作引入上面的BUG。

  stack_container.h:分配器StackAllocator,采用继承于std::allocator<T>;其内部维护一个原始申请堆缓冲区对象StackAllocator::Source,用以为分配器备份存储内容,减少再次在堆中申请或其他操作,其他采用该分配器可以共享同一存储空间;可以看出StackAllocator::Source采用base::AlignedMemory分配对齐的原始堆栈缓冲区stack_buffer_以及一个保存当前缓冲区是否被使用的标识used_stack_buffer_;

  分配器StackAllocator,内部含可重新指定类型的rebind;可共享存储缓冲区的复制构造函数;显式的构造函数;申请空间的allocate,当Source未被其他使用时,可直接分配该缓冲区,否则则直接通过std::allocator<T>::allocate为其分配,同样的deallocate,当Source为被释放的缓冲区时,直接释放(实际上只是简单的used_stack_buffer_ = false),否则认为是通过std::allocator<T>::allocate为其分配的,则通过std::allocator<T>::deallocate,释放该缓冲区。

  

 

              

Google之Chromium浏览器源码学习——base公共通用库(三)

标签:

原文地址:http://www.cnblogs.com/haomiao/p/4796078.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!