For Developers‎ > ‎Coding Style‎ > ‎

Important Abstractions and Data Structures

TaskRunner & SequencedTaskRunner & SingleThreadTaskRunner

Interfaces for posting base::Callbacks "tasks" to be run by the TaskRunner. TaskRunner makes no guarantees about execution (order, concurrency, or if it's even run at all). SequencedTaskRunner offers certain guarantees about the sequence of execution (roughly speaking FIFO, but see the header for nitty gritty details if interested) and SingleThreadTaskRunner offers the same guarantees as SequencedTaskRunner except all tasks run on the same thread. MessageLoopProxy is the canonical example of a SingleThreadTaskRunner. These interfaces are also useful for testing via dependency injection. NOTE: successfully posting to a TaskRunner does not necessarily mean the task will run.

NOTE: A very useful member function of TaskRunner is PostTaskAndReply(), which will post a task to a target TaskRunner and on completion post a "reply" task to the origin TaskRunner.

MessageLoop & MessageLoopProxy & BrowserThread & RunLoop

These are various APIs for posting a task. MessageLoop is a concrete object used by MessageLoopProxy (the most widely used task runner in Chromium code). You should almost always use MessageLoopProxy instead of MessageLoop, or if you're in chrome/ or content/, you can use BrowserThread. This is to avoid races on MessageLoop destruction, since MessageLoopProxy and BrowserThread will delete the task if the underlying MessageLoop is already destroyed. NOTE: successfully posting to a MessageLoop(Proxy) does not necessarily mean the task will run. 

 
PS: There's some debate about when to use SequencedTaskRunner vs MessageLoopProxy vs BrowserThread. Using an interface class like SequencedTaskRunner makes the code more abstract/reusable/testable. On the other hand, due to the extra layer of indirection, it makes the code less obvious. Using a concrete BrowserThread ID makes it immediately obvious which thread it's running on, although arguably you could name the SequencedTaskRunner variable appropriately to make it more clear. The current decision is to only convert code from BrowserThread to a TaskRunner subtype when necessary. MessageLoopProxy should probably always be passed around as a SingleThreadTaskRunner or a parent interface like SequencedTaskRunner.

 

base::SequencedWorkerPool & base::WorkerPool

These are the two primary worker pools in Chromium. SequencedWorkerPool is a more complicated worker pool that inherits from TaskRunner and provides ways to order tasks in a sequence (by sharing a SequenceToken) and also specifies shutdown behavior (block shutdown on task execution, do not run the task if the browser is shutting down and it hasn't started yet but if it has then block on it, or allow the task to run irrespective of browser shutdown and don't block shutdown on it). SequencedWorkerPool also provides a facility to return a SequencedTaskRunner based on a SequenceToken. The Chromium browser process will shutdown base::SequencedWorkerPool after all main browser threads (other than the main thread) have stopped. base::WorkerPool is a global object that is not shutdown on browser process shutdown, so all the tasks running on it will not be joined. It's generally unadvisable to use base::WorkerPool since tasks may have dependencies on other objects that may be in the process of being destroyed during browser shutdown.

base::Callback and base::Bind()

base::Callback is a set of internally refcounted templated callback classes with different arities and return values (including void). Note that these callbacks are copyable, but share (via refcounting) internal storage for the function pointer and the bound arguments. base::Bind() will bind arguments to a function pointer (under the hood, it copies the function pointer and all arguments into an internal refcounted storage object) and returns a base::Callback.

base::Bind() will automagically AddRef()/Release() the first argument if the function is a member function and will complain if the type is not refcounted (avoid this problem with base::WeakPtr or base::Unretained()). Also, for the function arguments, it will use a COMPILE_ASSERT to try to verify they are not raw pointers to a refcounted type (only possible with full type information, not forward declarations). Instead, use scoped_refptrs or call make_scoped_refptr() to prevent bugs. In addition, base::Bind() understands base::WeakPtr. If the function is a member function and the first argument is a base::WeakPtr to the object, base::Bind() will inject a wrapper function that only invokes the function pointer if the base::WeakPtr is non-NULL. base::Bind() also has the following helper wrappers for arguments.

  • base::Unretained() - disables the refcounting of member function receiver objects (which may not be of refcounted types) and the COMPILE_ASSERT on function arguments. Use with care, since it implies you need to make sure the lifetime of the object lasts beyond when the callback can be invoked. For the member function receiver object, it's probably better to use a base::WeakPtr instead.
  • base::Owned() - transfer ownership of a raw pointer to the returned base::Callback storage. Very useful because TaskRunners are not guaranteed to run callbacks (which may want to delete the object) on shutdown, so by making the callback take ownership, this prevents annoying shutdown leaks when the callback is not run.
  • base::Passed() - useful for passing a scoped object (scoped_ptr/ScopedVector/etc) to a callback. The primary difference between base::Owned() and base::Passed() is base::Passed() requires the function signature take the scoped type as a parameter, and thus allows for transferring ownership via .release(). NOTE: since the scope of the scoped type is the function scope, that means the base::Callback must only be called once. Otherwise, it would be a potential use after free and a definite double delete. Given the complexity of base::Passed()'s semantics in comparison to base::Owned(), you should prefer base::Owned() to base::Passed() in general.
  • base::ConstRef() - passes an argument as a const reference instead of copying it into the internal callback storage. Useful for obvious performance reasons, but generally should not be used, since it requires that the lifetime of the referent must live beyond when the callback can be invoked.
  • base::IgnoreResult() - use this with the function pointer passed to base::Bind() to ignore the result. Useful to make the callback usable with a TaskRunner which only takes Closures (callbacks with no parameters nor return values).

scoped_refptr<T> & base::RefCounted & base::RefCountedThreadSafe

Reference counting is occasionally useful but is more often a sign that someone isn't thinking carefully about ownership. Use it when ownership is truly shared (for example, multiple tabs sharing the same renderer process), not for when lifetime management is difficult to reason about.

Singleton & base::LazyInstance

They're globals, so you generally should avoid using them, as per the style guide. That said, when you use globals in Chromium code, it's often good to use one of these, and in general, prefer base::LazyInstance over Singleton. The reason to use these classes is construction is lazy (thereby preventing startup slowdown due to static initializers) and destruction order is well-defined. They are all destroyed in opposite order as construction when the AtExitManager is destroyed. In the Chromium browser process, the AtExitManager is instantiated early on in the main thread (the UI thread), so all of these objects will be destroyed on the main thread, even if constructed on a different thread. The reason to prefer base::LazyInstance over base::Singleton is base::LazyInstance reduces heap fragmentation by reserving space in the data segment and using placement new to construct the object in that memory location. NOTE: Both Singleton and base::LazyInstance provide "leaky" traits to leak the global on shutdown. This is often advisable (except potentially in library code where the code may be dynamically loaded into another process's address space or when data needs to be flushed on process shutdown) in order to not to slow down shutdown. There are valgrind suppressions for these "leaky" traits.

base::Thread & base::PlatformThread

Generally you shouldn't use these, since you should usually post tasks to an existing TaskRunner. PlatformThread is a platform-specific thread. base::Thread contains a MessageLoop running on a PlatformThread.

base::WeakPtr & base::WeakPtrFactory

Mostly thread-unsafe weak pointer that returns NULL if the referent has been destroyed. It's safe to pass across threads (and to destroy on other threads), but it should only be used on the original thread it was created on. base::WeakPtrFactory is useful for automatically canceling base::Callbacks when the referent of the base::WeakPtr gets destroyed.

FilePath

A cross-platform representation of a file path. You should generally use this instead of platform-specific representations.

ObserverList & ObserverListThreadSafe

ObserverList is a thread-unsafe object that is intended to be used as a member variable of a class. It provides a simple interface for iterating on a bunch of Observer objects and invoking a notification method.
 
ObserverListThreadSafe similar. It contains multiple ObserverLists, and observer notifications are invoked on the same PlatformThreadId that the observer was registered on, thereby allowing proxying notifications across threads and allowing the individual observers to receive notifications in a single threaded manner.

Pickle

Pickle provides a basic facility for object serialization and deserialization in binary form.

Value

Values allow for specifying recursive data classes (lists and dictionaries) containing simple values (bool/int/string/etc). These values can also be serialized to JSON and back.

LOG

This is the basic interface for logging in Chromium.

FileUtilProxy

Generally you should not do file I/O on jank-sensitive threads (BrowserThread::UI and BrowserThread::IO), so you can proxy them to another thread (such as BrowserThread::FILE) via these utilities.

TimeTimeDeltaTimeTicksTimer

Generally use TimeTicks instead of Time to keep a stable tick counter (Time may change if the user changes the computer clock).

PrefServiceExtensionPrefs

Containers for persistent state associated with a user Profile.

Important Abstractions and Data Structures的更多相关文章

  1. The Swiss Army Knife of Data Structures … in C#

    "I worked up a full implementation as well but I decided that it was too complicated to post in ...

  2. Choose Concurrency-Friendly Data Structures

    What is a high-performance data structure? To answer that question, we're used to applying normal co ...

  3. Objects and Data Structures

    Date Abstraction Hiding implementation is not just a matter of putting a layer of fucntions between ...

  4. Clean Code – Chapter 6 Objects and Data Structures

    Data Abstraction Hiding implementation Data/Object Anti-Symmetry Objects hide their data behind abst ...

  5. (转) Data structures

      Data structures A data structure is a group of data elements grouped together under one name. Thes ...

  6. CSIS 1119B/C Introduction to Data Structures and Algorithms

    CSIS 1119B/C Introduction to Data Structures and Algorithms Programming Assignment TwoDue Date: 18 A ...

  7. 20162314 《Program Design & Data Structures》Learning Summary Of The Eighth Week

    20162314 2017-2018-1 <Program Design & Data Structures>Learning Summary Of The Eighth Week ...

  8. c之指针与数组(2)Dynamic Data Structures: Malloc and Free--转载

    http://www.howstuffworks.com/c29.htm http://computer.howstuffworks.com/c.htm Dynamic Data Structures ...

  9. [Data Structures and Algorithms - 1] Introduction & Mathematics

    References: 1. Stanford University CS97SI by Jaehyun Park 2. Introduction to Algorithms 3. Kuangbin' ...

随机推荐

  1. Qt之QThread

    简述 QThread类提供了与系统无关的线程. QThread代表在程序中一个单独的线程控制.线程在run()中开始执行,默认情况下,run()通过调用exec()启动事件循环并在线程里运行一个Qt的 ...

  2. Qt之QStackedWidget

    简述 QStackedWidget继承自QFrame. QStackedWidget类提供了多页面切换的布局,一次只能看到一个界面. QStackedWidget可用于创建类似于QTabWidget提 ...

  3. Qt之图形(简笔画-绘制卡通蚂蚁)

    简述 关于简笔画的介绍很多,有动物.水果.蔬菜.交通工具等,通常会对绘制一步步进行拆分.组合.然后绘制为我们想要的结果. 下面来介绍另外的一个种类:昆虫类-卡通蚂蚁. 简述 绘制 效果 源码 绘制 效 ...

  4. hdoj Let the Balloon Rise

     /*Let the Balloon Rise Problem Description Contest time again! How excited it is to see balloons ...

  5. bzoj1051: [HAOI2006]受欢迎的牛(强联通)

    1051: [HAOI2006]受欢迎的牛 题目:传送门 题解: 今天又做一道水题... 强联通啊很明显 水个模板之后统计一下每个强联通分量中点的个数,再统计一下出度... 不难发现:缩点之后当且仅当 ...

  6. zzulioj--1778-- 和尚特烦恼4——有多少战斗力(gcd)

    1778: 和尚特烦恼4--有多少战斗力 Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 259  Solved: 123 SubmitStatusWe ...

  7. HUE搭配基础

    * HUE搭配基础 首先简单说一下Hue框架的来源:HUE=HadoopUser Experience,看这名字就知道怎么回事了吧,没错,直白来说就是Hadoop用户体验,是一个开源的Apache H ...

  8. python3.x学习笔记3(基础知识)

    1.集合集合是一个无序的,不重复的数据组合,作用如下: >>去重,把一个列表变成集合,就自动去重 >>关系测试,测试两组数据之前的交集.差集.并集等关系 2.关系运算 交集: ...

  9. 从C到OCblocks语法的声明

           在过去的一段时间,我开始从C的一些简单声明到更复杂的学习直到我开始学习了Objective-C中的blocks.我花了很长的一段时间去理解他并且认识到一旦你理解它是怎样组织的并且是怎样产 ...

  10. Oracle 流程控制语句

    分为选择语句循环语句两大类:一 选择语句1 if then ...end;set serveroutput on declare var_name1 varchar2(50):='East'; var ...