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

  本节将介绍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,释放该缓冲区。

  

              

时间: 2024-10-22 10:17:52

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

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

上次提到Chromium浏览器中base公共通用库中的内存分配器allocator,其中用到了三方库tcmalloc.jemalloc:对于这两个内存分配器,个人建议,对于内存,最好是自己维护内存池:此外在windows下使用可使用其自带的内存分配方式:具体的第三方库可以参阅:http://www.360doc.com/content/13/0915/09/8363527_314549128.shtml:目前我们主要的精力尽可能在Chromium浏览器中base公共通用库的主要内容上,所以不再详

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

Google的优秀C++开源项目繁多,其中的Chromium浏览器项目可以说是很具有代表性的,此外还包括其第三开发开源库或是自己的优秀开源库,可以根据需要抽取自己感兴趣的部分.在研究.学习该项目前的时先获取到需要获取一份谷歌的Chromium源码,可参考:http://blog.csdn.net/kuerjinjin/article/details/23563059,若无法获取且打算使用VS IDE的可从此处下载:http://blog.csdn.net/kuerjinjin/article/d

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

本文将介绍debug调试相关的内容,包括调试器.性能分析.堆跟踪.跟踪事件等: alias.h:Alias函数,提供防止载微软的编译器优化某参数变量的操作,内部通过#pragma optimize("", off)与#pragma optimize("", on)来实现关闭所有的优化选项,再恢复它们到原始(或默认)的设定:事实上Alias内部未实现任何的操作. debugger.h: 1. SpawnDebuggerOnProcess:提供开始注册系统级的JIT即时

【iScroll源码学习02】分解iScroll三个核心事件点

前言 最近两天看到很多的总结性发言,我想想今年好像我的变化挺大的,是不是该晚上来水一发呢?嗯,决定了,晚上来水一发! 上周六,我们简单模拟了下iScroll的实现,周日我们开始了学习iScroll的源码,今天我们接着上次的记录学习,因为最近事情稍微有点多了 学习进度可能要放慢,而且iScroll这个库实际意义很大,不能囫囵吞枣的学习,要学到精华,并且要用于项目中的,所以初步规划是最近两周主要围绕iScroll展开 而后两个选择:① 分离iScroll代码用于项目:② 抄袭iScroll精华部分用

【iScroll源码学习03】iScroll事件机制与滚动条的实现

[iScroll源码学习03]iScroll事件机制与滚动条的实现 前言 想不到又到周末了,周末的时间要抓紧学习才行,前几天我们学习了iScroll几点基础知识: 1. [iScroll源码学习02]分解iScroll三个核心事件点 2. [iScroll源码学习01]准备阶段 3. [iScroll源码学习00]模拟iScroll 今天我们来学习其事件机制以及滚动条的实现,完了后我们iScroll就学习的差不多了,最后会抽离iScroll的精华部分组成一个阉割版iScroll 并总结下iScr

Java并发包源码学习之AQS框架(一)概述

AQS其实就是java.util.concurrent.locks.AbstractQueuedSynchronizer这个类. 阅读Java的并发包源码你会发现这个类是整个java.util.concurrent的核心之一,也可以说是阅读整个并发包源码的一个突破口. 比如读ReentrantLock的源码你会发现其核心是它的一个内部类Sync: 整个包中很多类的结构都是如此,比如Semaphore,CountDownLatch都有一个内部类Sync,而所有的Sync都是继承自AbstractQ

[tomcat7源码学习]初始化之catalina.home和catalina.base(转)

我们在代码中为了获取某个配置文件路径下的文件经常会这么写 String tomcatPath = System.getProperty("catalina.home") + "/webapps/axis2/WEB-INF/conf/"; tomcatPath = tomcatPath.replace("/", File.separator); //使用此方法是为了区分unix系统与windows, //File.separator UNIX中为/

【 js 基础 】【 源码学习 】源码设计 (持续更新)

学习源码,除了学习对一些方法的更加聪明的代码实现,同时也要学习源码的设计,把握整体的架构.(推荐对源码有一定熟悉了之后,再看这篇文章) 目录结构:第一部分:zepto 设计分析第二部分:underscore 设计分析 第一部分: zepto 设计分析zepto 是一个轻量级的 Javascript 库.相对于 jquery 来说在 size 上更加小,主要是定位于移动设备.它是非常好的学习源码的入门级 javascript 库.这里重点说一下,这个库的设计,而对于详细的源码学习大家可以 star

jQuery源码学习感想

还记得去年(2015)九月份的时候,作为一个大四的学生去参加美团霸面,结果被美团技术总监教育了一番,那次问了我很多jQuery源码的知识点,以前虽然喜欢研究框架,但水平还不足够来研究jQuery源码,那时我不明白他们为何要求那么高,现在才知道,原来没那么高,他问的都是jQuery最基本的框架架构,不过对于不知道的来说,再简单我也是不知道,那时写了一篇博文去吐槽了一下,那时候也是我自己真正激发自己的时候,那时候我说我一定要搞好自己的jQuery基础,没想到那么快就实现了,一个月的源码学习时间就结束