<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title><![CDATA[(learn&think)]]></title>
  <link href="http://dreamrunner.org/atom.xml" rel="self"/>
  <link href="http://dreamrunner.org/"/>
  <updated>2017-06-12T00:13:48+08:00</updated>
  <id>http://dreamrunner.org/</id>
  <author>
    <name><![CDATA[DreamRunner]]></name>
    
  </author>
  <generator uri="http://octopress.org/">Octopress</generator>

  
  <entry>
    <title type="html"><![CDATA[C++11 Memory Model and Atomic]]></title>
    <link href="http://dreamrunner.org/blog/2017/06/11/C%2B%2B11-MemoryModel-Atomic/"/>
    <updated>2017-06-11T23:47:41+08:00</updated>
    <id>http://dreamrunner.org/blog/2017/06/11/C++11-MemoryModel-Atomic</id>
    <content type="html"><![CDATA[<div id="table-of-contents">
<h2>Table of Contents</h2>
<div id="text-table-of-contents">
<ul>
<li><a href="#sec-1">C++11 Atomic</a></li>
<li><a href="#sec-2">Memory Model and Order</a></li>
<li><a href="#sec-3">More</a></li>
</ul>
</div>
</div>

<div id="outline-container-sec-1" class="outline-2">
<h2 id="sec-1">C++11 Atomic<sup><a id="fnr.1" name="fnr.1" class="footref" href="#fn.1">1</a></sup></h2>
<div class="outline-text-2" id="text-1">
<p>
C++11 Atomic 可简单分为 4 部分:
</p>
<ol class="org-ol">
<li><code>atomic</code> 类
</li>
<li>对 <code>atomic</code> 类型的操作函数
</li>
<li><code>atomic_flag</code> 类
</li>
<li>内存序列同步相关操作
</li>
</ol>


<!-- more -->
</div>

<div id="outline-container-sec-1-1" class="outline-3">
<h3 id="sec-1-1"><code>atomic</code> 类</h3>
<div class="outline-text-3" id="text-1-1">
<p>
主要分为四种模板类:
</p>
<ol class="org-ol">
<li>基本 <code>std::atomic</code>
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #00ffff;">template</span>&lt; <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">T</span> &gt;
<span style="color: #00ffff;">struct</span> <span style="color: #98fb98;">atomic</span>;
</pre>
</div>
</li>
<li>整形(Integral)的特化
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #00ffff;">template</span>&lt;&gt;
<span style="color: #00ffff;">struct</span> <span style="color: #98fb98;">atomic</span>&lt;Integral&gt;;
</pre>
</div>
</li>
<li>bool 的特化
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #00ffff;">template</span>&lt;&gt;
<span style="color: #00ffff;">struct</span> <span style="color: #98fb98;">atomic</span>&lt;<span style="color: #98fb98;">bool</span>&gt;;
</pre>
</div>
</li>
<li>指针的特化
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #00ffff;">template</span>&lt; <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">T</span> &gt;
<span style="color: #00ffff;">struct</span> <span style="color: #98fb98;">atomic</span>&lt;<span style="color: #98fb98;">T</span>*&gt;;
</pre>
</div>
</li>
</ol>

<p>
bool 和 integral 类型:
</p>
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #7fffd4;">std</span>::atomic_bool        <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">atomic</span>&lt;<span style="color: #98fb98;">bool</span>&gt;

<span style="color: #7fffd4;">std</span>::<span style="color: #eedd82;">atomic_char</span>        <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">atomic</span>&lt;<span style="color: #98fb98;">char</span>&gt;
<span style="color: #7fffd4;">std</span>::atomic_schar       <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">atomic</span>&lt;<span style="color: #98fb98;">signed</span> <span style="color: #98fb98;">char</span>&gt;
<span style="color: #7fffd4;">std</span>::atomic_uchar       <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">atomic</span>&lt;<span style="color: #98fb98;">unsigned</span> <span style="color: #98fb98;">char</span>&gt;
<span style="color: #7fffd4;">std</span>::atomic_short       <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">atomic</span>&lt;<span style="color: #98fb98;">short</span>&gt;
<span style="color: #7fffd4;">std</span>::atomic_ushort      <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">atomic</span>&lt;<span style="color: #98fb98;">unsigned</span> <span style="color: #98fb98;">short</span>&gt;
<span style="color: #7fffd4;">std</span>::atomic_int <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">atomic</span>&lt;<span style="color: #98fb98;">int</span>&gt;
<span style="color: #7fffd4;">std</span>::atomic_uint        <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">atomic</span>&lt;<span style="color: #98fb98;">unsigned</span> <span style="color: #98fb98;">int</span>&gt;
<span style="color: #7fffd4;">std</span>::atomic_long        <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">atomic</span>&lt;<span style="color: #98fb98;">long</span>&gt;
<span style="color: #7fffd4;">std</span>::atomic_ulong       <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">atomic</span>&lt;<span style="color: #98fb98;">unsigned</span> <span style="color: #98fb98;">long</span>&gt;
<span style="color: #7fffd4;">std</span>::atomic_llong       <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">atomic</span>&lt;<span style="color: #98fb98;">long</span> <span style="color: #98fb98;">long</span>&gt;
<span style="color: #7fffd4;">std</span>::atomic_ullong      <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">atomic</span>&lt;<span style="color: #98fb98;">unsigned</span> <span style="color: #98fb98;">long</span> <span style="color: #98fb98;">long</span>&gt;
<span style="color: #7fffd4;">std</span>::atomic_char16_t    <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">atomic</span>&lt;char16_t&gt;
<span style="color: #7fffd4;">std</span>::atomic_char32_t    <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">atomic</span>&lt;char32_t&gt;
<span style="color: #7fffd4;">std</span>::atomic_wchar_t     <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">atomic</span>&lt;<span style="color: #98fb98;">wchar_t</span>&gt;
<span style="color: #7fffd4;">std</span>::atomic_int8_t      <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">atomic</span>&lt;<span style="color: #7fffd4;">std</span>::int8_t&gt;
<span style="color: #7fffd4;">std</span>::atomic_uint8_t     <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">atomic</span>&lt;<span style="color: #7fffd4;">std</span>::uint8_t&gt;
<span style="color: #7fffd4;">std</span>::atomic_int16_t     <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">atomic</span>&lt;<span style="color: #7fffd4;">std</span>::int16_t&gt;
<span style="color: #7fffd4;">std</span>::atomic_uint16_t    <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">atomic</span>&lt;<span style="color: #7fffd4;">std</span>::uint16_t&gt;
<span style="color: #7fffd4;">std</span>::atomic_int32_t     <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">atomic</span>&lt;<span style="color: #7fffd4;">std</span>::int32_t&gt;
<span style="color: #7fffd4;">std</span>::atomic_uint32_t    <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">atomic</span>&lt;<span style="color: #7fffd4;">std</span>::uint32_t&gt;
<span style="color: #7fffd4;">std</span>::atomic_int64_t     <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">atomic</span>&lt;<span style="color: #7fffd4;">std</span>::int64_t&gt;
<span style="color: #7fffd4;">std</span>::atomic_uint64_t    <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">atomic</span>&lt;<span style="color: #7fffd4;">std</span>::uint64_t&gt;
<span style="color: #7fffd4;">std</span>::atomic_int_least8_t        <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">atomic</span>&lt;<span style="color: #7fffd4;">std</span>::int_least8_t&gt;
<span style="color: #7fffd4;">std</span>::atomic_uint_least8_t       <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">atomic</span>&lt;<span style="color: #7fffd4;">std</span>::uint_least8_t&gt;
<span style="color: #7fffd4;">std</span>::atomic_int_least16_t       <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">atomic</span>&lt;<span style="color: #7fffd4;">std</span>::int_least16_t&gt;
<span style="color: #7fffd4;">std</span>::atomic_uint_least16_t      <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">atomic</span>&lt;<span style="color: #7fffd4;">std</span>::uint_least16_t&gt;
<span style="color: #7fffd4;">std</span>::atomic_int_least32_t       <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">atomic</span>&lt;<span style="color: #7fffd4;">std</span>::int_least32_t&gt;
<span style="color: #7fffd4;">std</span>::atomic_uint_least32_t      <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">atomic</span>&lt;<span style="color: #7fffd4;">std</span>::uint_least32_t&gt;
<span style="color: #7fffd4;">std</span>::atomic_int_least64_t       <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">atomic</span>&lt;<span style="color: #7fffd4;">std</span>::int_least64_t&gt;
<span style="color: #7fffd4;">std</span>::atomic_uint_least64_t      <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">atomic</span>&lt;<span style="color: #7fffd4;">std</span>::uint_least64_t&gt;
<span style="color: #7fffd4;">std</span>::atomic_int_fast8_t <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">atomic</span>&lt;<span style="color: #7fffd4;">std</span>::int_fast8_t&gt;
<span style="color: #7fffd4;">std</span>::atomic_uint_fast8_t        <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">atomic</span>&lt;<span style="color: #7fffd4;">std</span>::uint_fast8_t&gt;
<span style="color: #7fffd4;">std</span>::atomic_int_fast16_t        <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">atomic</span>&lt;<span style="color: #7fffd4;">std</span>::int_fast16_t&gt;
<span style="color: #7fffd4;">std</span>::atomic_uint_fast16_t       <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">atomic</span>&lt;<span style="color: #7fffd4;">std</span>::uint_fast16_t&gt;
<span style="color: #7fffd4;">std</span>::atomic_int_fast32_t        <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">atomic</span>&lt;<span style="color: #7fffd4;">std</span>::int_fast32_t&gt;
<span style="color: #7fffd4;">std</span>::atomic_uint_fast32_t       <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">atomic</span>&lt;<span style="color: #7fffd4;">std</span>::uint_fast32_t&gt;
<span style="color: #7fffd4;">std</span>::atomic_int_fast64_t        <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">atomic</span>&lt;<span style="color: #7fffd4;">std</span>::int_fast64_t&gt;
<span style="color: #7fffd4;">std</span>::atomic_uint_fast64_t       <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">atomic</span>&lt;<span style="color: #7fffd4;">std</span>::uint_fast64_t&gt;
<span style="color: #7fffd4;">std</span>::atomic_intptr_t    <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">atomic</span>&lt;<span style="color: #7fffd4;">std</span>::intptr_t&gt;
<span style="color: #7fffd4;">std</span>::atomic_uintptr_t   <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">atomic</span>&lt;<span style="color: #7fffd4;">std</span>::uintptr_t&gt;
<span style="color: #7fffd4;">std</span>::atomic_size_t      <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">atomic</span>&lt;<span style="color: #7fffd4;">std</span>::size_t&gt;
<span style="color: #7fffd4;">std</span>::atomic_ptrdiff_t   <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">atomic</span>&lt;<span style="color: #7fffd4;">std</span>::ptrdiff_t&gt;
<span style="color: #7fffd4;">std</span>::atomic_intmax_t    <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">atomic</span>&lt;<span style="color: #7fffd4;">std</span>::intmax_t&gt;
<span style="color: #7fffd4;">std</span>::atomic_uintmax_t   <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">atomic</span>&lt;<span style="color: #7fffd4;">std</span>::uintmax_t&gt;
</pre>
</div>

<p>
基本模板类定义:
</p>
<div class="org-src-container">

<pre class="src src-sh">template &lt; class T &gt; struct atomic {
    bool is_lock_free() const volatile;
    bool is_lock_free() const;
    void store(T, <span style="color: #eedd82;">memory_order</span> = memory_order_seq_cst) volatile;
    void store(T, <span style="color: #eedd82;">memory_order</span> = memory_order_seq_cst);
    T load(<span style="color: #eedd82;">memory_order</span> = memory_order_seq_cst) const volatile;
    T load(<span style="color: #eedd82;">memory_order</span> = memory_order_seq_cst) const;
    operator  T() const volatile;
    operator  T() const;
    T exchange(T, <span style="color: #eedd82;">memory_order</span> = memory_order_seq_cst) volatile;
    T exchange(T, <span style="color: #eedd82;">memory_order</span> = memory_order_seq_cst);
    bool compare_exchange_weak(T &amp;, T, memory_order, memory_order) volatile;
    bool compare_exchange_weak(T &amp;, T, memory_order, memory_order);
    bool compare_exchange_strong(T &amp;, T, memory_order, memory_order) volatile;
    bool compare_exchange_strong(T &amp;, T, memory_order, memory_order);
    bool compare_exchange_weak(T &amp;, T, <span style="color: #eedd82;">memory_order</span> = memory_order_seq_cst) volatile;
    bool compare_exchange_weak(T &amp;, T, <span style="color: #eedd82;">memory_order</span> = memory_order_seq_cst);
    bool compare_exchange_strong(T &amp;, T, <span style="color: #eedd82;">memory_order</span> = memory_order_seq_cst) volatile;
    bool compare_exchange_strong(T &amp;, T, <span style="color: #eedd82;">memory_order</span> = memory_order_seq_cst);
    atomic() = default;
    constexpr atomic(T);
    atomic(const atomic &amp;) = delete;
    atomic &amp; <span style="color: #eedd82;">operator</span>=(const atomic &amp;) = delete;
    atomic &amp; <span style="color: #eedd82;">operator</span>=(const atomic &amp;) <span style="color: #eedd82;">volatile</span> = delete;
    T <span style="color: #eedd82;">operator</span>=(T) volatile;
    T <span style="color: #eedd82;">operator</span>=(T);
};
</pre>
</div>

<p>
Integral 特有的函数:
</p>
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #98fb98;">integral</span> <span style="color: #87cefa;">fetch_add</span>(<span style="color: #98fb98;">integral</span>, memory_order = memory_order_seq_cst) <span style="color: #00ffff;">volatile</span>;
<span style="color: #98fb98;">integral</span> <span style="color: #87cefa;">fetch_add</span>(<span style="color: #98fb98;">integral</span>, memory_order = memory_order_seq_cst);

<span style="color: #98fb98;">integral</span> <span style="color: #87cefa;">fetch_sub</span>(<span style="color: #98fb98;">integral</span>, memory_order = memory_order_seq_cst) <span style="color: #00ffff;">volatile</span>;
<span style="color: #98fb98;">integral</span> <span style="color: #87cefa;">fetch_sub</span>(<span style="color: #98fb98;">integral</span>, memory_order = memory_order_seq_cst);

<span style="color: #98fb98;">integral</span> <span style="color: #87cefa;">fetch_and</span>(<span style="color: #98fb98;">integral</span>, memory_order = memory_order_seq_cst) <span style="color: #00ffff;">volatile</span>;
<span style="color: #98fb98;">integral</span> <span style="color: #87cefa;">fetch_and</span>(<span style="color: #98fb98;">integral</span>, memory_order = memory_order_seq_cst);

<span style="color: #98fb98;">integral</span> <span style="color: #87cefa;">fetch_or</span>(<span style="color: #98fb98;">integral</span>, memory_order = memory_order_seq_cst) <span style="color: #00ffff;">volatile</span>;
<span style="color: #98fb98;">integral</span> <span style="color: #87cefa;">fetch_or</span>(<span style="color: #98fb98;">integral</span>, memory_order = memory_order_seq_cst);

<span style="color: #98fb98;">integral</span> <span style="color: #87cefa;">fetch_xor</span>(<span style="color: #98fb98;">integral</span>, memory_order = memory_order_seq_cst) <span style="color: #00ffff;">volatile</span>;
<span style="color: #98fb98;">integral</span> <span style="color: #87cefa;">fetch_xor</span>(<span style="color: #98fb98;">integral</span>, memory_order = memory_order_seq_cst);

<span style="color: #98fb98;">integral</span> <span style="color: #00ffff;">operator</span><span style="color: #87cefa;">++</span>(<span style="color: #98fb98;">int</span>) <span style="color: #00ffff;">volatile</span>;
<span style="color: #98fb98;">integral</span> <span style="color: #00ffff;">operator</span><span style="color: #87cefa;">++</span>(<span style="color: #98fb98;">int</span>);
<span style="color: #98fb98;">integral</span> <span style="color: #00ffff;">operator</span><span style="color: #87cefa;">--</span>(<span style="color: #98fb98;">int</span>) <span style="color: #00ffff;">volatile</span>;
<span style="color: #98fb98;">integral</span> <span style="color: #00ffff;">operator</span><span style="color: #87cefa;">--</span>(<span style="color: #98fb98;">int</span>);
<span style="color: #98fb98;">integral</span> <span style="color: #00ffff;">operator</span><span style="color: #87cefa;">++</span>() <span style="color: #00ffff;">volatile</span>;
<span style="color: #98fb98;">integral</span> <span style="color: #00ffff;">operator</span><span style="color: #87cefa;">++</span>();
<span style="color: #98fb98;">integral</span> <span style="color: #00ffff;">operator</span><span style="color: #87cefa;">--</span>() <span style="color: #00ffff;">volatile</span>;
<span style="color: #98fb98;">integral</span> <span style="color: #00ffff;">operator</span><span style="color: #87cefa;">--</span>();
<span style="color: #98fb98;">integral</span> <span style="color: #00ffff;">operator</span><span style="color: #87cefa;">+=</span>(<span style="color: #98fb98;">integral</span>) <span style="color: #00ffff;">volatile</span>;
<span style="color: #98fb98;">integral</span> <span style="color: #00ffff;">operator</span><span style="color: #87cefa;">+=</span>(<span style="color: #98fb98;">integral</span>);
<span style="color: #98fb98;">integral</span> <span style="color: #00ffff;">operator</span><span style="color: #87cefa;">-=</span>(<span style="color: #98fb98;">integral</span>) <span style="color: #00ffff;">volatile</span>;
<span style="color: #98fb98;">integral</span> <span style="color: #00ffff;">operator</span><span style="color: #87cefa;">-=</span>(<span style="color: #98fb98;">integral</span>);
<span style="color: #98fb98;">integral</span> <span style="color: #00ffff;">operator</span><span style="color: #87cefa;">&amp;=</span>(<span style="color: #98fb98;">integral</span>) <span style="color: #00ffff;">volatile</span>;
<span style="color: #98fb98;">integral</span> <span style="color: #00ffff;">operator</span><span style="color: #87cefa;">&amp;=</span>(<span style="color: #98fb98;">integral</span>);
<span style="color: #98fb98;">integral</span> <span style="color: #00ffff;">operator</span><span style="color: #87cefa;">|=</span>(<span style="color: #98fb98;">integral</span>) <span style="color: #00ffff;">volatile</span>;
<span style="color: #98fb98;">integral</span> <span style="color: #00ffff;">operator</span><span style="color: #87cefa;">|=</span>(<span style="color: #98fb98;">integral</span>);
<span style="color: #98fb98;">integral</span> <span style="color: #00ffff;">operator</span><span style="color: #87cefa;">^=</span>(<span style="color: #98fb98;">integral</span>) <span style="color: #00ffff;">volatile</span>;
<span style="color: #98fb98;">integral</span> <span style="color: #00ffff;">operator</span><span style="color: #87cefa;">^=</span>(<span style="color: #98fb98;">integral</span>);
</pre>
</div>

<p>
指针特有的函数
</p>
<div class="org-src-container">

<pre class="src src-c++">T* fetch_add(ptrdiff_t, memory_order = memory_order_seq_cst) <span style="color: #00ffff;">volatile</span>;
T* fetch_add(ptrdiff_t, memory_order = memory_order_seq_cst);

T* fetch_sub(ptrdiff_t, memory_order = memory_order_seq_cst) <span style="color: #00ffff;">volatile</span>;
T* fetch_sub(ptrdiff_t, memory_order = memory_order_seq_cst);

  T* <span style="color: #00ffff;">operator</span>=(<span style="color: #98fb98;">T</span>*) <span style="color: #00ffff;">volatile</span>;
  <span style="color: #98fb98;">T</span>* <span style="color: #00ffff;">operator</span><span style="color: #87cefa;">=</span>(<span style="color: #98fb98;">T</span>*);
  <span style="color: #98fb98;">T</span>* <span style="color: #00ffff;">operator</span><span style="color: #87cefa;">++</span>(<span style="color: #98fb98;">int</span>) <span style="color: #00ffff;">volatile</span>;
  <span style="color: #98fb98;">T</span>* <span style="color: #00ffff;">operator</span><span style="color: #87cefa;">++</span>(<span style="color: #98fb98;">int</span>);
  <span style="color: #98fb98;">T</span>* <span style="color: #00ffff;">operator</span><span style="color: #87cefa;">--</span>(<span style="color: #98fb98;">int</span>) <span style="color: #00ffff;">volatile</span>;
  <span style="color: #98fb98;">T</span>* <span style="color: #00ffff;">operator</span><span style="color: #87cefa;">--</span>(<span style="color: #98fb98;">int</span>);
  <span style="color: #98fb98;">T</span>* <span style="color: #00ffff;">operator</span><span style="color: #87cefa;">++</span>() <span style="color: #00ffff;">volatile</span>;
  <span style="color: #98fb98;">T</span>* <span style="color: #00ffff;">operator</span><span style="color: #87cefa;">++</span>();
  <span style="color: #98fb98;">T</span>* <span style="color: #00ffff;">operator</span><span style="color: #87cefa;">--</span>() <span style="color: #00ffff;">volatile</span>;
  <span style="color: #98fb98;">T</span>* <span style="color: #00ffff;">operator</span><span style="color: #87cefa;">--</span>();
  <span style="color: #98fb98;">T</span>* <span style="color: #00ffff;">operator</span><span style="color: #87cefa;">+=</span>(<span style="color: #98fb98;">ptrdiff_t</span>) <span style="color: #00ffff;">volatile</span>;
  <span style="color: #98fb98;">T</span>* <span style="color: #00ffff;">operator</span><span style="color: #87cefa;">+=</span>(<span style="color: #98fb98;">ptrdiff_t</span>);
  <span style="color: #98fb98;">T</span>* <span style="color: #00ffff;">operator</span><span style="color: #87cefa;">-=</span>(<span style="color: #98fb98;">ptrdiff_t</span>) <span style="color: #00ffff;">volatile</span>;
  <span style="color: #98fb98;">T</span>* <span style="color: #00ffff;">operator</span><span style="color: #87cefa;">-=</span>(<span style="color: #98fb98;">ptrdiff_t</span>);
</pre>
</div>
</div>
</div>

<div id="outline-container-sec-1-2" class="outline-3">
<h3 id="sec-1-2"><code>atomic</code> 类型的操作函数</h3>
<div class="outline-text-3" id="text-1-2">
<p>
除了 <code>atomic</code> 类的成员函数,也提供了对其操作的函数:
</p>

<ul class="org-ul">
<li><code>atomic_is_lock_free</code>: checks if the atomic type&#8217;s operations are
lock-free
</li>
<li><code>atomic_store</code> and <code>atomic_store_explicit</code>: atomically replaces the
value of the atomic object with a non-atomic argument
</li>
<li><code>atomic_load</code> and <code>atomic_load_explicit</code>: atomically obtains the
value stored in an atomic object
</li>
<li><code>atomic_exchange</code> and <code>atomic_exchange_explicit</code>: atomically
replaces the value of the atomic object with non-atomic argument and
returns the old value of the atomic
</li>
<li><code>atomic_compare_exchange_weak</code>
<code>atomic_compare_exchange_weak_explicit</code>
<code>atomic_compare_exchange_strong</code>
<code>atomic_compare_exchange_strong_explicit</code>: atomically compares the
value of the atomic object with non-atomic argument and performs
atomic exchange if equal or atomic load if not
</li>
<li><code>atomic_fetch_add</code>
<code>atomic_fetch_add_explicit</code>: adds a non-atomic value to an atomic
object and obtains the previous value of the atomic 
</li>
<li><code>atomic_fetch_sub</code>
<code>atomic_fetch_sub_explicit</code>: subtracts a non-atomic value from an
atomic object and obtains the previous value of the atomic 
</li>
<li><code>atomic_fetch_and</code>
<code>atomic_fetch_and_explicit</code>: replaces the atomic object with the
result of logical AND with a non-atomic argument and obtains the
previous value of the atomic 
</li>
<li><code>atomic_fetch_or</code>
<code>atomic_fetch_or_explicit</code>: replaces the atomic object with the
result of logical OR with a non-atomic argument and obtains the
previous value of the atomic 
</li>
<li><code>atomic_fetch_xor</code>
<code>atomic_fetch_xor_explicit</code>: replaces the atomic object with the
result of logical XOR with a non-atomic argument and obtains the
previous value of the atomic 
</li>
</ul>
</div>
</div>

<div id="outline-container-sec-1-3" class="outline-3">
<h3 id="sec-1-3"><code>atomic_flag</code> 类</h3>
<div class="outline-text-3" id="text-1-3">
<p>
<code>atomic_flag</code> 是一种原子布尔类型，不同于 <code>std::atomic&lt;bool&gt;</code>, 不提供 load
或 store 操作,只支持两种操作， <code>test_and_set</code> 和 <code>clear</code> 。
</p>

<div class="org-src-container">

<pre class="src src-c++">atomic_flag() noexcept = <span style="color: #00ffff;">default</span>;
atomic_flag (<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">atomic_flag</span>&amp;<span style="color: #eedd82;">T</span>) = <span style="color: #00ffff;">delete</span>;
</pre>
</div>

<p>
<code>std::atomic_flag</code> 只有默认构造函数，拷贝构造函数已被禁用. 一般使用
<code>ATOMIC_FLAG_INIT</code> 初始化为 clear 状态.
</p>
</div>
</div>

<div id="outline-container-sec-1-4" class="outline-3">
<h3 id="sec-1-4">内存序列同步相关操作</h3>
<div class="outline-text-3" id="text-1-4">
<ul class="org-ul">
<li><code>memory_order</code>: defines memory ordering constraints for the given
atomic operation 
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #00ffff;">enum</span> <span style="color: #98fb98;">memory_order</span> {
    <span style="color: #eedd82;">memory_order_relaxed</span>,
    <span style="color: #eedd82;">memory_order_consume</span>,
    <span style="color: #eedd82;">memory_order_acquire</span>,
    <span style="color: #eedd82;">memory_order_release</span>,
    <span style="color: #eedd82;">memory_order_acq_rel</span>,
    <span style="color: #eedd82;">memory_order_seq_cst</span>
};
</pre>
</div>
</li>
<li><code>kill_dependency</code>: removes the specified object from the
<code>std::memory_order_consume</code> dependency tree
</li>
<li><code>atomic_thread_fence</code>: Establishes memory synchronization ordering
of non-atomic and relaxed atomic accesses, as instructed by order,
without an associated atomic operation.
</li>
<li><code>atomic_signal_fence</code>: Establishes memory synchronization ordering
of non-atomic and relaxed atomic accesses, as instructed by order,
between a thread and a signal handler executed on the same thread.
This is equivalent to std::atomic_thread_fence, except no CPU
instructions for memory ordering are issued. Only reordering of the
instructions by the compiler is suppressed as order instructs. 
</li>
</ul>
</div>
</div>
</div>

<div id="outline-container-sec-2" class="outline-2">
<h2 id="sec-2">Memory Model and Order</h2>
<div class="outline-text-2" id="text-2">
<p>
在<a href="http://dreamrunner.org/blog/2014/06/28/qian-tan-memory-reordering/">浅谈 Memory Reordering</a>中提及编译开发者和处理器制造商遵循的中心内存排序准则是: 不能改变单线程程序的行为. 从而产生了:
</p>
<ul class="org-ul">
<li>Memory ordering at compile time: 编译优化造成
</li>
<li>Memory ordering at processor time: CPU 允许乱序机器指令优化造成
</li>
</ul>

<p>
在多核多线程时代，当多线程共享某一变量时，不同线程对共享变量的读写就应该格外小心，不适当的乱序执行可能导致程序运行错误。所以必须对编译器和
CPU 作出一定的约束才能合理正确地优化你的程序，这个约束就是 <b>内存模型
(Memory Model)</b> .
</p>

<p>
或者说,程序转化成机器指令执行时并不按照之前的原始代码顺序执行,所以内存模型是程序员、编译器，CPU 之间的准则约束,遵守这一准则约束后,大家各自做优化, 从而尽可能提高程序的性能。
</p>

<p>
<a href="https://en.wikipedia.org/wiki/Memory_model_(programming)">wiki 上的 Memory model</a>给出一个比较抽象的描述: In computing, a memory
model describes the interactions of threads through memory and their
shared use of the data.
</p>

<p>
C++11 中规定了 6 种访存次序(Memory Order)，如下：
</p>
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #00ffff;">enum</span> <span style="color: #98fb98;">memory_order</span> {
    <span style="color: #eedd82;">memory_order_relaxed</span>,
    <span style="color: #eedd82;">memory_order_consume</span>,
    <span style="color: #eedd82;">memory_order_acquire</span>,
    <span style="color: #eedd82;">memory_order_release</span>,
    <span style="color: #eedd82;">memory_order_acq_rel</span>,
    <span style="color: #eedd82;">memory_order_seq_cst</span>
};
</pre>
</div>

<p>
上面 C++11 Atomic 涉及 <code>memory_order</code> 的接口, 默认值是
<code>std::memory_order_seq_cst</code> .
</p>

<p>
可以把上述 6 种访存次序(内存序)分为 3 类，顺序一致性模型
(<code>memory_order_seq_cst</code>)，Acquire-Release 模型
(<code>memory_order_consume</code>, <code>memory_order_acquire</code>,
<code>memory_order_release</code>, <code>memory_order_acq_rel</code>) 和 Relax 模型
(<code>memory_order_relaxed</code>). 
</p>

<ul class="org-ul">
<li><code>memory_order_relaxed</code>: all reorderings are okay<sup><a id="fnr.2" name="fnr.2" class="footref" href="#fn.2">2</a></sup>
</li>
<li><code>memory_order_acquire</code>: guarantees that subsequent loads are not
moved before the current load or any preceding loads.
</li>
<li><code>memory_order_release</code>: preceding stores are not moved past the
current store or any subsequent stores.
</li>
<li><code>memory_order_acq_rel</code>: combines the two previous guarantees.
</li>
<li><code>memory_order_consume</code>: potentially weaker form of
memory_order_acquire that enforces ordering of the current load
before other operations that are data-dependent on it (for instance,
when a load of a pointer is marked memory_order_consume, subsequent
operations that dereference this pointer won’t be moved before it
(yes, even that is not guaranteed on all platforms!).
</li>
<li><code>memory_order_scq_cst</code>: 是 <code>memory_order_acq_rel</code> 的加强版，除了有
<code>acq_rel</code> 语义，还保证是<a href="https://en.wikipedia.org/wiki/Sequential_consistency">sequencially-consistent</a>.
</li>
</ul>
</div>
</div>

<div id="outline-container-sec-3" class="outline-2">
<h2 id="sec-3">More</h2>
<div class="outline-text-2" id="text-3">
<ul class="org-ul">
<li><a href="https://github.com/forhappy/Cplusplus-Concurrency-In-Practice/blob/master/zh/chapter8-Memory-Model/web-resources.md">C++ 多线程与内存模型资料汇总</a>
</li>
<li>Herb Sutter 的 talk
<ul class="org-ul">
<li><a href="https://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Herb-Sutter-atomic-Weapons-1-of-2">Atomic Weapons 1</a>
</li>
<li><a href="https://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Herb-Sutter-atomic-Weapons-1-of-2">Atomic Weapon 2</a>
</li>
</ul>
</li>
<li><a href="https://bartoszmilewski.com/2008/12/01/c-atomics-and-memory-ordering/">C++ atomics and memory ordering</a>
</li>
</ul>
</div>
</div>
<div id="footnotes">
<h2 class="footnotes">Footnotes: </h2>
<div id="text-footnotes">

<div class="footdef"><sup><a id="fn.1" name="fn.1" class="footnum" href="#fnr.1">1</a></sup> <p class="footpara">
<a href="http://en.cppreference.com/w/cpp/atomic">http://en.cppreference.com/w/cpp/atomic</a>
</p></div>

<div class="footdef"><sup><a id="fn.2" name="fn.2" class="footnum" href="#fnr.2">2</a></sup> <p class="footpara">
<a href="https://bartoszmilewski.com/2008/12/01/c-atomics-and-memory-ordering/">https://bartoszmilewski.com/2008/12/01/c-atomics-and-memory-ordering/</a>
</p></div>


</div>
</div>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Make Colorful Equations With Mathjax]]></title>
    <link href="http://dreamrunner.org/blog/2014/12/15/make-colorful-equations-with-mathjax/"/>
    <updated>2014-12-15T22:18:35+08:00</updated>
    <id>http://dreamrunner.org/blog/2014/12/15/make-colorful-equations-with-mathjax</id>
    <content type="html"><![CDATA[<script type="math/tex; mode=display">
\begin{align}
\definecolor{x}{RGB}{114,0,172}
\definecolor{mean}{RGB}{45,177,93}
\definecolor{var}{RGB}{251,0,29}
\definecolor{e}{RGB}{18,110,213}

f(\color{x} x,\color{mean} \mu,\color{var} \sigma \color{black} ) =
\frac{1}{\color{var}\sigma \color{black} \sqrt{2\pi}} \color{e}
e \color{black} ^{- \frac{( {\color{x}x} - {\color{mean} \mu})^2}
{2{ \color{var} \sigma}^2}}
\end{align}
</script>

<p>其中,<font color="2DB15D"> $\mu$ </font> 是分布的均值或期望值,
而<font color="FB001D"> $\sigma$ </font> 是它的标准差, 
<font color="FB001D"> $\sigma^2$ </font>则是方差.</p>

<!-- more -->

<h2 id="mathjax-color-extension">加载 Mathjax Color extension</h2>

<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
<span class="line-number">5</span>
<span class="line-number">6</span>
<span class="line-number">7</span>
<span class="line-number">8</span>
<span class="line-number">9</span>
<span class="line-number">10</span>
<span class="line-number">11</span>
<span class="line-number">12</span>
</pre></td><td class="code"><pre><code class="diff"><span class="line"><span class="gd">--- a/head.html</span>
</span><span class="line"><span class="gi">+++ b/head.html</span>
</span><span class="line"><span class="gu">@@ -13,7 +13,8 @@</span>
</span><span class="line">     skipTags: [&#39;script&#39;, &#39;noscript&#39;, &#39;style&#39;, &#39;textarea&#39;, &#39;pre&#39;, &#39;code&#39;]
</span><span class="line">   },
</span><span class="line">   messageStyle: &quot;none&quot;,
</span><span class="line"><span class="gd">-  &quot;HTML-CSS&quot;: { preferredFont: &quot;TeX&quot;, availableFonts: [&quot;STIX&quot;,&quot;TeX&quot;] }</span>
</span><span class="line"><span class="gi">+  &quot;HTML-CSS&quot;: { preferredFont: &quot;TeX&quot;, availableFonts: [&quot;STIX&quot;,&quot;TeX&quot;] },</span>
</span><span class="line"><span class="gi">+  TeX: { extensions: [&quot;color.js&quot;] }</span>
</span><span class="line"> });
</span><span class="line"> &lt;/script&gt;
</span><span class="line"> &lt;script src=&quot;http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_HTML&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;
</span></code></pre></td></tr></table></div></figure></notextile></div>

<h2 id="section">使用</h2>

<p>使用 <code>\definecolor</code> 和 <code>\color</code> 来为公式添加颜色如下:</p>

<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
<span class="line-number">5</span>
<span class="line-number">6</span>
<span class="line-number">7</span>
<span class="line-number">8</span>
<span class="line-number">9</span>
<span class="line-number">10</span>
<span class="line-number">11</span>
</pre></td><td class="code"><pre><code class="javascript"><span class="line"><span class="err">\</span><span class="nx">begin</span><span class="p">{</span><span class="nx">align</span><span class="p">}</span>
</span><span class="line"><span class="err">\</span><span class="nx">definecolor</span><span class="p">{</span><span class="nx">x</span><span class="p">}{</span><span class="nx">RGB</span><span class="p">}{</span><span class="mi">114</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">172</span><span class="p">}</span>
</span><span class="line"><span class="err">\</span><span class="nx">definecolor</span><span class="p">{</span><span class="nx">mean</span><span class="p">}{</span><span class="nx">RGB</span><span class="p">}{</span><span class="mi">45</span><span class="p">,</span><span class="mi">177</span><span class="p">,</span><span class="mi">93</span><span class="p">}</span>
</span><span class="line"><span class="err">\</span><span class="nx">definecolor</span><span class="p">{</span><span class="kd">var</span><span class="p">}{</span><span class="nx">RGB</span><span class="p">}{</span><span class="mi">251</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">29</span><span class="p">}</span>
</span><span class="line"><span class="err">\</span><span class="nx">definecolor</span><span class="p">{</span><span class="nx">e</span><span class="p">}{</span><span class="nx">RGB</span><span class="p">}{</span><span class="mi">18</span><span class="p">,</span><span class="mi">110</span><span class="p">,</span><span class="mi">213</span><span class="p">}</span>
</span><span class="line">
</span><span class="line"><span class="nx">f</span><span class="p">(</span><span class="err">\</span><span class="nx">color</span><span class="p">{</span><span class="nx">x</span><span class="p">}</span> <span class="nx">x</span><span class="p">,</span><span class="err">\</span><span class="nx">color</span><span class="p">{</span><span class="nx">mean</span><span class="p">}</span> <span class="err">\</span><span class="nx">mu</span><span class="p">,</span><span class="err">\</span><span class="nx">color</span><span class="p">{</span><span class="kd">var</span><span class="p">}</span> <span class="err">\</span><span class="nx">sigma</span> <span class="err">\</span><span class="nx">color</span><span class="p">{</span><span class="nx">black</span><span class="p">}</span> <span class="p">)</span> <span class="o">=</span>
</span><span class="line"><span class="err">\</span><span class="nx">frac</span><span class="p">{</span><span class="mi">1</span><span class="p">}{</span><span class="err">\</span><span class="nx">color</span><span class="p">{</span><span class="kd">var</span><span class="p">}</span><span class="err">\</span><span class="nx">sigma</span> <span class="err">\</span><span class="nx">color</span><span class="p">{</span><span class="nx">black</span><span class="p">}</span> <span class="err">\</span><span class="nx">sqrt</span><span class="p">{</span><span class="mi">2</span><span class="err">\</span><span class="nx">pi</span><span class="p">}}</span> <span class="err">\</span><span class="nx">color</span><span class="p">{</span><span class="nx">e</span><span class="p">}</span>
</span><span class="line"><span class="nx">e</span> <span class="err">\</span><span class="nx">color</span><span class="p">{</span><span class="nx">black</span><span class="p">}</span> <span class="o">^</span><span class="p">{</span><span class="o">-</span> <span class="err">\</span><span class="nx">frac</span><span class="p">{(</span> <span class="p">{</span><span class="err">\</span><span class="nx">color</span><span class="p">{</span><span class="nx">x</span><span class="p">}</span><span class="nx">x</span><span class="p">}</span> <span class="o">-</span> <span class="p">{</span><span class="err">\</span><span class="nx">color</span><span class="p">{</span><span class="nx">mean</span><span class="p">}</span> <span class="err">\</span><span class="nx">mu</span><span class="p">})</span><span class="o">^</span><span class="mi">2</span><span class="p">}</span>
</span><span class="line"><span class="p">{</span><span class="mi">2</span><span class="p">{</span> <span class="err">\</span><span class="nx">color</span><span class="p">{</span><span class="kd">var</span><span class="p">}</span> <span class="err">\</span><span class="nx">sigma</span><span class="p">}</span><span class="o">^</span><span class="mi">2</span><span class="p">}}</span>
</span><span class="line"><span class="err">\</span><span class="nx">end</span><span class="p">{</span><span class="nx">align</span><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure></notextile></div>

<p>MathJax 的 <code>\definecolor</code> 不支持 <code>HTML</code> 的颜色颜色空间,所以手动在它们之间转换颜色,文字部分如下:</p>

<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
</pre></td><td class="code"><pre><code class="html"><span class="line">其中,<span class="nt">&lt;font</span> <span class="na">color=</span><span class="s">&quot;2DB15D&quot;</span><span class="nt">&gt;</span> $\mu$ <span class="nt">&lt;/font&gt;</span> 是分布的均值或期望值,
</span><span class="line">而<span class="nt">&lt;font</span> <span class="na">color=</span><span class="s">&quot;FB001D&quot;</span><span class="nt">&gt;</span> $\sigma$ <span class="nt">&lt;/font&gt;</span> 是它的标准差,
</span><span class="line"><span class="nt">&lt;font</span> <span class="na">color=</span><span class="s">&quot;FB001D&quot;</span><span class="nt">&gt;</span> $\sigma^2$ <span class="nt">&lt;/font&gt;</span>则是方差.
</span></code></pre></td></tr></table></div></figure></notextile></div>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[浅谈C++11 Multithreading Programming]]></title>
    <link href="http://dreamrunner.org/blog/2014/08/25/C11-multithreading-programming/"/>
    <updated>2014-08-25T00:00:00+08:00</updated>
    <id>http://dreamrunner.org/blog/2014/08/25/C11-multithreading-programming</id>
    <content type="html"><![CDATA[<div id="outline-container-sec-1" class="outline-2">
<h2 id="sec-1">Overview</h2>
<div class="outline-text-2" id="text-1">
<p>
上一篇<a href="http://dreamrunner.org/blog/2014/08/07/C-multithreading-programming/">浅谈 C++ Multithreading Programming</a>主要介绍时下规范好的 C++使用
Pthread 库和 Boost Thread 库实现 C++多线程编程.这里主要谈谈正在规范的 C++11
引入的 Thread 库和 Atomic 库,终于自带的 C++库能支持高效并可移植的
Multithreading 编程.分为 2 篇,这里先谈谈 C++11 的<a href="http://en.cppreference.com/w/cpp/thread">Thread 的库</a> (并包含对
<a href="http://en.cppreference.com/w/c/thread">C 的支持</a>), 后一篇谈谈
C++11 的<a href="http://en.cppreference.com/w/cpp/atomic">Atomic 操作的库</a>.
</p>

<p>
<a href="https://en.wikipedia.org/wiki/C++11">C++11</a>(之前被成为 C++0x)是编程语言 C++最新版本的标准.它由 <a href="https://en.wikipedia.org/wiki/International_Organization_for_Standardization">ISO </a>在 2011 年 8 月
12 日被批准替代<a href="https://en.wikipedia.org/wiki/C++03">C++03</a>. C++11 标准正在规范中,从<a href="https://isocpp.org/std/the-standard">ISO 页面</a> 可以知道如何获得进行中的草稿:
</p>
<ul class="org-ul">
<li><a href="https://isocpp.org/files/papers/N3690.pdf">下载最新进行的 pdf 版草稿(N3690)</a>
</li>
<li><a href="https://github.com/cplusplus/draft">从 Github 获取草稿的源文件</a>
</li>
</ul>

<p>
所以本文:
</p>
<ul class="org-ul">
<li>标准内容主要参考如上的 N3690 版本的 C++11 标准.
</li>
<li>使用的编译器是 GCC4.8,<a href="https://gcc.gnu.org/gcc-4.8/cxx0x_status.html">关于 GCC4.8 支持 C+11 的情况</a>.
</li>
<li>源代码之类主要参考<a href="http://www.cplusplus.com/reference/multithreading/">cplusplus</a> 和 <a href="http://en.cppreference.com/w/">cppreference</a>.
</li>
</ul>

<p>
更多有关 C++参考最后的<a href="#reference">其他资料</a>.
</p>

<!-- more -->
</div>
</div>

<div id="outline-container-sec-2" class="outline-2">
<h2 id="sec-2">Compile</h2>
<div class="outline-text-2" id="text-2">
<p>
GCC 编译支持 C++11,使用编译选项 <code>-std=c++11</code> 或 <code>-std=gnu++11</code>, 前者关闭
GNU 扩张支持.并加上 <code>-pthread</code> 选项.
</p>

<div class="org-src-container">

<pre class="src src-sh">g++ program.o -o program -std=c++11 -pthread
</pre>
</div>

<p>
如果漏掉 <code>-phtread</code> 选项,编译能通过,当运行出现如下错误:
</p>
<div class="org-src-container">

<pre class="src src-sh">terminate called after throwing an instance of <span style="color: #ffa07a;">'std::system_error'</span>
  what():  Enable multithreading to use std::thread: Operation not permitted
</pre>
</div>
</div>
</div>

<div id="outline-container-sec-3" class="outline-2">
<h2 id="sec-3">Threads</h2>
<div class="outline-text-2" id="text-3">
</div><div id="outline-container-sec-3-1" class="outline-3">
<h3 id="sec-3-1"><code>&lt;thread&gt;</code> 概要</h3>
<div class="outline-text-3" id="text-3-1">
<p>
头文件是 <code>&lt;thread&gt;</code>, 分为两部分: <code>thread</code> 类和在 namespace
<code>this_thread</code> 用来管理当前 thread 的函数.具体见之后的<a href="#thread_header">Header &lt;thread&gt; synopsis</a>.
</p>
</div>
</div>

<div id="outline-container-sec-3-2" class="outline-3">
<h3 id="sec-3-2"><code>thread::id</code> 类</h3>
<div class="outline-text-3" id="text-3-2">
<p>
<code>thread::id</code> 类型的对象为每个执行的线程提供唯一的标识,并为所有并不表示线程执行(默认构造的线程对象)的所有线程对象提供一个唯一的值.
</p>

<p>
<code>thread::id</code> 类没有特别的东西,主要提供方便比较或打印等运算符重载.
</p>
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #00ffff;">namespace</span> <span style="color: #7fffd4;">std</span> {
<span style="color: #00ffff;">class</span> <span style="color: #7fffd4;">thread</span>::<span style="color: #98fb98;">id</span> {
 <span style="color: #00ffff;">public</span>:
  id() noexcept;
};
<span style="color: #98fb98;">bool</span> <span style="color: #00ffff;">operator</span><span style="color: #87cefa;">==</span>(<span style="color: #7fffd4;">thread</span>::<span style="color: #98fb98;">id</span> <span style="color: #eedd82;">x</span>, <span style="color: #7fffd4;">thread</span>::<span style="color: #98fb98;">id</span> <span style="color: #eedd82;">y</span>) noexcept;
<span style="color: #98fb98;">bool</span> <span style="color: #00ffff;">operator</span><span style="color: #87cefa;">!=</span>(<span style="color: #7fffd4;">thread</span>::<span style="color: #98fb98;">id</span> <span style="color: #eedd82;">x</span>, <span style="color: #7fffd4;">thread</span>::<span style="color: #98fb98;">id</span> <span style="color: #eedd82;">y</span>) noexcept;
<span style="color: #98fb98;">bool</span> <span style="color: #00ffff;">operator</span><span style="color: #87cefa;">&lt;</span>(<span style="color: #7fffd4;">thread</span>::<span style="color: #98fb98;">id</span> <span style="color: #eedd82;">x</span>, <span style="color: #7fffd4;">thread</span>::<span style="color: #98fb98;">id</span> <span style="color: #eedd82;">y</span>) noexcept;
<span style="color: #98fb98;">bool</span> <span style="color: #00ffff;">operator</span><span style="color: #87cefa;">&lt;=</span>(<span style="color: #7fffd4;">thread</span>::<span style="color: #98fb98;">id</span> <span style="color: #eedd82;">x</span>, <span style="color: #7fffd4;">thread</span>::<span style="color: #98fb98;">id</span> <span style="color: #eedd82;">y</span>) noexcept;
<span style="color: #98fb98;">bool</span> <span style="color: #00ffff;">operator</span><span style="color: #87cefa;">&gt;</span>(<span style="color: #7fffd4;">thread</span>::<span style="color: #98fb98;">id</span> <span style="color: #eedd82;">x</span>, <span style="color: #7fffd4;">thread</span>::<span style="color: #98fb98;">id</span> <span style="color: #eedd82;">y</span>) noexcept;
<span style="color: #98fb98;">bool</span> <span style="color: #00ffff;">operator</span><span style="color: #87cefa;">&gt;=</span>(<span style="color: #7fffd4;">thread</span>::<span style="color: #98fb98;">id</span> <span style="color: #eedd82;">x</span>, <span style="color: #7fffd4;">thread</span>::<span style="color: #98fb98;">id</span> <span style="color: #eedd82;">y</span>) noexcept;
<span style="color: #00ffff;">template</span>&lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">charT</span>, <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">traits</span>&gt;
<span style="color: #98fb98;">basic_ostream</span>&lt;<span style="color: #98fb98;">charT</span>, <span style="color: #98fb98;">traits</span>&gt;&amp;
<span style="color: #00ffff;">operator</span><span style="color: #87cefa;">&lt;&lt;</span> (<span style="color: #98fb98;">basic_ostream</span>&lt;<span style="color: #98fb98;">charT</span>, <span style="color: #98fb98;">traits</span>&gt;&amp; <span style="color: #eedd82;">out</span>, <span style="color: #7fffd4;">thread</span>::<span style="color: #98fb98;">id</span> <span style="color: #eedd82;">id</span>);
<span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">Hash support</span>
<span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">T</span>&gt; <span style="color: #00ffff;">struct</span> <span style="color: #98fb98;">hash</span>;
<span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">typename</span> <span style="color: #98fb98;">T</span>&gt; &lt;&gt; <span style="color: #00ffff;">struct</span> <span style="color: #98fb98;">hash</span>&lt;<span style="color: #7fffd4;">thread</span>::<span style="color: #98fb98;">id</span>&gt;;
}
</pre>
</div>
</div>
</div>
<div id="outline-container-sec-3-3" class="outline-3">
<h3 id="sec-3-3"><code>thread</code> 类</h3>
<div class="outline-text-3" id="text-3-3">
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #00ffff;">namespace</span> <span style="color: #7fffd4;">std</span> {
<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">thread</span> {
 <span style="color: #00ffff;">public</span>:
  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">types:</span>
  <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">id</span>;
  <span style="color: #00ffff;">typedef</span> <span style="color: #98fb98;">implementation</span>-defined native_handle_type; <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">See 30.2.3</span>
  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">construct/copy/destroy:</span>
  thread() noexcept;
  <span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">F</span>, <span style="color: #00ffff;">class</span> ...Args&gt; <span style="color: #00ffff;">explicit</span> <span style="color: #87cefa;">thread</span>(<span style="color: #98fb98;">F</span>&amp;&amp; <span style="color: #eedd82;">f</span>, Args&amp;&amp;... args);
  ~<span style="color: #87cefa;">thread</span>();
  <span style="color: #87cefa;">thread</span>(<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">thread</span>&amp;) = <span style="color: #00ffff;">delete</span>;
  thread(<span style="color: #98fb98;">thread</span>&amp;&amp;) noexcept;
  <span style="color: #98fb98;">thread</span>&amp; <span style="color: #00ffff;">operator</span><span style="color: #87cefa;">=</span>(<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">thread</span>&amp;) = <span style="color: #00ffff;">delete</span>;
  thread&amp; <span style="color: #00ffff;">operator</span>=(<span style="color: #98fb98;">thread</span>&amp;&amp;) noexcept;
  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">members:</span>
  <span style="color: #98fb98;">void</span> <span style="color: #87cefa;">swap</span>(<span style="color: #98fb98;">thread</span>&amp;) noexcept;
  <span style="color: #98fb98;">bool</span> <span style="color: #87cefa;">joinable</span>() <span style="color: #00ffff;">const</span> <span style="color: #98fb98;">noexcept</span>;
  <span style="color: #98fb98;">void</span> <span style="color: #87cefa;">join</span>();
  <span style="color: #98fb98;">void</span> <span style="color: #87cefa;">detach</span>();
  <span style="color: #98fb98;">id</span> <span style="color: #87cefa;">get_id</span>() <span style="color: #00ffff;">const</span> <span style="color: #98fb98;">noexcept</span>;
  <span style="color: #98fb98;">native_handle_type</span> <span style="color: #87cefa;">native_handle</span>(); <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">See 30.2.3</span>
  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">static members:</span>
  <span style="color: #00ffff;">static</span> <span style="color: #98fb98;">unsigned</span> <span style="color: #87cefa;">hardware_concurrency</span>() noexcept;
};
}
</pre>
</div>
</div>
</div>

<div id="outline-container-sec-3-4" class="outline-3">
<h3 id="sec-3-4">Constructs a thread object</h3>
<div class="outline-text-3" id="text-3-4">
<p>
从如上的 <code>thread</code> 类知道, 构造 thread 对象:
</p>
<ol class="org-ol">
<li>默认构造构造一个线程对象,但并不代表任何执行线程.
</li>
<li>移动构造从其他线程构造一个 thread 对象,并设置其他线程为默认构造状态.
</li>
<li>初始化构造创建一个新的 thread 对象并把它与执行线程相关联.复制/移动所有参数
<code>args..</code> 到 thread 可访问的内存通过如下函数:
</li>
</ol>
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">T</span>&gt;
<span style="color: #00ffff;">typename</span> <span style="color: #7fffd4;">decay</span>&lt;<span style="color: #98fb98;">T</span>&gt;::<span style="color: #98fb98;">type</span> <span style="color: #87cefa;">decay_copy</span>(<span style="color: #98fb98;">T</span>&amp;&amp; <span style="color: #eedd82;">v</span>) {
    <span style="color: #00ffff;">return</span> <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">forward</span>&lt;T&gt;(v);
}
</pre>
</div>
<p>
求值和复制/移动参数过程丢出的任何 exceptions 仅在当前线程丢出,不在新线程中.
</p>
<ol class="org-ol">
<li>复制构造复制构造被删除.线程不可被复制.
</li>
</ol>

<p>
实例:
</p>
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;iostream&gt;</span>  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">NOLINT</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;utility&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;thread&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;functional&gt;</span>

<span style="color: #00ffff;">using</span> <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">cout</span>;
<span style="color: #00ffff;">using</span> <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">endl</span>;

<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">Thread1Fun</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">n</span>) {
  <span style="color: #00ffff;">for</span> (<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span> = 0; i &lt; n; ++i) {
    cout &lt;&lt; <span style="color: #ffa07a;">"Thread 1 executing"</span> &lt;&lt; endl;
  }
}

<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">Thread2Fun</span>(<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">int</span>&amp; <span style="color: #eedd82;">n</span>) {
  <span style="color: #00ffff;">for</span> (<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span> = 0; i &lt; n; ++i) {
    <span style="color: #7fffd4;">std</span>::cout &lt;&lt; <span style="color: #ffa07a;">"Thread 2 executing\n"</span>;
  }
}

<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">main</span>() {
  <span style="color: #00ffff;">const</span> <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">kLoops</span> = 5;
  <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">thread</span> <span style="color: #eedd82;">t1</span>;  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">t1 is not a thread</span>
  <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">thread</span> <span style="color: #eedd82;">t2</span>(Thread1Fun, kLoops + 1);  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">pass by value</span>
  <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">thread</span> <span style="color: #eedd82;">t3</span>(Thread2Fun, <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">ref</span>(<span style="color: #eedd82;">kLoops</span>));  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">pass by reference</span>
  <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">thread</span> <span style="color: #eedd82;">t4</span>(<span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">move</span>(<span style="color: #eedd82;">t3</span>));
  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">t4 is now running f2(). t3 is no longer a thread</span>
  t2.join();
  t4.join();
  <span style="color: #00ffff;">return</span> 0;
}
</pre>
</div>
</div>
</div>
<div id="outline-container-sec-3-5" class="outline-3">
<h3 id="sec-3-5">joinable</h3>
<div class="outline-text-3" id="text-3-5">
<p>
用来检查一个线程对象是否是正在执行的线程.若是,返回 <code>true</code>. 所以默认构造 thread 对象是不可 joinable.
</p>

<p>
实例:
</p>
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;iostream&gt;</span>  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">NOLINT</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;thread&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;chrono&gt;</span>
<span style="color: #00ffff;">using</span> <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">cout</span>;
<span style="color: #00ffff;">using</span> <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">endl</span>;

<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">ThreadFun</span>() {
  <span style="color: #7fffd4;">std</span>::<span style="color: #7fffd4;">this_thread</span>::sleep_for(<span style="color: #7fffd4;">std</span>::<span style="color: #7fffd4;">chrono</span>::seconds(1));
}

<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">main</span>() {
  <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">thread</span> <span style="color: #eedd82;">t</span>;
  cout &lt;&lt; <span style="color: #ffa07a;">"default construct, joinable: "</span> &lt;&lt; t.joinable() &lt;&lt; endl;

  t = <span style="color: #7fffd4;">std</span>::thread(ThreadFun);
  cout &lt;&lt; <span style="color: #ffa07a;">"initial construct, joinable: "</span> &lt;&lt; t.joinable() &lt;&lt; endl;
  t.join();
  <span style="color: #00ffff;">return</span> 0;
}
</pre>
</div>

<p>
结果:
</p>
<div class="org-src-container">

<pre class="src src-sh">default construct, joinable: 0
initial construct, joinable: 1
</pre>
</div>
</div>
</div>
<div id="outline-container-sec-3-6" class="outline-3">
<h3 id="sec-3-6"><code>get_id</code></h3>
<div class="outline-text-3" id="text-3-6">
<p>
返回 thread 对象的 <code>std::thread::id</code> 值.
实例:
</p>
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;iostream&gt;</span>  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">NOLINT</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;thread&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;chrono&gt;</span>

<span style="color: #00ffff;">using</span> <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">cout</span>;
<span style="color: #00ffff;">using</span> <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">endl</span>;

<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">ThreadFun</span>() {
  <span style="color: #7fffd4;">std</span>::<span style="color: #7fffd4;">this_thread</span>::sleep_for(<span style="color: #7fffd4;">std</span>::<span style="color: #7fffd4;">chrono</span>::seconds(1));
}

<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">main</span>() {
  <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">thread</span> <span style="color: #eedd82;">t1</span>(ThreadFun);
  <span style="color: #7fffd4;">std</span>::<span style="color: #7fffd4;">thread</span>::<span style="color: #98fb98;">id</span> <span style="color: #eedd82;">id_t1</span> = t1.get_id();
  cout &lt;&lt; <span style="color: #ffa07a;">"thread1's id: "</span> &lt;&lt; id_t1 &lt;&lt; endl;
  t1.join();
  <span style="color: #00ffff;">return</span> 0;
}
</pre>
</div>
</div>
</div>

<div id="outline-container-sec-3-7" class="outline-3">
<h3 id="sec-3-7"><code>native_handle</code></h3>
<div class="outline-text-3" id="text-3-7">
<p>
这个函数是 implementation-defined. 它允许提供底层实现细节的访问.但实际使用它是 non-portable. 
</p>

<p>
实例: 使用 <code>native_handle</code> 打开在 POSIX 系统上 C++线程的实时调度.
</p>
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;pthread.h&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;thread&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;mutex&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;iostream&gt;</span>  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">NOLINT</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;chrono&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;cstring&gt;</span>
<span style="color: #00ffff;">using</span> <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">cout</span>;
<span style="color: #00ffff;">using</span> <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">endl</span>;

<span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">mutex</span> <span style="color: #eedd82;">iomutex</span>;
<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">ThreadFun</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">thread_id</span>) {
  <span style="color: #7fffd4;">std</span>::<span style="color: #7fffd4;">this_thread</span>::sleep_for(<span style="color: #7fffd4;">std</span>::<span style="color: #7fffd4;">chrono</span>::seconds(1));
  <span style="color: #98fb98;">sched_param</span> <span style="color: #eedd82;">sch</span>;
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">policy</span>;
  pthread_getschedparam(pthread_self(), &amp;policy, &amp;sch);
  <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">lock_guard</span>&lt;<span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">mutex</span>&gt; <span style="color: #eedd82;">lk</span>(iomutex);
  cout &lt;&lt; <span style="color: #ffa07a;">"Thread "</span> &lt;&lt; thread_id &lt;&lt; <span style="color: #ffa07a;">" is executing at priority "</span>
       &lt;&lt; sch.sched_priority &lt;&lt; endl;
}

<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">main</span>() {
  <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">thread</span> <span style="color: #eedd82;">t1</span>(ThreadFun, 1), <span style="color: #eedd82;">t2</span>(ThreadFun, 2);
  <span style="color: #98fb98;">sched_param</span> <span style="color: #eedd82;">sch</span>;
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">policy</span>;
  pthread_getschedparam(t1.native_handle(), &amp;policy, &amp;sch);
  sch.sched_priority = 20;
  <span style="color: #00ffff;">if</span> (pthread_setschedparam(t1.native_handle(), SCHED_FIFO, &amp;sch)) {
    cout &lt;&lt; <span style="color: #ffa07a;">"Failed to setschedparam: "</span> &lt;&lt; <span style="color: #7fffd4;">std</span>::strerror(errno) &lt;&lt; endl;
  }
  t1.join();
  t2.join();
  <span style="color: #00ffff;">return</span> 0;
}
</pre>
</div>

<p>
使用 Super User,结果:
</p>
<div class="org-src-container">

<pre class="src src-sh">$ sudo ./test
Thread 1 is executing at priority 20
Thread 2 is executing at priority 0
</pre>
</div>
</div>
</div>
<div id="outline-container-sec-3-8" class="outline-3">
<h3 id="sec-3-8"><code>hardware_concurrency</code> (static)</h3>
<div class="outline-text-3" id="text-3-8">
<p>
返回硬件支持的 thread 数.这个值仅作为参考.如果这个值不可计算或没有很多的定义,那么实现返回 0.
</p>

<div class="org-src-container">

<pre class="src src-c++"><span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;iostream&gt;</span>  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">NOLINT</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;thread&gt;</span>

<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">main</span>() {
    <span style="color: #98fb98;">unsigned</span> <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">num</span> = <span style="color: #7fffd4;">std</span>::<span style="color: #7fffd4;">thread</span>::hardware_concurrency();
    <span style="color: #7fffd4;">std</span>::cout &lt;&lt; num &lt;&lt; <span style="color: #ffa07a;">" concurrent threads are supported."</span> &lt;&lt; <span style="color: #7fffd4;">std</span>::endl;
}
</pre>
</div>
</div>
</div>
<div id="outline-container-sec-3-9" class="outline-3">
<h3 id="sec-3-9">swap</h3>
<div class="outline-text-3" id="text-3-9">
<p>
<code>swap</code> 操作用来交换 2 个线程对象的底层句柄.有 2 种可选,thread 类的成员函数和在 std 下的全局函数.
</p>

<p>
实例:
</p>
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;iostream&gt;</span>  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">NOLINT</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;thread&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;chrono&gt;</span>

<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">Thread1Fun</span>() {
  <span style="color: #7fffd4;">std</span>::<span style="color: #7fffd4;">this_thread</span>::sleep_for(<span style="color: #7fffd4;">std</span>::<span style="color: #7fffd4;">chrono</span>::seconds(1));
}

<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">Thread2Fun</span>() {
  <span style="color: #7fffd4;">std</span>::<span style="color: #7fffd4;">this_thread</span>::sleep_for(<span style="color: #7fffd4;">std</span>::<span style="color: #7fffd4;">chrono</span>::seconds(1));
}

<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">main</span>() {
    <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">thread</span> <span style="color: #eedd82;">t1</span>(Thread1Fun);
    <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">thread</span> <span style="color: #eedd82;">t2</span>(Thread2Fun);
    <span style="color: #7fffd4;">std</span>::cout &lt;&lt; <span style="color: #ffa07a;">"thread 1 id: "</span> &lt;&lt; t1.get_id() &lt;&lt; <span style="color: #7fffd4;">std</span>::endl;
    <span style="color: #7fffd4;">std</span>::cout &lt;&lt; <span style="color: #ffa07a;">"thread 2 id: "</span> &lt;&lt; t2.get_id() &lt;&lt; <span style="color: #7fffd4;">std</span>::endl;

    <span style="color: #7fffd4;">std</span>::swap(t1, t2);
    <span style="color: #7fffd4;">std</span>::cout &lt;&lt; <span style="color: #ffa07a;">"after std::swap(t1, t2):"</span> &lt;&lt; <span style="color: #7fffd4;">std</span>::endl;
    <span style="color: #7fffd4;">std</span>::cout &lt;&lt; <span style="color: #ffa07a;">"thread 1 id: "</span> &lt;&lt; t1.get_id() &lt;&lt; <span style="color: #7fffd4;">std</span>::endl;
    <span style="color: #7fffd4;">std</span>::cout &lt;&lt; <span style="color: #ffa07a;">"thread 2 id: "</span> &lt;&lt; t2.get_id() &lt;&lt; <span style="color: #7fffd4;">std</span>::endl;

    t1.swap(t2);
    <span style="color: #7fffd4;">std</span>::cout &lt;&lt; <span style="color: #ffa07a;">"after t1.swap(t2):"</span> &lt;&lt; <span style="color: #7fffd4;">std</span>::endl;
    <span style="color: #7fffd4;">std</span>::cout &lt;&lt; <span style="color: #ffa07a;">"thread 1 id: "</span> &lt;&lt; t1.get_id() &lt;&lt; <span style="color: #7fffd4;">std</span>::endl;
    <span style="color: #7fffd4;">std</span>::cout &lt;&lt; <span style="color: #ffa07a;">"thread 2 id: "</span> &lt;&lt; t2.get_id() &lt;&lt; <span style="color: #7fffd4;">std</span>::endl;
    t1.join();
    t2.join();
    <span style="color: #00ffff;">return</span> 0;
}
</pre>
</div>
</div>
</div>
<div id="outline-container-sec-3-10" class="outline-3">
<h3 id="sec-3-10">管理当前 thread 的函数</h3>
<div class="outline-text-3" id="text-3-10">
<p>
在 thread 的头文件中,加了一个新的 namespace <code>this_thread</code> 用来包含一些管理操作当前 thread 的一些函数.
</p>

<div class="org-src-container">

<pre class="src src-c++"><span style="color: #98fb98;">void</span> <span style="color: #87cefa;">yield</span>();
</pre>
</div>
<p>
重新调度线程的执行,让其他线程运行.具体行为依赖于实现,与 OS 的调度机制有关.
</p>

<div class="org-src-container">

<pre class="src src-c++"><span style="color: #7fffd4;">std</span>::<span style="color: #7fffd4;">thread</span>::<span style="color: #98fb98;">id</span> <span style="color: #87cefa;">get_id</span>();
</pre>
</div>
<p>
返回当前线程的 <code>thread::id</code> 类型的对象.
</p>

<div class="org-src-container">

<pre class="src src-c++"><span style="color: #00ffff;">template</span>&lt; <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Rep</span>, <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Period</span> &gt;
<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">sleep_for</span>( <span style="color: #00ffff;">const</span> <span style="color: #7fffd4;">std</span>::<span style="color: #7fffd4;">chrono</span>::<span style="color: #98fb98;">duration</span>&lt;<span style="color: #98fb98;">Rep</span>, <span style="color: #98fb98;">Period</span>&gt;&amp; <span style="color: #eedd82;">sleep_duration</span> );
</pre>
</div>
<p>
阻塞当前线程的执行至少相对时间 <code>sleep_duration</code>.
</p>

<div class="org-src-container">

<pre class="src src-c++"><span style="color: #00ffff;">template</span>&lt; <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Clock</span>, <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Duration</span> &gt;
<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">sleep_until</span>( <span style="color: #00ffff;">const</span> <span style="color: #7fffd4;">std</span>::<span style="color: #7fffd4;">chrono</span>::<span style="color: #98fb98;">time_point</span>&lt;<span style="color: #98fb98;">Clock</span>,<span style="color: #98fb98;">Duration</span>&gt;&amp; <span style="color: #eedd82;">sleep_time</span> );
</pre>
</div>
<p>
阻塞当前线程的执行直到绝对时间 <code>sleep_time</code> 到达.
</p>

<p>
实例:
</p>
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;iostream&gt;</span>  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">NOLINT</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;thread&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;chrono&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;mutex&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;atomic&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;ctime&gt;</span>
<span style="color: #00ffff;">using</span> <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">cout</span>;
<span style="color: #00ffff;">using</span> <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">endl</span>;
<span style="color: #00ffff;">using</span> <span style="color: #7fffd4;">std</span>::<span style="color: #7fffd4;">chrono</span>::<span style="color: #98fb98;">system_clock</span>;

<span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">atomic</span>&lt;<span style="color: #98fb98;">bool</span>&gt; <span style="color: #87cefa;">ready</span>(<span style="color: #7fffd4;">false</span>);

<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">Thread1Fun</span>() {
  <span style="color: #00ffff;">while</span> (!ready) {
    <span style="color: #7fffd4;">std</span>::<span style="color: #7fffd4;">this_thread</span>::yield();
  }
  <span style="color: #7fffd4;">std</span>::<span style="color: #7fffd4;">thread</span>::<span style="color: #98fb98;">id</span> <span style="color: #eedd82;">id</span> = <span style="color: #7fffd4;">std</span>::<span style="color: #7fffd4;">this_thread</span>::get_id();
  cout &lt;&lt; <span style="color: #ffa07a;">"thread "</span> &lt;&lt; id &lt;&lt; <span style="color: #ffa07a;">"go to sleep"</span> &lt;&lt; endl;
  <span style="color: #7fffd4;">std</span>::<span style="color: #7fffd4;">this_thread</span>::sleep_for(<span style="color: #7fffd4;">std</span>::<span style="color: #7fffd4;">chrono</span>::seconds(1));
}

<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">Thread2Fun</span>() {
  <span style="color: #7fffd4;">std</span>::<span style="color: #7fffd4;">thread</span>::<span style="color: #98fb98;">id</span> <span style="color: #eedd82;">id</span> = <span style="color: #7fffd4;">std</span>::<span style="color: #7fffd4;">this_thread</span>::get_id();
  cout &lt;&lt; <span style="color: #ffa07a;">"thread "</span> &lt;&lt; id &lt;&lt; <span style="color: #ffa07a;">"is running"</span> &lt;&lt; endl;
  ready = <span style="color: #7fffd4;">true</span>;

  <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">time_t</span> <span style="color: #eedd82;">tt</span> = <span style="color: #7fffd4;">system_clock</span>::to_time_t(<span style="color: #7fffd4;">system_clock</span>::now());
  <span style="color: #00ffff;">struct</span> <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">tm</span> *<span style="color: #eedd82;">ptm</span> = <span style="color: #7fffd4;">std</span>::localtime(&amp;tt);
  ptm-&gt;tm_sec += 2;
  <span style="color: #7fffd4;">std</span>::<span style="color: #7fffd4;">this_thread</span>::sleep_until(<span style="color: #7fffd4;">system_clock</span>::from_time_t(mktime(ptm)));
}

<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">main</span>() {
  <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">thread</span> <span style="color: #eedd82;">t1</span>(Thread1Fun);
  <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">thread</span> <span style="color: #eedd82;">t2</span>(Thread2Fun);
  t1.join();
  t2.join();
  <span style="color: #00ffff;">return</span> 0;
}
</pre>
</div>
</div>
</div>
</div>
<div id="outline-container-sec-4" class="outline-2">
<h2 id="sec-4">Mutual exclusion</h2>
<div class="outline-text-2" id="text-4">
</div><div id="outline-container-sec-4-1" class="outline-3">
<h3 id="sec-4-1"><code>&lt;mutex&gt;</code> 概要</h3>
<div class="outline-text-3" id="text-4-1">
<p>
头文件 <code>&lt;mutex&gt;</code> 分为: mutexes,locks 和一些特殊函数. 
具体见之后的<a href="#mutex_header">Header &lt;mutex&gt; synopsis</a>.
</p>

<ul class="org-ul">
<li><b>Mutexes</b> 是<a href="#lockable_types">lockable types</a>,用来对关键区域代码访问保护: <a href="#mutex_class"><code>mutex</code></a>,
<a href="#recursive_mutex_class"><code>recursive_mutex</code></a>, <a href="#timed_mutex_class"><code>timed_mutex</code></a>, <a href="#recursive_timed_mutex_class"><code>recursive_timed_mutex</code></a>.
</li>
<li><b>Locks</b> 是用来管理 mutex 的对象,并对 mutex 的 lifetime 自我管理:<a href="#lock_guard_class"><code>lock_guard</code></a>, <a href="#unique_lock_class"><code>unique_lock</code></a>.
</li>
<li><b>Functions</b> 可以同时锁多个 mutexes(<a href="#try_lock_func"><code>try_lock</code></a>, <a href="#lock_func"><code>lock</code></a>),并使某个函数只被调用一次(<a href="#call_once_func"><code>call_once</code></a>).
</li>
</ul>
</div>
</div>

<div id="outline-container-sec-4-2" class="outline-3">
<h3 id="sec-4-2">Lockable types</h3>
<div class="outline-text-3" id="text-4-2">
<p>
<a id="lockable_types" name="lockable_types"></a>
</p>
<img src="http://dreamrunner.org/images/blog/2014/c++11/lockable_type.png" title="'lockable_type'" />

<p>
C++11 为 mutex 定义了不同类型的要求,如上图的层次,往右要求逐渐加强.
</p>
</div>

<div id="outline-container-sec-4-2-1" class="outline-4">
<h4 id="sec-4-2-1">BasicLockable</h4>
<div class="outline-text-4" id="text-4-2-1">
<p>
BasicLockable 概念描述了最少特性类型,也就是满足(若 m 是 BasicLockable 类型
):
</p>
<ul class="org-ul">
<li><code>m.lock()</code>
</li>
<li><code>m.unlock()</code>
</li>
</ul>

<p>
所以所有 mutex 都满足 BasicLockable 类型: <code>mutex</code>, <code>recursive_mutex</code>,
<code>timed_mutex</code>, <code>recursive_timed_mutex</code>, <code>unique_lock</code>.
</p>
</div>
</div>
<div id="outline-container-sec-4-2-2" class="outline-4">
<h4 id="sec-4-2-2">Lockable</h4>
<div class="outline-text-4" id="text-4-2-2">
<p>
Lockable 概念扩展了 BasicLockable 概念,并支持 <code>try_lock</code>. 
</p>

<p>
所以这些 mutex 满足 Lockable 类型: <code>mutex</code>, <code>recursive_mutex</code>,
<code>timed_mutex</code>, <code>recursive_timed_mutex</code>.
</p>
</div>
</div>
<div id="outline-container-sec-4-2-3" class="outline-4">
<h4 id="sec-4-2-3">TimedLockable</h4>
<div class="outline-text-4" id="text-4-2-3">
<p>
TimedLockable 概念扩展了 Lockable 概念,并支持 <code>try_lock_for</code> 和
<code>try_lock_until</code>. 
</p>

<p>
所以这些 mutex 满足 TimedLockable 类型: <code>timed_mutex</code>,
<code>recursive_timed_mutex</code>.
</p>
</div>
</div>
</div>

<div id="outline-container-sec-4-3" class="outline-3">
<h3 id="sec-4-3"><code>mutex</code> 类</h3>
<div class="outline-text-3" id="text-4-3">
<p>
<a id="mutex_class" name="mutex_class"></a>
<code>mutex</code> 类提供了一个不可递归的排它锁.基本接口可以从如下类中参考.
</p>
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #00ffff;">namespace</span> <span style="color: #7fffd4;">std</span> {
<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">mutex</span> {
 <span style="color: #00ffff;">public</span>:
  <span style="color: #98fb98;">constexpr</span> <span style="color: #87cefa;">mutex</span>() noexcept;
  ~<span style="color: #87cefa;">mutex</span>();
  <span style="color: #87cefa;">mutex</span>(<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">mutex</span>&amp;) = <span style="color: #00ffff;">delete</span>;
  <span style="color: #98fb98;">mutex</span>&amp; <span style="color: #00ffff;">operator</span><span style="color: #87cefa;">=</span>(<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">mutex</span>&amp;) = <span style="color: #00ffff;">delete</span>;
  <span style="color: #98fb98;">void</span> <span style="color: #87cefa;">lock</span>();
  <span style="color: #98fb98;">bool</span> <span style="color: #87cefa;">try_lock</span>();
  <span style="color: #98fb98;">void</span> <span style="color: #87cefa;">unlock</span>();
  <span style="color: #00ffff;">typedef</span> <span style="color: #98fb98;">implementation</span>-defined native_handle_type; <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">See 30.2.3</span>
  <span style="color: #98fb98;">native_handle_type</span> <span style="color: #87cefa;">native_handle</span>(); <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">See 30.2.3</span>
};
}
</pre>
</div>

<p>
实例:
</p>
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;iostream&gt;</span>  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">NOLINT</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;vector&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;thread&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;mutex&gt;</span>
<span style="color: #00ffff;">using</span> <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">cout</span>;
<span style="color: #00ffff;">using</span> <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">endl</span>;
<span style="color: #00ffff;">using</span> <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">vector</span>;

<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">g_value</span> = 0;
<span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">mutex</span> <span style="color: #eedd82;">count_mutex</span>;

<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">Increase</span>() {
  <span style="color: #00ffff;">const</span> <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">kLoops</span> = 100;
  <span style="color: #00ffff;">for</span> (<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span> = 0; i &lt; kLoops; ++i) {
    count_mutex.lock();
    g_value++;
    count_mutex.unlock();
  }
}

<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">main</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">argc</span>, <span style="color: #98fb98;">char</span> *<span style="color: #eedd82;">argv</span>[]) {
  <span style="color: #00ffff;">const</span> <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">kNumThreads</span> = 5;
  <span style="color: #98fb98;">vector</span>&lt;<span style="color: #7fffd4;">std</span>::thread&gt; <span style="color: #eedd82;">threads</span>;
  <span style="color: #00ffff;">for</span> (<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span> = 0; i &lt; kNumThreads; ++i) {
    threads.push_back(<span style="color: #7fffd4;">std</span>::thread(Increase));
  }
  <span style="color: #00ffff;">for</span> (<span style="color: #00ffff;">auto</span> &amp;<span style="color: #eedd82;">thread</span> : threads) {
    thread.join();
  }
  cout &lt;&lt; <span style="color: #ffa07a;">"value = "</span> &lt;&lt; g_value &lt;&lt; endl;
  <span style="color: #00ffff;">return</span> 0;
}
</pre>
</div>
</div>
</div>
<div id="outline-container-sec-4-4" class="outline-3">
<h3 id="sec-4-4"><code>recursive_mutex</code> 类</h3>
<div class="outline-text-3" id="text-4-4">
<p>
<a id="recursive_mutex_class" name="recursive_mutex_class"></a>可递归的排它锁.如下基本接口如 <code>mutex</code> 基本一样.
</p>
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #00ffff;">namespace</span> <span style="color: #7fffd4;">std</span> {
<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">recursive_mutex</span> {
 <span style="color: #00ffff;">public</span>:
  <span style="color: #87cefa;">recursive_mutex</span>();
  ~<span style="color: #87cefa;">recursive_mutex</span>();
  <span style="color: #87cefa;">recursive_mutex</span>(<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">recursive_mutex</span>&amp;) = <span style="color: #00ffff;">delete</span>;
  <span style="color: #98fb98;">recursive_mutex</span>&amp; <span style="color: #00ffff;">operator</span><span style="color: #87cefa;">=</span>(<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">recursive_mutex</span>&amp;) = <span style="color: #00ffff;">delete</span>;
  <span style="color: #98fb98;">void</span> <span style="color: #87cefa;">lock</span>();
  <span style="color: #98fb98;">bool</span> <span style="color: #87cefa;">try_lock</span>() noexcept;
  <span style="color: #98fb98;">void</span> <span style="color: #87cefa;">unlock</span>();
  <span style="color: #00ffff;">typedef</span> <span style="color: #98fb98;">implementation</span>-defined native_handle_type; <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">See 30.2.3</span>
  <span style="color: #98fb98;">native_handle_type</span> <span style="color: #87cefa;">native_handle</span>(); <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">See 30.2.3</span>
};
}
</pre>
</div>
</div>
</div>
<div id="outline-container-sec-4-5" class="outline-3">
<h3 id="sec-4-5"><code>timed_mutex</code> 类</h3>
<div class="outline-text-3" id="text-4-5">
<p>
<a id="timed_mutex_class" name="timed_mutex_class"></a>
</p>
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #00ffff;">namespace</span> <span style="color: #7fffd4;">std</span> {
<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">timed_mutex</span> {
 <span style="color: #00ffff;">public</span>:
  <span style="color: #87cefa;">timed_mutex</span>();
  ~<span style="color: #87cefa;">timed_mutex</span>();
  <span style="color: #87cefa;">timed_mutex</span>(<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">timed_mutex</span>&amp;) = <span style="color: #00ffff;">delete</span>;
  <span style="color: #98fb98;">timed_mutex</span>&amp; <span style="color: #00ffff;">operator</span><span style="color: #87cefa;">=</span>(<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">timed_mutex</span>&amp;) = <span style="color: #00ffff;">delete</span>;
  <span style="color: #98fb98;">void</span> <span style="color: #87cefa;">lock</span>();
  <span style="color: #98fb98;">bool</span> <span style="color: #87cefa;">try_lock</span>();
  <span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Rep</span>, <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Period</span>&gt;
  <span style="color: #98fb98;">bool</span> <span style="color: #87cefa;">try_lock_for</span>(<span style="color: #00ffff;">const</span> <span style="color: #7fffd4;">chrono</span>::<span style="color: #98fb98;">duration</span>&lt;<span style="color: #98fb98;">Rep</span>, <span style="color: #98fb98;">Period</span>&gt;&amp; <span style="color: #eedd82;">rel_time</span>);
  <span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Clock</span>, <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Duration</span>&gt;
  <span style="color: #98fb98;">bool</span> <span style="color: #87cefa;">try_lock_until</span>(<span style="color: #00ffff;">const</span> <span style="color: #7fffd4;">chrono</span>::<span style="color: #98fb98;">time_point</span>&lt;<span style="color: #98fb98;">Clock</span>, <span style="color: #98fb98;">Duration</span>&gt;&amp; <span style="color: #eedd82;">abs_time</span>);
  <span style="color: #98fb98;">void</span> <span style="color: #87cefa;">unlock</span>();
  <span style="color: #00ffff;">typedef</span> <span style="color: #98fb98;">implementation</span>-defined native_handle_type; <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">See 30.2.3</span>
  <span style="color: #98fb98;">native_handle_type</span> <span style="color: #87cefa;">native_handle</span>(); <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">See 30.2.3</span>
};
}
</pre>
</div>
</div>
</div>
<div id="outline-container-sec-4-6" class="outline-3">
<h3 id="sec-4-6"><code>recursive_timed_mutex</code> 类</h3>
<div class="outline-text-3" id="text-4-6">
<p>
<a id="recursive_timed_mutex_class" name="recursive_timed_mutex_class"></a>
</p>

<div class="org-src-container">

<pre class="src src-c++"><span style="color: #00ffff;">namespace</span> <span style="color: #7fffd4;">std</span> {
<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">recursive_timed_mutex</span> {
 <span style="color: #00ffff;">public</span>:
  <span style="color: #87cefa;">recursive_timed_mutex</span>();
  ~<span style="color: #87cefa;">recursive_timed_mutex</span>();
  <span style="color: #87cefa;">recursive_timed_mutex</span>(<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">recursive_timed_mutex</span>&amp;) = <span style="color: #00ffff;">delete</span>;
  <span style="color: #98fb98;">recursive_timed_mutex</span>&amp; <span style="color: #00ffff;">operator</span><span style="color: #87cefa;">=</span>(<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">recursive_timed_mutex</span>&amp;) = <span style="color: #00ffff;">delete</span>;
  <span style="color: #98fb98;">void</span> <span style="color: #87cefa;">lock</span>();
  <span style="color: #98fb98;">bool</span> <span style="color: #87cefa;">try_lock</span>() noexcept;
  <span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Rep</span>, <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Period</span>&gt;
  <span style="color: #98fb98;">bool</span> <span style="color: #87cefa;">try_lock_for</span>(<span style="color: #00ffff;">const</span> <span style="color: #7fffd4;">chrono</span>::<span style="color: #98fb98;">duration</span>&lt;<span style="color: #98fb98;">Rep</span>, <span style="color: #98fb98;">Period</span>&gt;&amp; <span style="color: #eedd82;">rel_time</span>);
  <span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Clock</span>, <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Duration</span>&gt;
  <span style="color: #98fb98;">bool</span> <span style="color: #87cefa;">try_lock_until</span>(<span style="color: #00ffff;">const</span> <span style="color: #7fffd4;">chrono</span>::<span style="color: #98fb98;">time_point</span>&lt;<span style="color: #98fb98;">Clock</span>, <span style="color: #98fb98;">Duration</span>&gt;&amp; <span style="color: #eedd82;">abs_time</span>);
  <span style="color: #98fb98;">void</span> <span style="color: #87cefa;">unlock</span>();
  <span style="color: #00ffff;">typedef</span> <span style="color: #98fb98;">implementation</span>-defined native_handle_type; <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">See 30.2.3</span>
  <span style="color: #98fb98;">native_handle_type</span> <span style="color: #87cefa;">native_handle</span>(); <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">See 30.2.3</span>
};
}
</pre>
</div>
</div>
</div>
<div id="outline-container-sec-4-7" class="outline-3">
<h3 id="sec-4-7">Mutex Exception safety</h3>
<div class="outline-text-3" id="text-4-7">
<p>
基本保证: 当 exception 被以上 mutex 的成员函数抛出时,这些 mutex 对象保持有效状态. 如果是 <code>lock</code> 操作被 exception, lock 不会被抛出 exception 的线程所拥有.
</p>

<p>
抛出的是一个 <code>system_error</code> exception, 导致的基本情况是:
</p>
<table border="2" cellspacing="0" cellpadding="6" rules="groups" frame="hsides">


<colgroup>
<col class="left" />

<col class="left" />

<col class="left" />
</colgroup>
<thead>
<tr>
<th scope="col" class="left">exception 类型</th>
<th scope="col" class="left">error 情况</th>
<th scope="col" class="left">描述</th>
</tr>
</thead>
<tbody>
<tr>
<td class="left"><code>system_error</code></td>
<td class="left"><code>errc::resource_deadlock_would_occur</code></td>
<td class="left">deadlock 被检测到</td>
</tr>

<tr>
<td class="left"><code>system_error</code></td>
<td class="left"><code>errc::operation_not_permitted</code></td>
<td class="left">线程没有权利做这个操作</td>
</tr>

<tr>
<td class="left"><code>system_error</code></td>
<td class="left"><code>errc::device_or_resource_busy</code></td>
<td class="left">native handle 已经被锁</td>
</tr>
</tbody>
</table>
</div>
</div>

<div id="outline-container-sec-4-8" class="outline-3">
<h3 id="sec-4-8"><code>lock_guard</code> 类</h3>
<div class="outline-text-3" id="text-4-8">
<p>
<a id="lock_guard_class" name="lock_guard_class"></a>
</p>

<p>
之前的 mutex 必须写明 lock 和 unlock 调用,如果在 lock 和 unlock 之间产生
exception,那么必须在 exception 处理中不能忘记处理 unlock.当只是在一个关键区域内需要 mutex 保护,使用这样的 mutex 既不方便也容易忘记 unlock 而造成死锁.
</p>

<p>
引入对之前的 mutex 的封装后的 <code>lock_guard</code> 和 <code>unique_lock</code> ,提供易用性的 <a href="http://en.wikipedia.com/wiki/Resource_Acquisition_Is_Initialization">RAII-style</a> 机制来获取锁在一段区域内.
</p>

<p>
lock guard 是一个用来管理一个 mutex 对象,并保持锁住它的对象.
</p>

<p>
在构造时,mutex 对象被调用的线程锁住,然后在析构时,mutex 被解锁.它是最简单的 lock,并且作为自动作用范围直到它的作用区域结束时特别有用.通过这种方法,它保证 mutex 对象得到解锁即使在 exception 被抛出时.
</p>

<div class="org-src-container">

<pre class="src src-c++"><span style="color: #00ffff;">namespace</span> <span style="color: #7fffd4;">std</span> {
<span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Mutex</span>&gt;
<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">lock_guard</span> {
 <span style="color: #00ffff;">public</span>:
  <span style="color: #00ffff;">typedef</span> <span style="color: #98fb98;">Mutex</span> <span style="color: #98fb98;">mutex_type</span>;
  <span style="color: #00ffff;">explicit</span> <span style="color: #87cefa;">lock_guard</span>(<span style="color: #98fb98;">mutex_type</span>&amp; <span style="color: #eedd82;">m</span>);
  <span style="color: #87cefa;">lock_guard</span>(<span style="color: #98fb98;">mutex_type</span>&amp; <span style="color: #eedd82;">m</span>, <span style="color: #98fb98;">adopt_lock_t</span>);
  ~<span style="color: #87cefa;">lock_guard</span>();
  <span style="color: #87cefa;">lock_guard</span>(lock_guard <span style="color: #00ffff;">const</span>&amp;) = <span style="color: #00ffff;">delete</span>;
  <span style="color: #98fb98;">lock_guard</span>&amp; <span style="color: #00ffff;">operator</span><span style="color: #87cefa;">=</span>(lock_guard <span style="color: #00ffff;">const</span>&amp;) = <span style="color: #00ffff;">delete</span>;
 <span style="color: #00ffff;">private</span>:
  <span style="color: #98fb98;">mutex_type</span>&amp; <span style="color: #eedd82;">pm</span>; <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">exposition only</span>
};
}
</pre>
</div>

<p>
实例:
</p>
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;iostream&gt;</span>  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">NOLINT</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;thread&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;mutex&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;stdexcept&gt;</span>

<span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">mutex</span> <span style="color: #eedd82;">mtx</span>;

<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">PrintEven</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">x</span>) {
  <span style="color: #00ffff;">if</span> (x % 2 == 0) {
    <span style="color: #7fffd4;">std</span>::cout &lt;&lt; x &lt;&lt; <span style="color: #ffa07a;">" is even\n"</span>;
  } <span style="color: #00ffff;">else</span> {
    <span style="color: #00ffff;">throw</span>(<span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">logic_error</span>(<span style="color: #ffa07a;">"not even"</span>));
  }
}

<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">PrintThreadEvenId</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">id</span>) {
  <span style="color: #00ffff;">try</span> {
    <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">lock_guard</span>&lt;<span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">mutex</span>&gt; <span style="color: #eedd82;">lck</span>(mtx);
    PrintEven(id);
  } <span style="color: #00ffff;">catch</span> (<span style="color: #7fffd4;">std</span>::logic_error&amp;) {
    <span style="color: #7fffd4;">std</span>::cout &lt;&lt; <span style="color: #ffa07a;">"[exception caught]"</span> &lt;&lt; <span style="color: #7fffd4;">std</span>::endl;
  }
}

<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">main</span>() {
  <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">thread</span> <span style="color: #eedd82;">threads</span>[10];
  <span style="color: #00ffff;">for</span> (<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span> = 0; i &lt; 10; ++i) {
    threads[i] = <span style="color: #7fffd4;">std</span>::thread(PrintThreadEvenId, i+1);
  }
  <span style="color: #00ffff;">for</span> (<span style="color: #00ffff;">auto</span>&amp; <span style="color: #eedd82;">th</span> : threads) {
    th.join();
  }
  <span style="color: #00ffff;">return</span> 0;
}
</pre>
</div>
</div>
</div>
<div id="outline-container-sec-4-9" class="outline-3">
<h3 id="sec-4-9"><code>unique_lock</code> 类</h3>
<div class="outline-text-3" id="text-4-9">
<p>
<a id="unique_lock_class" name="unique_lock_class"></a>
</p>

<p>
<code>unique_lock</code> 与上面的 <code>lock_guard</code> 基本差不多,同样是 <a href="http://en.wikipedia.com/wiki/Resource_Acquisition_Is_Initialization">RAII-style</a> 机制来获取锁在一段区域内的对象.
</p>

<p>
但 <code>lock_guard</code> 非常简单,只提供构造自动拥有锁和析构释放锁,如果需要一些其他的操作,那么就需要更复杂和接口更多的类来处理, <code>lock_guard</code> 能满足如此要求. 它类基本接口如下.
</p>
</div>

<div id="outline-container-sec-4-9-1" class="outline-4">
<h4 id="sec-4-9-1">class</h4>
<div class="outline-text-4" id="text-4-9-1">
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #00ffff;">namespace</span> <span style="color: #7fffd4;">std</span> {
<span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Mutex</span>&gt;
<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">unique_lock</span> {
 <span style="color: #00ffff;">public</span>:
  <span style="color: #00ffff;">typedef</span> <span style="color: #98fb98;">Mutex</span> <span style="color: #98fb98;">mutex_type</span>;
  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">30.4.2.2.1, construct/copy/destroy:</span>
  unique_lock() noexcept;
  <span style="color: #00ffff;">explicit</span> <span style="color: #87cefa;">unique_lock</span>(<span style="color: #98fb98;">mutex_type</span>&amp; <span style="color: #eedd82;">m</span>);
  unique_lock(<span style="color: #98fb98;">mutex_type</span>&amp; <span style="color: #eedd82;">m</span>, <span style="color: #98fb98;">defer_lock_t</span>) noexcept;
  <span style="color: #87cefa;">unique_lock</span>(<span style="color: #98fb98;">mutex_type</span>&amp; <span style="color: #eedd82;">m</span>, <span style="color: #98fb98;">try_to_lock_t</span>);
  <span style="color: #87cefa;">unique_lock</span>(<span style="color: #98fb98;">mutex_type</span>&amp; <span style="color: #eedd82;">m</span>, <span style="color: #98fb98;">adopt_lock_t</span>);
  <span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Clock</span>, <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Duration</span>&gt;
  <span style="color: #87cefa;">unique_lock</span>(<span style="color: #98fb98;">mutex_type</span>&amp; <span style="color: #eedd82;">m</span>, <span style="color: #00ffff;">const</span> <span style="color: #7fffd4;">chrono</span>::<span style="color: #98fb98;">time_point</span>&lt;<span style="color: #98fb98;">Clock</span>, <span style="color: #98fb98;">Duration</span>&gt;&amp; <span style="color: #eedd82;">abs_time</span>);
  <span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Rep</span>, <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Period</span>&gt;
  <span style="color: #87cefa;">unique_lock</span>(<span style="color: #98fb98;">mutex_type</span>&amp; <span style="color: #eedd82;">m</span>, <span style="color: #00ffff;">const</span> <span style="color: #7fffd4;">chrono</span>::<span style="color: #98fb98;">duration</span>&lt;<span style="color: #98fb98;">Rep</span>, <span style="color: #98fb98;">Period</span>&gt;&amp; <span style="color: #eedd82;">rel_time</span>);
  ~<span style="color: #87cefa;">unique_lock</span>();
  <span style="color: #87cefa;">unique_lock</span>(unique_lock <span style="color: #00ffff;">const</span>&amp;) = <span style="color: #00ffff;">delete</span>;
  <span style="color: #98fb98;">unique_lock</span>&amp; <span style="color: #00ffff;">operator</span><span style="color: #87cefa;">=</span>(unique_lock <span style="color: #00ffff;">const</span>&amp;) = <span style="color: #00ffff;">delete</span>;
  unique_lock(<span style="color: #98fb98;">unique_lock</span>&amp;&amp; <span style="color: #eedd82;">u</span>) noexcept;
  unique_lock&amp; <span style="color: #00ffff;">operator</span>=(<span style="color: #98fb98;">unique_lock</span>&amp;&amp; u) noexcept;
  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">30.4.2.2.2, locking:</span>
  <span style="color: #98fb98;">void</span> <span style="color: #87cefa;">lock</span>();
  <span style="color: #98fb98;">bool</span> <span style="color: #87cefa;">try_lock</span>();
  <span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Rep</span>, <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Period</span>&gt;
  <span style="color: #98fb98;">bool</span> <span style="color: #87cefa;">try_lock_for</span>(<span style="color: #00ffff;">const</span> <span style="color: #7fffd4;">chrono</span>::<span style="color: #98fb98;">duration</span>&lt;<span style="color: #98fb98;">Rep</span>, <span style="color: #98fb98;">Period</span>&gt;&amp; <span style="color: #eedd82;">rel_time</span>);
  <span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Clock</span>, <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Duration</span>&gt;
  <span style="color: #98fb98;">bool</span> <span style="color: #87cefa;">try_lock_until</span>(<span style="color: #00ffff;">const</span> <span style="color: #7fffd4;">chrono</span>::<span style="color: #98fb98;">time_point</span>&lt;<span style="color: #98fb98;">Clock</span>, <span style="color: #98fb98;">Duration</span>&gt;&amp; <span style="color: #eedd82;">abs_time</span>);
  <span style="color: #98fb98;">void</span> <span style="color: #87cefa;">unlock</span>();
  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">30.4.2.2.3, modifiers:</span>
  <span style="color: #98fb98;">void</span> <span style="color: #87cefa;">swap</span>(<span style="color: #98fb98;">unique_lock</span>&amp; <span style="color: #eedd82;">u</span>) noexcept;
  mutex_type *release() noexcept;
  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">30.4.2.2.4, observers:</span>
  <span style="color: #98fb98;">bool</span> <span style="color: #87cefa;">owns_lock</span>() <span style="color: #00ffff;">const</span> <span style="color: #98fb98;">noexcept</span>;
  <span style="color: #00ffff;">explicit</span> <span style="color: #00ffff;">operator</span> <span style="color: #98fb98;">bool</span> () <span style="color: #00ffff;">const</span> <span style="color: #98fb98;">noexcept</span>;
  mutex_type* mutex() <span style="color: #00ffff;">const</span> <span style="color: #98fb98;">noexcept</span>;
 <span style="color: #00ffff;">private</span>:
  <span style="color: #98fb98;">mutex_type</span> *<span style="color: #eedd82;">pm</span>; <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">exposition only</span>
  <span style="color: #98fb98;">bool</span> <span style="color: #eedd82;">owns</span>; <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">exposition only</span>
};
<span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Mutex</span>&gt;
<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">swap</span>(<span style="color: #98fb98;">unique_lock</span>&lt;<span style="color: #98fb98;">Mutex</span>&gt;&amp; <span style="color: #eedd82;">x</span>, <span style="color: #98fb98;">unique_lock</span>&lt;<span style="color: #98fb98;">Mutex</span>&gt;&amp; <span style="color: #eedd82;">y</span>) noexcept;
}
</pre>
</div>
</div>
</div>
<div id="outline-container-sec-4-9-2" class="outline-4">
<h4 id="sec-4-9-2">Constructor</h4>
<div class="outline-text-4" id="text-4-9-2">
<p>
在<a href="#mutex_header">mutex header 概要</a>中可以看到有不同的构造函数,其中一类 <code>unique_lock</code> 构造传入不同的类型:
</p>
<ul class="org-ul">
<li><code>defer_lock</code> : 不去获取 mutex,只有要和 mutex 一样,手动去 lock 它.
</li>
<li><code>try_to_lock</code> : 相当于在构造时,调用 <code>try_lock</code>, 不阻塞,之后可通过成员函数 <code>bool owns_lock()</code> 或直接操作符 <code>explicit operator bool()
  const</code> 判断是否获取锁成功.
</li>
<li><code>adopt_lock_t</code> : 认为调用的线程已经占有这个锁 m.已经占有这个锁了,为什么要去创建一个 <code>unique_lock</code> 去包含它呢? 因为可以利用 <code>unique_lock</code>
中途接手管理这个锁 m, 比如想用 <a href="http://en.wikipedia.com/wiki/Resource_Acquisition_Is_Initialization">RAII-style</a> 机制管理它,使它 exception
safe 等.
</li>
</ul>

<p>
这些类型在源代码定义基本如下:
</p>
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #00ffff;">struct</span> <span style="color: #98fb98;">defer_lock_t</span> { };
<span style="color: #00ffff;">struct</span> <span style="color: #98fb98;">try_to_lock_t</span> { };
<span style="color: #00ffff;">struct</span> <span style="color: #98fb98;">adopt_lock_t</span> { };
constexpr <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">defer_lock_t</span> <span style="color: #eedd82;">defer_lock</span> = <span style="color: #7fffd4;">std</span>::defer_lock_t();
constexpr <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">try_to_lock_t</span> <span style="color: #eedd82;">try_to_lock</span> = <span style="color: #7fffd4;">std</span>::try_to_lock_t();
constexpr <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">adopt_lock_t</span> <span style="color: #eedd82;">adopt_lock</span> = <span style="color: #7fffd4;">std</span>::adopt_lock_t();
</pre>
</div>

<p>
余下的构造:
</p>
<ul class="org-ul">
<li><code>unique_lock();</code> :仅仅创建一个 <code>nique_lock</code> 对象,不和任何 mutex 相关联.
</li>
<li><code>nique_lock(unique_lock&amp;&amp; other);</code> : 通过 other 的内容来构造
<code>nique_lock</code>  对像,使得 other 不和任何 mutex 相关连联.
</li>
<li><code>explicit unique_lock(mutex_type&amp; m);</code> : 通过 <code>m.lock()</code> 来构造与 m 相关联的 <code>unique_lock</code> 对象.
</li>
<li><code>unique_lock(mutex_type&amp; m, const std::chrono::duration&lt;Rep,Period&gt;&amp;
  timeout_duration);</code> : 通过 <code>m.try_lock_for(timeout_duration)</code> 来构造与 m 相关联的 <code>unique_lock</code> 对象.
</li>
<li><code>unique_lock( mutex_type&amp; m, const
  std::chrono::time_point&lt;Clock,Duration&gt;&amp; timeout_time);</code> : 通过
<code>m.try_lock_until(timeout_time)</code> 来构造与 m 相关联的 <code>unique_lock</code> 对象.
</li>
</ul>
</div>
</div>

<div id="outline-container-sec-4-9-3" class="outline-4">
<h4 id="sec-4-9-3">实例</h4>
<div class="outline-text-4" id="text-4-9-3">
<p>
利用 <code>defer_lock</code>, 不去获取 mutex, 只创建与它相关联的 <code>unique_lock</code> 对象,之后用 <code>lock()</code> 同时去获取两个锁,防止死锁.
</p>
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;iostream&gt;</span>  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">NOLINT</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;mutex&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;thread&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;chrono&gt;</span>
<span style="color: #00ffff;">using</span> <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">cout</span>;
<span style="color: #00ffff;">using</span> <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">endl</span>;

<span style="color: #00ffff;">struct</span> <span style="color: #98fb98;">Box</span> {
  <span style="color: #00ffff;">explicit</span> <span style="color: #87cefa;">Box</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">num</span>) : num_things{num} {}
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">num_things</span>;
  <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">mutex</span> <span style="color: #eedd82;">m</span>;
};

<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">Transfer</span>(<span style="color: #98fb98;">Box</span> *<span style="color: #eedd82;">from</span>, <span style="color: #98fb98;">Box</span> *<span style="color: #eedd82;">to</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">num</span>) {
  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">don't actually take the locks yet</span>
  <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">unique_lock</span>&lt;<span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">mutex</span>&gt; <span style="color: #eedd82;">lock1</span>(from-&gt;m, <span style="color: #7fffd4;">std</span>::defer_lock);
  <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">unique_lock</span>&lt;<span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">mutex</span>&gt; <span style="color: #eedd82;">lock2</span>(to-&gt;m, <span style="color: #7fffd4;">std</span>::defer_lock);
  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">lock both unique_locks without deadlock</span>
  <span style="color: #7fffd4;">std</span>::lock(lock1, lock2);
  from-&gt;num_things -= num;
  to-&gt;num_things += num;
  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">'from.m' and 'to.m' mutexes unlocked in 'unique_lock' dtors</span>
}

<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">main</span>() {
  <span style="color: #98fb98;">Box</span> <span style="color: #eedd82;">acc1</span>(100);
  <span style="color: #98fb98;">Box</span> <span style="color: #eedd82;">acc2</span>(50);
  cout &lt;&lt; <span style="color: #ffa07a;">"acc1 num = "</span> &lt;&lt; acc1.num_things &lt;&lt;
      <span style="color: #ffa07a;">" ,acc2 num = "</span> &lt;&lt; acc2.num_things &lt;&lt; endl;
  <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">thread</span> <span style="color: #eedd82;">t1</span>(Transfer, &amp;acc1, &amp;acc2, 10);
  <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">thread</span> <span style="color: #eedd82;">t2</span>(Transfer, &amp;acc2, &amp;acc1, 5);
  t1.join();
  t2.join();
  cout &lt;&lt; <span style="color: #ffa07a;">"after transfer: "</span> &lt;&lt; <span style="color: #ffa07a;">"acc1 num = "</span> &lt;&lt; acc1.num_things &lt;&lt;
      <span style="color: #ffa07a;">" ,acc2 num = "</span> &lt;&lt; acc2.num_things &lt;&lt; endl;
  <span style="color: #00ffff;">return</span> 0;
}
</pre>
</div>
</div>
</div>
</div>
<div id="outline-container-sec-4-10" class="outline-3">
<h3 id="sec-4-10"><code>lock_guard</code> VS <code>unique_lock</code></h3>
<div class="outline-text-3" id="text-4-10">
<p>
<code>lock_guard</code> 和 <code>unique_lock</code> 很大程序上很相似,都是 <a href="http://en.wikipedia.com/wiki/Resource_Acquisition_Is_Initialization">RAII-style</a> 机制来封装一个 mutex 的锁, <code>lock_guard</code> 可以说是 <code>unique_lock</code> 更严格并拥有限制的接口的版本.
</p>

<p>
如何合适的选择两者的使用呢? 如果 <code>lock_guard</code> 对于情况 A 足够,那么就使用它. 不仅仅是从效率(efficiency)考虑,更是从想要表达的功能(functionality)
考虑. 使用 <code>lock_guard</code> 不仅避免了不需要的其他接口的开销,更是对读代码者表达它的意图,你将永远都不需要解锁这个 guard.
</p>

<p>
所以你先考虑使用 <code>lock_guard</code>, 除非你需要 <code>unique_lock</code> 的功能. 比如
<code>condition_variable</code> 就需要传入一个 <code>unique_lock</code> 对象.
</p>
</div>
</div>
<div id="outline-container-sec-4-11" class="outline-3">
<h3 id="sec-4-11"><code>try_lock</code> 和 <code>lock</code></h3>
<div class="outline-text-3" id="text-4-11">
<p>
<a id="try_lock_func" name="try_lock_func"></a>
</p>
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #00ffff;">template</span>&lt; <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Lockable1</span>, <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Lockable2</span>, <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">LockableN</span>... &gt;
<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">try_lock</span>(<span style="color: #98fb98;">Lockable1</span>&amp; <span style="color: #eedd82;">lock1</span>, <span style="color: #98fb98;">Lockable2</span>&amp; <span style="color: #eedd82;">lock2</span>, LockableN&amp; lockn... );
</pre>
</div>

<p>
按对象 lock1, lock2, &#x2026;, lockn 从头到尾的顺序尝试去获取每个锁. 如果某个 <code>try_lock</code> 失败, unlock 所有对象并返回. 返回值:
</p>
<ul class="org-ul">
<li>成功: -1.
</li>
<li>失败: 以 0 为起始点的获取锁失败的对象次序数(0 对于 lock1, 1 对于 lock2, ..).
</li>
</ul>
<p>
<a id="lock_func" name="lock_func"></a>
</p>
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #00ffff;">template</span>&lt; <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Lockable1</span>, <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Lockable2</span>, <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">LockableN</span>... &gt;
<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">lock</span>( <span style="color: #98fb98;">Lockable1</span>&amp; <span style="color: #eedd82;">lock1</span>, <span style="color: #98fb98;">Lockable2</span>&amp; <span style="color: #eedd82;">lock2</span>, LockableN&amp; lockn... );
</pre>
</div>

<p>
占有传入的锁 lock1, lock2, &#x2026;, lockn,使用 <b>防止死锁算饭</b> 来防止死锁.
</p>

<p>
对于传入对象按照不特定的顺序调用它们的成员函数 <code>lock</code> , <code>try_lock</code>,
<code>unlock</code> ,确保最后所有的锁被获取成功在函数返回时.
</p>
</div>
</div>
<div id="outline-container-sec-4-12" class="outline-3">
<h3 id="sec-4-12"><code>call_once</code></h3>
<div class="outline-text-3" id="text-4-12">
<p>
<a id="call_once_func" name="call_once_func"></a>
</p>
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #00ffff;">class</span> <span style="color: #98fb98;">once_flag</span>;
<span style="color: #00ffff;">template</span>&lt; <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Callable</span>, <span style="color: #00ffff;">class</span>... Args &gt;
<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">call_once</span>( <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">once_flag</span>&amp; <span style="color: #eedd82;">flag</span>, <span style="color: #98fb98;">Callable</span>&amp;&amp; <span style="color: #eedd82;">f</span>, Args&amp;&amp;... args );
</pre>
</div>
<p>
为了让一段代码只被多个线程只执行一次, mutex 文件中中包含了这个保证只调用一次的接口.
</p>

<p>
<code>once_flag</code> 对象是辅助 <code>call_once</code> 的,作为多个线程共同执行这段的标识,
所以这些个线程必须传入同一个 <code>once_flag</code> 对象.
</p>

<p>
它并对 <b>exception</b> 做一定的处理,如果 <code>call_once</code> 执行的函数以 exception
退出,那么 exception 会抛给调用者.这次已 exception 退出的执行并不算一次,之后其他函数仍可以继续调用它一次.
</p>

<p>
如下的实例, t1 和 t2 线程抛出 exception, t3 仍然运行一次, t4 无论是怎样,都得不到运行.
</p>
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;iostream&gt;</span>  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">NOLINT</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;thread&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;mutex&gt;</span>
<span style="color: #00ffff;">using</span> <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">cout</span>;
<span style="color: #00ffff;">using</span> <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">endl</span>;

<span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">once_flag</span> <span style="color: #eedd82;">flag</span>;

<span style="color: #00ffff;">inline</span> <span style="color: #98fb98;">void</span> <span style="color: #87cefa;">MayThrowFunction</span>(<span style="color: #98fb98;">bool</span> <span style="color: #eedd82;">do_throw</span>) {
  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">only one instance of this function can be run simultaneously</span>
  <span style="color: #00ffff;">if</span> (do_throw) {
    cout &lt;&lt; <span style="color: #ffa07a;">"throw"</span> &lt;&lt; endl;  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">this message may be printed from 0 to 3 times</span>
    <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">if function exits via exception, another function selected</span>
    <span style="color: #00ffff;">throw</span> <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">exception</span>();
  }
  cout &lt;&lt; <span style="color: #ffa07a;">"once"</span> &lt;&lt; endl;  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">printed exactly once, it's guaranteed that</span>
  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">there are no messages after it</span>
}

<span style="color: #00ffff;">inline</span> <span style="color: #98fb98;">void</span> <span style="color: #87cefa;">DoOnce</span>(<span style="color: #98fb98;">bool</span> <span style="color: #eedd82;">do_throw</span>) {
  <span style="color: #00ffff;">try</span> {
    <span style="color: #7fffd4;">std</span>::call_once(flag, MayThrowFunction, do_throw);
  }
  <span style="color: #00ffff;">catch</span> (...) {
  }
}

<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">main</span>() {
  <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">thread</span> <span style="color: #eedd82;">t1</span>(DoOnce, <span style="color: #7fffd4;">true</span>);
  <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">thread</span> <span style="color: #eedd82;">t2</span>(DoOnce, <span style="color: #7fffd4;">true</span>);
  <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">thread</span> <span style="color: #eedd82;">t3</span>(DoOnce, <span style="color: #7fffd4;">false</span>);
  <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">thread</span> <span style="color: #eedd82;">t4</span>(DoOnce, <span style="color: #7fffd4;">true</span>);
  t1.join();
  t2.join();
  t3.join();
  t4.join();
  <span style="color: #00ffff;">return</span> 0;
}
</pre>
</div>
</div>
</div>
</div>

<div id="outline-container-sec-5" class="outline-2">
<h2 id="sec-5">Condition variables</h2>
<div class="outline-text-2" id="text-5">
</div><div id="outline-container-sec-5-1" class="outline-3">
<h3 id="sec-5-1"><code>&lt;condition_variable&gt;</code> 概要</h3>
<div class="outline-text-3" id="text-5-1">
<p>
<code>&lt;condition_variable&gt;</code> 头文件主要包含两个 <code>condition_variable</code> 类, 一个全局函数.
</p>
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #00ffff;">namespace</span> <span style="color: #7fffd4;">std</span> {
<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">condition_variable</span>;
<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">condition_variable_any</span>;
<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">notify_all_at_thread_exit</span>(<span style="color: #98fb98;">condition_variable</span>&amp; <span style="color: #eedd82;">cond</span>, <span style="color: #98fb98;">unique_lock</span>&lt;mutex&gt; <span style="color: #eedd82;">lk</span>);
<span style="color: #00ffff;">enum</span> <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">cv_status</span> { <span style="color: #eedd82;">no_timeout</span>, <span style="color: #eedd82;">timeout</span> };
}
</pre>
</div>
</div>
<div id="outline-container-sec-5-1-1" class="outline-4">
<h4 id="sec-5-1-1"><code>cv_status</code></h4>
<div class="outline-text-4" id="text-5-1-1">
<p>
Condition variables 与 mutex 之类在等待 timeout 时,返回的不一样,mutex 之类放回 <code>bool</code> 类型, 而 Condition variables 特意为它定义了 <code>enum</code> 类型:
<code>no_timeout</code> 和 <code>timeout</code>, 来判断等待是否成功.
</p>
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #00ffff;">enum</span> <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">cv_status</span> { <span style="color: #eedd82;">no_timeout</span>, <span style="color: #eedd82;">timeout</span> };
</pre>
</div>

<ul class="org-ul">
<li><code>cv_status::no_timeout</code> The function returned without a timeout (i.e.,
it was notified).
</li>
<li><code>cv_status::timeout</code> The function returned because it reached its
time limit (timeout).
</li>
</ul>
</div>
</div>

<div id="outline-container-sec-5-1-2" class="outline-4">
<h4 id="sec-5-1-2"><code>notify_all_at_thread_exit</code></h4>
<div class="outline-text-4" id="text-5-1-2">
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #98fb98;">void</span> <span style="color: #87cefa;">notify_all_at_thread_exit</span>(<span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">condition_variable</span>&amp; <span style="color: #eedd82;">cond</span>,
                                <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">unique_lock</span>&lt;<span style="color: #7fffd4;">std</span>::mutex&gt; <span style="color: #eedd82;">lk</span>);
</pre>
</div>
<p>
<code>&lt;condition_variable&gt;</code> 头文件中有这个函数,它提供机制 notify 其他线程在调用这个函数的线程退出时. 它相当于操作(并包括清理所有 <code>thread_local</code> 对象):
</p>
<div class="org-src-container">

<pre class="src src-c++">lk.unlock();
cond.notify_all();
</pre>
</div>

<p>
虽然可以在调用线程的最后同样调用如上两句代码,但意图没有表现出来,表明
cond 的 notify 必须在线程退出时调用,后面维护者可能会在这之后继续添加代码.
<code>notify_all_at_thread_exit</code> 用一句调用替代两个调用,既不用在函数最后去调用它,而且表明它的意图.
</p>

<p>
它的操作流程如下:
</p>
<ol class="org-ol">
<li>之前获取的锁 lk 的拥有权被转移到 cond 的内部.
</li>
<li>当此线程退出时, cond 被 notified 通过:
</li>
</ol>
<div class="org-src-container">

<pre class="src src-c++">lk.unlock();
cond.notify_all();
</pre>
</div>

<p>
<b>Notes</b>
</p>
<ul class="org-ul">
<li>如果 <code>lk.mutex()</code> 没有被当前线程锁住,调用此函数导致 undefined behavior.
</li>
<li>如果 <code>lk.mutex()</code> 的 mutex 不是其他线程使用来等待 condition variable
的同一个的话, 调用此函数导致 undefined behavior.
</li>
</ul>
</div>
</div>
</div>
<div id="outline-container-sec-5-2" class="outline-3">
<h3 id="sec-5-2"><code>condition_variable</code> 类</h3>
<div class="outline-text-3" id="text-5-2">
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #00ffff;">namespace</span> <span style="color: #7fffd4;">std</span> {
<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">condition_variable</span> {
 <span style="color: #00ffff;">public</span>:
  <span style="color: #87cefa;">condition_variable</span>();
  ~<span style="color: #87cefa;">condition_variable</span>();
  <span style="color: #87cefa;">condition_variable</span>(<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">condition_variable</span>&amp;) = <span style="color: #00ffff;">delete</span>;
  <span style="color: #98fb98;">condition_variable</span>&amp; <span style="color: #00ffff;">operator</span><span style="color: #87cefa;">=</span>(<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">condition_variable</span>&amp;) = <span style="color: #00ffff;">delete</span>;
  <span style="color: #98fb98;">void</span> <span style="color: #87cefa;">notify_one</span>() noexcept;
  <span style="color: #98fb98;">void</span> <span style="color: #87cefa;">notify_all</span>() noexcept;
  <span style="color: #98fb98;">void</span> <span style="color: #87cefa;">wait</span>(<span style="color: #98fb98;">unique_lock</span>&lt;mutex&gt;&amp; <span style="color: #eedd82;">lock</span>);
  <span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Predicate</span>&gt;
  <span style="color: #98fb98;">void</span> <span style="color: #87cefa;">wait</span>(<span style="color: #98fb98;">unique_lock</span>&lt;mutex&gt;&amp; <span style="color: #eedd82;">lock</span>, <span style="color: #98fb98;">Predicate</span> <span style="color: #eedd82;">pred</span>);
  <span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Clock</span>, <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Duration</span>&gt;
  <span style="color: #98fb98;">cv_status</span> <span style="color: #87cefa;">wait_until</span>(<span style="color: #98fb98;">unique_lock</span>&lt;mutex&gt;&amp; <span style="color: #eedd82;">lock</span>,
                       <span style="color: #00ffff;">const</span> <span style="color: #7fffd4;">chrono</span>::<span style="color: #98fb98;">time_point</span>&lt;<span style="color: #98fb98;">Clock</span>, <span style="color: #98fb98;">Duration</span>&gt;&amp; <span style="color: #eedd82;">abs_time</span>);
  <span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Clock</span>, <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Duration</span>, <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Predicate</span>&gt;
  <span style="color: #98fb98;">bool</span> <span style="color: #87cefa;">wait_until</span>(<span style="color: #98fb98;">unique_lock</span>&lt;mutex&gt;&amp; <span style="color: #eedd82;">lock</span>,
                  <span style="color: #00ffff;">const</span> <span style="color: #7fffd4;">chrono</span>::<span style="color: #98fb98;">time_point</span>&lt;<span style="color: #98fb98;">Clock</span>, <span style="color: #98fb98;">Duration</span>&gt;&amp; <span style="color: #eedd82;">abs_time</span>,
                  <span style="color: #98fb98;">Predicate</span> <span style="color: #eedd82;">pred</span>);
  <span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Rep</span>, <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Period</span>&gt;
  <span style="color: #98fb98;">cv_status</span> <span style="color: #87cefa;">wait_for</span>(<span style="color: #98fb98;">unique_lock</span>&lt;mutex&gt;&amp; <span style="color: #eedd82;">lock</span>,
                     <span style="color: #00ffff;">const</span> <span style="color: #7fffd4;">chrono</span>::<span style="color: #98fb98;">duration</span>&lt;<span style="color: #98fb98;">Rep</span>, <span style="color: #98fb98;">Period</span>&gt;&amp; <span style="color: #eedd82;">rel_time</span>);
  <span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Rep</span>, <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Period</span>, <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Predicate</span>&gt;
  <span style="color: #98fb98;">bool</span> <span style="color: #87cefa;">wait_for</span>(<span style="color: #98fb98;">unique_lock</span>&lt;mutex&gt;&amp; <span style="color: #eedd82;">lock</span>,
                <span style="color: #00ffff;">const</span> <span style="color: #7fffd4;">chrono</span>::<span style="color: #98fb98;">duration</span>&lt;<span style="color: #98fb98;">Rep</span>, <span style="color: #98fb98;">Period</span>&gt;&amp; <span style="color: #eedd82;">rel_time</span>,
                <span style="color: #98fb98;">Predicate</span> <span style="color: #eedd82;">pred</span>);
  <span style="color: #00ffff;">typedef</span> <span style="color: #98fb98;">implementation</span>-defined native_handle_type; <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">See 30.2.3</span>
  <span style="color: #98fb98;">native_handle_type</span> <span style="color: #87cefa;">native_handle</span>(); <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">See 30.2.3</span>
};
}
</pre>
</div>
<p>
Condition Variable 的基本概念可以从之前篇<a href="http://dreamrunner.org/blog/2014/08/07/C-multithreading-programming/#sec-5-4">浅谈 C++ Multithreading
 Programming</a>中获取.
</p>

<p>
<code>condition_variable</code> 类的 <code>void wait(unique_lock&lt;mutex&gt;&amp; lock,
Predicate pred);</code> 接口:
</p>
<ul class="org-ul">
<li>需要传入 <code>unique_lock</code>.
</li>
<li><code>pred</code> 函数, 如果 predicate 返回 <code>false</code> ,等待. 相当于:
</li>
</ul>
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #00ffff;">while</span> (!pred()) {
    wait(lock);
}
</pre>
</div>

<p>
实例:
</p>
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;iostream&gt;</span>  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">NOLINT</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;string&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;thread&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;mutex&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;condition_variable&gt;</span>
<span style="color: #00ffff;">using</span> <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">string</span>;
<span style="color: #00ffff;">using</span> <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">cout</span>;
<span style="color: #00ffff;">using</span> <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">endl</span>;

<span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">mutex</span> <span style="color: #eedd82;">m</span>;
<span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">condition_variable</span> <span style="color: #eedd82;">cv</span>;
<span style="color: #98fb98;">string</span> <span style="color: #eedd82;">data</span>;
<span style="color: #98fb98;">bool</span> <span style="color: #eedd82;">g_ready</span> = <span style="color: #7fffd4;">false</span>;
<span style="color: #98fb98;">bool</span> <span style="color: #eedd82;">g_processed</span> = <span style="color: #7fffd4;">false</span>;

<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">WorkerThread</span>() {
    <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">Wait until main() sends data</span>
    <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">unique_lock</span>&lt;<span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">mutex</span>&gt; <span style="color: #eedd82;">lk</span>(m);
    cv.wait(lk, []{<span style="color: #00ffff;">return</span> g_ready;});

    <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">after the wait, we own the lock.</span>
    cout &lt;&lt; <span style="color: #ffa07a;">"Worker thread is processing data"</span> &lt;&lt; endl;
    data += <span style="color: #ffa07a;">" after processing"</span>;

    <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">Send data back to main()</span>
    g_processed = <span style="color: #7fffd4;">true</span>;
    cout &lt;&lt; <span style="color: #ffa07a;">"Worker thread signals data processing completed"</span> &lt;&lt; endl;

    <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">Manual unlocking is done before notifying, to avoid</span>
    <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">that the waiting thread gets blocked again.</span>
    lk.unlock();
    cv.notify_one();
}

<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">main</span>() {
    <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">thread</span> <span style="color: #eedd82;">worker</span>(WorkerThread);
     data = <span style="color: #ffa07a;">"Example data"</span>;
    <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">send data to the worker thread</span>
    {
        <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">lock_guard</span>&lt;<span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">mutex</span>&gt; <span style="color: #eedd82;">lk</span>(m);
        g_ready = <span style="color: #7fffd4;">true</span>;
        cout &lt;&lt; <span style="color: #ffa07a;">"main() signals data ready for processing"</span> &lt;&lt; endl;
    }
    cv.notify_one();

    <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">wait for the worker</span>
    {
        <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">unique_lock</span>&lt;<span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">mutex</span>&gt; <span style="color: #eedd82;">lk</span>(m);
        cv.wait(lk, []{<span style="color: #00ffff;">return</span> g_processed;});
    }
    cout &lt;&lt; <span style="color: #ffa07a;">"Back in main(), data = "</span> &lt;&lt; data &lt;&lt; <span style="color: #ffa07a;">'\n'</span>;
    worker.join();
    <span style="color: #00ffff;">return</span> 0;
}
</pre>
</div>
</div>
</div>
<div id="outline-container-sec-5-3" class="outline-3">
<h3 id="sec-5-3"><code>condition_variable_any</code> 类</h3>
<div class="outline-text-3" id="text-5-3">
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #00ffff;">namespace</span> <span style="color: #7fffd4;">std</span> {
<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">condition_variable_any</span> {
 <span style="color: #00ffff;">public</span>:
  <span style="color: #87cefa;">condition_variable_any</span>();
  ~<span style="color: #87cefa;">condition_variable_any</span>();
  <span style="color: #87cefa;">condition_variable_any</span>(<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">condition_variable_any</span>&amp;) = <span style="color: #00ffff;">delete</span>;
  <span style="color: #98fb98;">condition_variable_any</span>&amp; <span style="color: #00ffff;">operator</span><span style="color: #87cefa;">=</span>(<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">condition_variable_any</span>&amp;) = <span style="color: #00ffff;">delete</span>;
  <span style="color: #98fb98;">void</span> <span style="color: #87cefa;">notify_one</span>() noexcept;
  <span style="color: #98fb98;">void</span> <span style="color: #87cefa;">notify_all</span>() noexcept;
  <span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Lock</span>&gt;
  <span style="color: #98fb98;">void</span> <span style="color: #87cefa;">wait</span>(<span style="color: #98fb98;">Lock</span>&amp; <span style="color: #eedd82;">lock</span>);
  <span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Lock</span>, <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Predicate</span>&gt;
  <span style="color: #98fb98;">void</span> <span style="color: #87cefa;">wait</span>(<span style="color: #98fb98;">Lock</span>&amp; <span style="color: #eedd82;">lock</span>, <span style="color: #98fb98;">Predicate</span> <span style="color: #eedd82;">pred</span>);
  <span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Lock</span>, <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Clock</span>, <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Duration</span>&gt;
  <span style="color: #98fb98;">cv_status</span> <span style="color: #87cefa;">wait_until</span>(<span style="color: #98fb98;">Lock</span>&amp; <span style="color: #eedd82;">lock</span>, <span style="color: #00ffff;">const</span> <span style="color: #7fffd4;">chrono</span>::<span style="color: #98fb98;">time_point</span>&lt;<span style="color: #98fb98;">Clock</span>, <span style="color: #98fb98;">Duration</span>&gt;&amp; <span style="color: #eedd82;">abs_time</span>);
  <span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Lock</span>, <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Clock</span>, <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Duration</span>, <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Predicate</span>&gt;
  <span style="color: #98fb98;">bool</span> <span style="color: #87cefa;">wait_until</span>(<span style="color: #98fb98;">Lock</span>&amp; <span style="color: #eedd82;">lock</span>, <span style="color: #00ffff;">const</span> <span style="color: #7fffd4;">chrono</span>::<span style="color: #98fb98;">time_point</span>&lt;<span style="color: #98fb98;">Clock</span>, <span style="color: #98fb98;">Duration</span>&gt;&amp; <span style="color: #eedd82;">abs_time</span>,
                  <span style="color: #98fb98;">Predicate</span> <span style="color: #eedd82;">pred</span>);
  <span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Lock</span>, <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Rep</span>, <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Period</span>&gt;
  <span style="color: #98fb98;">cv_status</span> <span style="color: #87cefa;">wait_for</span>(<span style="color: #98fb98;">Lock</span>&amp; <span style="color: #eedd82;">lock</span>, <span style="color: #00ffff;">const</span> <span style="color: #7fffd4;">chrono</span>::<span style="color: #98fb98;">duration</span>&lt;<span style="color: #98fb98;">Rep</span>, <span style="color: #98fb98;">Period</span>&gt;&amp; <span style="color: #eedd82;">rel_time</span>);
  <span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Lock</span>, <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Rep</span>, <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Period</span>, <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Predicate</span>&gt;
  <span style="color: #98fb98;">bool</span> <span style="color: #87cefa;">wait_for</span>(<span style="color: #98fb98;">Lock</span>&amp; <span style="color: #eedd82;">lock</span>, <span style="color: #00ffff;">const</span> <span style="color: #7fffd4;">chrono</span>::<span style="color: #98fb98;">duration</span>&lt;<span style="color: #98fb98;">Rep</span>, <span style="color: #98fb98;">Period</span>&gt;&amp; <span style="color: #eedd82;">rel_time</span>,
                <span style="color: #98fb98;">Predicate</span> <span style="color: #eedd82;">pred</span>);
};
}
</pre>
</div>

<p>
<code>condition_variable_any</code> 是 <code>condition_variable</code> 的一个通用版,它可以等待任何满足 BasicLockable 要求 Lock 类型的对象.其他与 <code>condition_variable</code>
一样.
</p>

<p>
实例:
</p>
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;iostream&gt;</span>  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">NOLINT</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;condition_variable&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;thread&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;chrono&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;vector&gt;</span>
<span style="color: #00ffff;">using</span> <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">cout</span>;
<span style="color: #00ffff;">using</span> <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">endl</span>;

<span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">condition_variable_any</span> <span style="color: #eedd82;">cv</span>;
<span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">mutex</span> <span style="color: #eedd82;">cv_m</span>;  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">This mutex is used for three purposes:</span>
                  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">1) to synchronize accesses to i</span>
                  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">2) to synchronize accesses to std::cout</span>
                  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">3) for the condition variable cv</span>
<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">g_wait_val</span> = 0;

<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">WaitVal</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">id</span>) {
  <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">unique_lock</span>&lt;<span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">mutex</span>&gt; <span style="color: #eedd82;">lk</span>(cv_m);
  cout &lt;&lt; <span style="color: #ffa07a;">"thread "</span> &lt;&lt; id &lt;&lt; <span style="color: #ffa07a;">" Waiting... "</span> &lt;&lt; endl;
  cv.wait(lk, []{<span style="color: #00ffff;">return</span> g_wait_val == 1;});
  cout &lt;&lt; <span style="color: #ffa07a;">"...finished waiting,"</span> &lt;&lt; <span style="color: #ffa07a;">"thread "</span> &lt;&lt; id &lt;&lt; endl;
}

<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">Signals</span>() {
  <span style="color: #7fffd4;">std</span>::<span style="color: #7fffd4;">this_thread</span>::sleep_for(<span style="color: #7fffd4;">std</span>::<span style="color: #7fffd4;">chrono</span>::seconds(1));
  {
    <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">lock_guard</span>&lt;<span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">mutex</span>&gt; <span style="color: #eedd82;">lk</span>(cv_m);
    cout &lt;&lt; <span style="color: #ffa07a;">"Notifying..."</span> &lt;&lt; endl;
  }
  cv.notify_all();
  <span style="color: #7fffd4;">std</span>::<span style="color: #7fffd4;">this_thread</span>::sleep_for(<span style="color: #7fffd4;">std</span>::<span style="color: #7fffd4;">chrono</span>::seconds(1));
  {
    <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">lock_guard</span>&lt;<span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">mutex</span>&gt; <span style="color: #eedd82;">lk</span>(cv_m);
    g_wait_val = 1;
    cout &lt;&lt; <span style="color: #ffa07a;">"Notifying again..."</span> &lt;&lt; endl;
  }
  cv.notify_all();
}

<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">main</span>() {
  <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">vector</span>&lt;<span style="color: #7fffd4;">std</span>::thread&gt; <span style="color: #eedd82;">threads</span>;
  <span style="color: #00ffff;">for</span> (<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span> = 0; i &lt; 3; ++i) {
    threads.emplace_back(WaitVal, i);
  }
  threads.emplace_back(Signals);
  <span style="color: #00ffff;">for</span> (<span style="color: #00ffff;">auto</span>&amp; <span style="color: #eedd82;">t</span> : threads) {
        t.join();
  }
  <span style="color: #00ffff;">return</span> 0;
}
</pre>
</div>
</div>
</div>
<div id="outline-container-sec-5-4" class="outline-3">
<h3 id="sec-5-4"><code>condition_variable</code> VS <code>condition_variable_any</code></h3>
<div class="outline-text-3" id="text-5-4">
<p>
引自 N3690 §30.5[thread.condition]:
</p>

<p>
Class <code>condition_variable</code> provides a condition variable that can only
wait on an object of type <code>unique_lock&lt;mutex&gt;</code> , allowing maximum
efficiency on some platforms. Class <code>condition_variable_any</code> provides a
general condition variable that can wait on objects of user-supplied
lock types.
</p>

<p>
<code>condition_variable</code> 只与 <code>unique_lock&lt;mutex&gt;</code> 类型对象关联,在某些平台上,它可以更好的得到特定的优化,如果不需要
<code>condition_variable_any</code> 的灵活性, 选更高效的 <code>condition_variable</code> 对象使用.
</p>
</div>
</div>
</div>

<div id="outline-container-sec-6" class="outline-2">
<h2 id="sec-6">Future</h2>
<div class="outline-text-2" id="text-6">
</div><div id="outline-container-sec-6-1" class="outline-3">
<h3 id="sec-6-1"><code>&lt;future&gt;</code> 概要</h3>
<div class="outline-text-3" id="text-6-1">
<p>
如果要异步的获取一个函数的运行结果, 可以创建一个线程,并利用 Condition
varialbes 来同步线程间使得另外线程正确获取到这个结果. 但 C++11 的
<code>future</code> 库使得这一过程更方便, 它提供接口使程序在一个线程中获取一个在同一个或其他线程中运行的函数的结果(值或异常), (这些类使用并不限制在
multi-threaded 程序中,同样可以在 single-threaded 使用.
</p>

<p>
<a href="#future_header">future 的概要</a>主要分为:
</p>
<ul class="org-ul">
<li>运行函数提供共享结果的 Providers 类: <code>promise</code> 和 <code>packaged_task</code> .
</li>
<li>获取共享结果的 Futures 类: <code>future</code> 和 <code>shared_future</code> .
</li>
<li>Error handling: <code>future_error</code> , <code>future_errc</code> 等.
</li>
<li>Providers 提供函数: <code>async</code> .
</li>
</ul>
</div>
</div>

<div id="outline-container-sec-6-2" class="outline-3">
<h3 id="sec-6-2">Error handling</h3>
<div class="outline-text-3" id="text-6-2">
</div><div id="outline-container-sec-6-2-1" class="outline-4">
<h4 id="sec-6-2-1"><code>future_error</code> 类</h4>
<div class="outline-text-4" id="text-6-2-1">
<img src="http://dreamrunner.org/images/blog/2014/c++11/future_error.png" title="'future_error'" />

<p>
<code>future_error</code> 类定义对 future 对象非法操作抛出异常的对象类型. 也就是专门为 future 库中接口出现异常提供特定的异常类.
</p>

<p>
从上图类图可知,这个类继承自 <a href="http://www.cplusplus.com/logic_error"><code>logic_error</code></a> , 并添加获取<a href="http://www.cplusplus.com/error_code"> <code>error_code</code></a> 的成员函数 <code>code</code> , 获取 exception 信息的 <code>what</code> 成员函数.
</p>
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #00ffff;">namespace</span> <span style="color: #7fffd4;">std</span> {
<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">future_error</span> : <span style="color: #00ffff;">public</span> <span style="color: #98fb98;">logic_error</span> {
 <span style="color: #00ffff;">public</span>:
  <span style="color: #87cefa;">future_error</span>(<span style="color: #98fb98;">error_code</span> <span style="color: #eedd82;">ec</span>); <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">exposition only</span>
  <span style="color: #00ffff;">const</span> <span style="color: #98fb98;">error_code</span>&amp; <span style="color: #87cefa;">code</span>() <span style="color: #00ffff;">const</span> <span style="color: #98fb98;">noexcept</span>;
  <span style="color: #00ffff;">const</span> <span style="color: #98fb98;">char</span>* <span style="color: #87cefa;">what</span>() <span style="color: #00ffff;">const</span> <span style="color: #98fb98;">noexcept</span>;
};
}
<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">error_code</span>&amp; <span style="color: #87cefa;">code</span>() <span style="color: #00ffff;">const</span> <span style="color: #98fb98;">noexcept</span>;
</pre>
</div>

<p>
实例:
</p>
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;future&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;iostream&gt;</span>  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">NOLINT</span>

<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">main</span>() {
  <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">future</span>&lt;<span style="color: #98fb98;">int</span>&gt; <span style="color: #eedd82;">empty</span>;
  <span style="color: #00ffff;">try</span> {
    <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">n</span> = empty.get();
  } <span style="color: #00ffff;">catch</span> (<span style="color: #00ffff;">const</span> <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">future_error</span>&amp; <span style="color: #eedd82;">e</span>) {
    <span style="color: #7fffd4;">std</span>::cout &lt;&lt; <span style="color: #ffa07a;">"Caught a future_error with code \""</span> &lt;&lt; e.code()
              &lt;&lt; <span style="color: #ffa07a;">"\"\nMessage: \""</span> &lt;&lt; e.what() &lt;&lt; <span style="color: #ffa07a;">"\"\n"</span>;
  }
}
</pre>
</div>
</div>
</div>
<div id="outline-container-sec-6-2-2" class="outline-4">
<h4 id="sec-6-2-2"><code>future_errc</code></h4>
<div class="outline-text-4" id="text-6-2-2">
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #00ffff;">enum</span> <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">future_errc</span> {
    <span style="color: #eedd82;">broken_promise</span>             = <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">implementation-defined */</span>,
    <span style="color: #eedd82;">future_already_retrieved</span>   = <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">implementation-defined */</span>,
    <span style="color: #eedd82;">promise_already_satisfied</span>  = <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">implementation-defined */</span>,
    <span style="color: #eedd82;">no_state</span>                   = <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">implementation-defined */</span>
};
</pre>
</div>

<p>
这个 enum class 定义了 future 抛出异常的<a href="http://en.cppreference.com/w/cpp/error/error_condition">error condition</a>. <code>future_errc</code> 的值可以用来创建 <code>error_condition</code> 对象, 并与 <code>future_error</code> 的成员函数
<code>code</code> 返回的值对比, 决定所抛出异常的类型.
</p>

<p>
所以 <code>&lt;future&gt;</code> 另外有两个函数提供它们之间的转换:
</p>
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">error_code</span> <span style="color: #87cefa;">make_error_code</span>( <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">future_errc</span> <span style="color: #eedd82;">e</span> );
<span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">error_condition</span> <span style="color: #87cefa;">make_error_condition</span>( <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">future_errc</span> <span style="color: #eedd82;">e</span> );
<span style="color: #00ffff;">template</span>&lt;&gt;
<span style="color: #00ffff;">struct</span> <span style="color: #98fb98;">is_error_condition_enum</span>&lt;<span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">future_errc</span>&gt; : <span style="color: #7fffd4;">std</span>::true_type;
</pre>
</div>

<p>
实例:
</p>
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;iostream&gt;</span>  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">NOLINT</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;future&gt;</span>

<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">main</span>() {
  <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">promise</span>&lt;<span style="color: #98fb98;">int</span>&gt; <span style="color: #eedd82;">prom</span>;

  <span style="color: #00ffff;">try</span> {
    prom.get_future();
    prom.get_future();
    <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">throws std::future_error with future_already_retrieved</span>
  }
  <span style="color: #00ffff;">catch</span> (<span style="color: #7fffd4;">std</span>::future_error&amp; e) {
    <span style="color: #00ffff;">if</span> (e.code() ==
        <span style="color: #7fffd4;">std</span>::make_error_condition(<span style="color: #7fffd4;">std</span>::<span style="color: #7fffd4;">future_errc</span>::future_already_retrieved)) {
      <span style="color: #7fffd4;">std</span>::cerr &lt;&lt; <span style="color: #ffa07a;">"[future already retrieved]\n"</span>;
    } <span style="color: #00ffff;">else</span> {
      <span style="color: #7fffd4;">std</span>::cerr &lt;&lt; <span style="color: #ffa07a;">"[unknown exception]\n"</span>;
    }
  }
  <span style="color: #00ffff;">return</span> 0;
}
</pre>
</div>
</div>
</div>
<div id="outline-container-sec-6-2-3" class="outline-4">
<h4 id="sec-6-2-3"><code>future_status</code></h4>
<div class="outline-text-4" id="text-6-2-3">
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #00ffff;">enum</span> <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">future_status</span> {
    <span style="color: #eedd82;">ready</span>,
    <span style="color: #eedd82;">timeout</span>,
    <span style="color: #eedd82;">deferred</span>
};
</pre>
</div>

<p>
<code>future</code> 和 <code>shared_future</code> 类中属于 wait 类型的接口返回的状态.
</p>
<ul class="org-ul">
<li>deferred: 返回这个类型是因为共享状态(shared state)含有的一个 deferred
函数.(见<a href="#async">async 函数</a>)
</li>
</ul>
</div>
</div>

<div id="outline-container-sec-6-2-4" class="outline-4">
<h4 id="sec-6-2-4"><code>future_category</code></h4>
<div class="outline-text-4" id="text-6-2-4">
<p>
用来识别 future error 种类.
</p>
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #00ffff;">const</span> <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">error_category</span>&amp; <span style="color: #87cefa;">future_category</span>();
</pre>
</div>

<p>
这个函数返回一个 <code>error_category</code> 类型的静态对象,拥有如下特性:
</p>
<ul class="org-ul">
<li>它的 <code>name</code> 成员函数返回指向字符串&#8221;future&#8221;的指针.
</li>
</ul>

<p>
实例:
</p>
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;iostream&gt;</span>  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">NOLINT</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;future&gt;</span>

<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">main</span>() {
  <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">promise</span>&lt;<span style="color: #98fb98;">int</span>&gt; <span style="color: #eedd82;">prom</span>;
  <span style="color: #00ffff;">try</span> {
    prom.get_future();
    prom.get_future();
    <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">throws a std::future_error of the future category</span>
  }
  <span style="color: #00ffff;">catch</span> (<span style="color: #7fffd4;">std</span>::future_error&amp; e) {
    <span style="color: #00ffff;">if</span> (e.code().category() == <span style="color: #7fffd4;">std</span>::future_category()) {
      <span style="color: #7fffd4;">std</span>::cerr &lt;&lt; <span style="color: #ffa07a;">"future_error of the future category thrown\n"</span>;
    }
  }
  <span style="color: #00ffff;">return</span> 0;
}
</pre>
</div>
</div>
</div>
</div>
<div id="outline-container-sec-6-3" class="outline-3">
<h3 id="sec-6-3"><code>template promise</code></h3>
<div class="outline-text-3" id="text-6-3">
<p>
模版类 promise 提供一种方便的方法存储一个值或异常,之后可以异步的被
future 对象获取(同一个或其他线程).
</p>

<p>
promise 对象在共享状态(shared state)存储值的操作 <b>synchronizes-with</b> 在其他函数中成功获取这个共享状态的返回值(如 <code>future::get</code> ).
</p>
</div>
<div id="outline-container-sec-6-3-1" class="outline-4">
<h4 id="sec-6-3-1">class</h4>
<div class="outline-text-4" id="text-6-3-1">
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #00ffff;">namespace</span> <span style="color: #7fffd4;">std</span> {
<span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">R</span>&gt;
<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">promise</span> {
 <span style="color: #00ffff;">public</span>:
  <span style="color: #87cefa;">promise</span>();
  <span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Allocator</span>&gt;
  <span style="color: #87cefa;">promise</span>(<span style="color: #98fb98;">allocator_arg_t</span>, <span style="color: #00ffff;">const</span> <span style="color: #98fb98;">Allocator</span>&amp; <span style="color: #eedd82;">a</span>);
  promise(<span style="color: #98fb98;">promise</span>&amp;&amp; <span style="color: #eedd82;">rhs</span>) noexcept;
  <span style="color: #87cefa;">promise</span>(<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">promise</span>&amp; <span style="color: #eedd82;">rhs</span>) = <span style="color: #00ffff;">delete</span>;
  ~<span style="color: #87cefa;">promise</span>();
  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">assignment</span>
  promise&amp; <span style="color: #00ffff;">operator</span>=(<span style="color: #98fb98;">promise</span>&amp;&amp; rhs) noexcept;
  <span style="color: #98fb98;">promise</span>&amp; <span style="color: #00ffff;">operator</span><span style="color: #87cefa;">=</span>(<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">promise</span>&amp; <span style="color: #eedd82;">rhs</span>) = <span style="color: #00ffff;">delete</span>;
  <span style="color: #98fb98;">void</span> <span style="color: #87cefa;">swap</span>(<span style="color: #98fb98;">promise</span>&amp; <span style="color: #eedd82;">other</span>) noexcept;
  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">retrieving the result</span>
  <span style="color: #98fb98;">future</span>&lt;<span style="color: #98fb98;">R</span>&gt; <span style="color: #87cefa;">get_future</span>();
  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">setting the result</span>
  <span style="color: #98fb98;">void</span> <span style="color: #87cefa;">set_value</span>(<span style="color: #98fb98;">see</span> <span style="color: #eedd82;">below</span> );
  <span style="color: #98fb98;">void</span> <span style="color: #87cefa;">set_exception</span>(<span style="color: #98fb98;">exception_ptr</span> <span style="color: #eedd82;">p</span>);
  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">setting the result with deferred notification</span>
  <span style="color: #98fb98;">void</span> <span style="color: #87cefa;">set_value_at_thread_exit</span>(<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">R</span>&amp; <span style="color: #eedd82;">r</span>);
  <span style="color: #98fb98;">void</span> <span style="color: #87cefa;">set_value_at_thread_exit</span>(<span style="color: #98fb98;">see</span> <span style="color: #eedd82;">below</span> );
  <span style="color: #98fb98;">void</span> <span style="color: #87cefa;">set_exception_at_thread_exit</span>(<span style="color: #98fb98;">exception_ptr</span> <span style="color: #eedd82;">p</span>);
};
<span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">R</span>&gt;
<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">swap</span>(<span style="color: #98fb98;">promise</span>&lt;<span style="color: #98fb98;">R</span>&gt;&amp; <span style="color: #eedd82;">x</span>, <span style="color: #98fb98;">promise</span>&lt;<span style="color: #98fb98;">R</span>&gt;&amp; <span style="color: #eedd82;">y</span>) noexcept;
<span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">R</span>, <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Alloc</span>&gt;
<span style="color: #00ffff;">struct</span> <span style="color: #98fb98;">uses_allocator</span>&lt;<span style="color: #98fb98;">promise</span>&lt;<span style="color: #98fb98;">R</span>&gt;, <span style="color: #98fb98;">Alloc</span>&gt;;
}
</pre>
</div>
</div>
</div>
<div id="outline-container-sec-6-3-2" class="outline-4">
<h4 id="sec-6-3-2"><code>set_value</code> and <code>set_value_at_thread_exit</code></h4>
<div class="outline-text-4" id="text-6-3-2">
<p>
<code>set_value</code> 接口存储值到 shared state,并使 state 准备好.这个操作是原子性的. 而 <code>set_value_at_thread_exit</code> 接口如名字,调用后不会马上设置值到
shared state 中,只在当前函数退出时.
</p>

<p>
使用 <code>get_future</code> 返回与它相关联同一个 shared state 的 future 对象.
</p>

<p>
实例:
</p>
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;iostream&gt;</span>  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">NOLINT</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;functional&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;thread&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;future&gt;</span>

<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">Print</span>(<span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">future</span>&lt;<span style="color: #98fb98;">int</span>&gt;&amp; <span style="color: #eedd82;">fut</span>) {
  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">(synchronizes with getting the future)</span>
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">x</span> = fut.get();
  <span style="color: #7fffd4;">std</span>::cout &lt;&lt; <span style="color: #ffa07a;">"value: "</span> &lt;&lt; x &lt;&lt; <span style="color: #7fffd4;">std</span>::endl;
}

<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">main</span>() {
  <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">promise</span>&lt;<span style="color: #98fb98;">int</span>&gt; <span style="color: #eedd82;">prom</span>;
  <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">future</span>&lt;<span style="color: #98fb98;">int</span>&gt; <span style="color: #eedd82;">fut</span> = prom.get_future();
  <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">thread</span> <span style="color: #eedd82;">t1</span>(Print, <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">ref</span>(<span style="color: #eedd82;">fut</span>));
  prom.set_value(10);  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">fulfill promise</span>
  t1.join();
  <span style="color: #00ffff;">return</span> 0;
}
</pre>
</div>
</div>
</div>
<div id="outline-container-sec-6-3-3" class="outline-4">
<h4 id="sec-6-3-3"><code>set_exception</code> and <code>set_exception_at_thread_exit</code></h4>
<div class="outline-text-4" id="text-6-3-3">
<p>
这两个接口与上面 <code>set_value</code> 和  <code>set_value_at_thread_exit</code> 一样, 只是保存的是 exception.
</p>

<p>
实例:
</p>
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;iostream&gt;</span>  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">NOLINT</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;thread&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;future&gt;</span>

<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">main</span>() {
  <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">promise</span>&lt;<span style="color: #98fb98;">int</span>&gt; <span style="color: #eedd82;">result</span>;

  <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">thread</span> <span style="color: #eedd82;">t</span>([&amp;]{
      <span style="color: #00ffff;">try</span> {
        <span style="color: #00ffff;">throw</span> <span style="color: #7fffd4;">std</span>::runtime_error(<span style="color: #ffa07a;">"Example"</span>);
      } <span style="color: #00ffff;">catch</span>(...) {
        <span style="color: #00ffff;">try</span> {
          <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">store anything thrown in the promise</span>
          result.set_exception(<span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">current_exception</span>());
        } <span style="color: #00ffff;">catch</span>(...) {}  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">set_exception() may throw too</span>
      }
    });

  <span style="color: #00ffff;">try</span> {
    <span style="color: #7fffd4;">std</span>::cout &lt;&lt; result.get_future().get();
  } <span style="color: #00ffff;">catch</span>(<span style="color: #00ffff;">const</span> <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">exception</span>&amp; <span style="color: #eedd82;">e</span>) {
    <span style="color: #7fffd4;">std</span>::cout &lt;&lt; <span style="color: #ffa07a;">"Exception from the thread: "</span> &lt;&lt; e.what() &lt;&lt; <span style="color: #7fffd4;">std</span>::endl;
  }
  t.join();
  <span style="color: #00ffff;">return</span> 0;
}
</pre>
</div>
</div>
</div>
</div>
<div id="outline-container-sec-6-4" class="outline-3">
<h3 id="sec-6-4"><code>template packaged_task</code></h3>
<div class="outline-text-3" id="text-6-4">
<p>
<code>packaged_task</code> 与 <code>promise</code> 类似,都是提供异步获取值的方法,不同是
<code>promise</code> 直接设置值, 而 <code>packaged_task</code> 封装一个可调用的元素,并把这个可调用任务的返回值异步到 shared state 中.
</p>
</div>
<div id="outline-container-sec-6-4-1" class="outline-4">
<h4 id="sec-6-4-1">class</h4>
<div class="outline-text-4" id="text-6-4-1">
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #00ffff;">namespace</span> <span style="color: #7fffd4;">std</span> {
<span style="color: #00ffff;">template</span>&lt;<span style="color: #00ffff;">class</span>&gt; <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">packaged_task</span>; <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">undefined</span>
<span style="color: #00ffff;">template</span>&lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">R</span>, <span style="color: #00ffff;">class</span>... ArgTypes&gt;
<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">packaged_task</span>&lt;R(<span style="color: #eedd82;">ArgTypes</span>...)&gt; {
 <span style="color: #00ffff;">public</span>:
  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">construction and destruction</span>
  packaged_task() noexcept;
  <span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">F</span>&gt;
  <span style="color: #00ffff;">explicit</span> <span style="color: #87cefa;">packaged_task</span>(<span style="color: #98fb98;">F</span>&amp;&amp; <span style="color: #eedd82;">f</span>);
  <span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">F</span>, <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Allocator</span>&gt;
  <span style="color: #00ffff;">explicit</span> <span style="color: #87cefa;">packaged_task</span>(<span style="color: #98fb98;">allocator_arg_t</span>, <span style="color: #00ffff;">const</span> <span style="color: #98fb98;">Allocator</span>&amp; <span style="color: #eedd82;">a</span>, <span style="color: #98fb98;">F</span>&amp;&amp; <span style="color: #eedd82;">f</span>);
  ~packaged_task();
  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">no copy</span>
  packaged_task(<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">packaged_task</span>&amp;) = <span style="color: #00ffff;">delete</span>;
  <span style="color: #98fb98;">packaged_task</span>&amp; <span style="color: #00ffff;">operator</span><span style="color: #87cefa;">=</span>(<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">packaged_task</span>&amp;) = <span style="color: #00ffff;">delete</span>;
  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">move support</span>
  packaged_task(<span style="color: #98fb98;">packaged_task</span>&amp;&amp; <span style="color: #eedd82;">rhs</span>) noexcept;
  packaged_task&amp; <span style="color: #00ffff;">operator</span>=(<span style="color: #98fb98;">packaged_task</span>&amp;&amp; rhs) noexcept;
  <span style="color: #98fb98;">void</span> <span style="color: #87cefa;">swap</span>(<span style="color: #98fb98;">packaged_task</span>&amp; <span style="color: #eedd82;">other</span>) noexcept;
  <span style="color: #98fb98;">bool</span> <span style="color: #87cefa;">valid</span>() <span style="color: #00ffff;">const</span> <span style="color: #98fb98;">noexcept</span>;
  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">result retrieval</span>
  <span style="color: #98fb98;">future</span>&lt;<span style="color: #98fb98;">R</span>&gt; <span style="color: #87cefa;">get_future</span>();
  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">execution</span>
  <span style="color: #98fb98;">void</span> <span style="color: #00ffff;">operator</span><span style="color: #87cefa;">()</span>(ArgTypes... );
  <span style="color: #98fb98;">void</span> <span style="color: #87cefa;">make_ready_at_thread_exit</span>(ArgTypes...);
  <span style="color: #98fb98;">void</span> <span style="color: #87cefa;">reset</span>();
};
<span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">R</span>, <span style="color: #00ffff;">class</span>... ArgTypes&gt;
<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">swap</span>(<span style="color: #98fb98;">packaged_task</span>&lt;R(ArgTypes...)&gt;&amp; <span style="color: #eedd82;">x</span>, <span style="color: #98fb98;">packaged_task</span>&lt;R(ArgTypes...)&gt;&amp; <span style="color: #eedd82;">y</span>) noexcept;
<span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">R</span>, <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Alloc</span>&gt;
<span style="color: #00ffff;">struct</span> <span style="color: #98fb98;">uses_allocator</span>&lt;<span style="color: #98fb98;">packaged_task</span>&lt;<span style="color: #98fb98;">R</span>&gt;, <span style="color: #98fb98;">Alloc</span>&gt;;
}
</pre>
</div>
</div>
</div>
<div id="outline-container-sec-6-4-2" class="outline-4">
<h4 id="sec-6-4-2">construct and use</h4>
<div class="outline-text-4" id="text-6-4-2">
<p>
<code>packaged_task</code> 的创建与 <code>thread</code> 类似, 它可以:
</p>
<ul class="org-ul">
<li>Lambda 表达式.
</li>
<li>Bind 一个函数.
</li>
<li>直接传入函数.
</li>
</ul>

<p>
运行:
</p>
<ul class="org-ul">
<li>因为它重载了操作符 <code>()</code> , 可以直接运行如: <code>task()</code> .
</li>
<li>可以 <code>move</code> 给一个线程运行.
</li>
</ul>

<p>
实例:
</p>
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;iostream&gt;</span>  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">NOLINT</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;cmath&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;thread&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;future&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;functional&gt;</span>

<span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">unique function to avoid disambiguating the std::pow overload set</span>
<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">FunPow</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">x</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">y</span>) {
  <span style="color: #00ffff;">return</span> <span style="color: #7fffd4;">std</span>::pow(x, y);
}

<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">TaskLambda</span>() {
  <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">packaged_task</span>&lt;<span style="color: #98fb98;">int</span>(<span style="color: #98fb98;">int</span>, <span style="color: #98fb98;">int</span>)&gt; <span style="color: #eedd82;">task</span>([](<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">a</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">b</span>) {
      <span style="color: #00ffff;">return</span> <span style="color: #7fffd4;">std</span>::pow(a, b);
    });
  <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">future</span>&lt;<span style="color: #98fb98;">int</span>&gt; <span style="color: #eedd82;">result</span> = task.get_future();
  task(2, 9);
  <span style="color: #7fffd4;">std</span>::cout &lt;&lt; <span style="color: #ffa07a;">"task_lambda:\t"</span> &lt;&lt; result.get() &lt;&lt; <span style="color: #ffa07a;">'\n'</span>;
}

<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">TaskBind</span>() {
  <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">packaged_task</span>&lt;<span style="color: #98fb98;">int</span>()&gt; <span style="color: #eedd82;">task</span>(<span style="color: #7fffd4;">std</span>::bind(FunPow, 2, 11));
  <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">future</span>&lt;<span style="color: #98fb98;">int</span>&gt; <span style="color: #eedd82;">result</span> = task.get_future();
  task();
  <span style="color: #7fffd4;">std</span>::cout &lt;&lt; <span style="color: #ffa07a;">"task_bind:\t"</span> &lt;&lt; result.get() &lt;&lt; <span style="color: #ffa07a;">'\n'</span>;
}

<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">TaskThread</span>() {
  <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">packaged_task</span>&lt;<span style="color: #98fb98;">int</span>(<span style="color: #98fb98;">int</span>, <span style="color: #98fb98;">int</span>)&gt; <span style="color: #eedd82;">task</span>(FunPow);
  <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">future</span>&lt;<span style="color: #98fb98;">int</span>&gt; <span style="color: #eedd82;">result</span> = task.get_future();
  <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">thread</span> <span style="color: #eedd82;">task_td</span>(<span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">move</span>(<span style="color: #eedd82;">task</span>), 2, 10);
  task_td.join();
  <span style="color: #7fffd4;">std</span>::cout &lt;&lt; <span style="color: #ffa07a;">"task_thread:\t"</span> &lt;&lt; result.get() &lt;&lt; <span style="color: #ffa07a;">'\n'</span>;
}

<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">main</span>() {
  TaskLambda();
  TaskBind();
  TaskThread();
}
</pre>
</div>
</div>
</div>
<div id="outline-container-sec-6-4-3" class="outline-4">
<h4 id="sec-6-4-3">reset</h4>
<div class="outline-text-4" id="text-6-4-3">
<p>
<code>packaged_task</code> 的 <code>reset</code> 接口, 重置状态,舍弃之前运行的结果.相当于: <code>*this = packaged_task(std::move(f))</code> .
</p>

<p>
实例:
</p>
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;iostream&gt;</span>  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">NOLINT</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;cmath&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;thread&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;future&gt;</span>

<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">main</span>() {
    <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">packaged_task</span>&lt;<span style="color: #98fb98;">int</span>(<span style="color: #98fb98;">int</span>, <span style="color: #98fb98;">int</span>)&gt; <span style="color: #eedd82;">task</span>([](<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">a</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">b</span>) {
        <span style="color: #00ffff;">return</span> <span style="color: #7fffd4;">std</span>::pow(a, b);
    });
    <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">future</span>&lt;<span style="color: #98fb98;">int</span>&gt; <span style="color: #eedd82;">result</span> = task.get_future();
    task(2, 9);
    <span style="color: #7fffd4;">std</span>::cout &lt;&lt; <span style="color: #ffa07a;">"2^9 = "</span> &lt;&lt; result.get() &lt;&lt; <span style="color: #ffa07a;">'\n'</span>;

    task.reset();
    result = task.get_future();
    <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">thread</span> <span style="color: #eedd82;">task_td</span>(<span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">move</span>(<span style="color: #eedd82;">task</span>), 2, 10);
    task_td.join();
    <span style="color: #7fffd4;">std</span>::cout &lt;&lt; <span style="color: #ffa07a;">"2^10 = "</span> &lt;&lt; result.get() &lt;&lt; <span style="color: #ffa07a;">'\n'</span>;
}
</pre>
</div>
</div>
</div>
</div>
<div id="outline-container-sec-6-5" class="outline-3">
<h3 id="sec-6-5"><code>template future</code> 类</h3>
<div class="outline-text-3" id="text-6-5">
<p>
模版类 <code>future</code> 是用来异步获取共享状态里的结果. <code>future</code> 类是独占的,不能与其他 <code>future</code> 共享异步的获取结果. 若要多个 <code>future</code> 共享异步结果,
使用之后的 <code>shared_future</code> 类.
</p>

<p>
有效的与共享状态相关联的 future 对象,由如下函数构造:
</p>
<ul class="org-ul">
<li><code>async</code> .
</li>
<li><code>promise::get_future</code> .
</li>
<li><code>package_task::get_future</code> .
</li>
</ul>

<p>
它的接口:
</p>
<ul class="org-ul">
<li><code>share</code> : 转换 shared state 从 *this 到一个 <code>shared_future</code> 对象.
</li>
<li><code>get</code> : 返回 shared state 的值, 若未准备好,调用者阻塞等待它准备好.
</li>
<li><code>wait</code> : 阻塞等待结果直到有效.
</li>
<li><code>wait_for</code> 和 <code>wait_until</code> : 等待一段时间, 并通过 <code>future_status</code> 判断等待后的状态.
</li>
</ul>

<div class="org-src-container">

<pre class="src src-c++"><span style="color: #00ffff;">namespace</span> <span style="color: #7fffd4;">std</span> {
<span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">R</span>&gt;
<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">future</span> {
 <span style="color: #00ffff;">public</span>:
  future() noexcept;
  future(<span style="color: #98fb98;">future</span> &amp;&amp;) noexcept;
  <span style="color: #87cefa;">future</span>(<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">future</span>&amp; <span style="color: #eedd82;">rhs</span>) = <span style="color: #00ffff;">delete</span>;
  ~<span style="color: #87cefa;">future</span>();
  <span style="color: #98fb98;">future</span>&amp; <span style="color: #00ffff;">operator</span><span style="color: #87cefa;">=</span>(<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">future</span>&amp; <span style="color: #eedd82;">rhs</span>) = <span style="color: #00ffff;">delete</span>;
  future&amp; <span style="color: #00ffff;">operator</span>=(<span style="color: #98fb98;">future</span>&amp;&amp;) noexcept;
  <span style="color: #98fb98;">shared_future</span>&lt;<span style="color: #98fb98;">R</span>&gt; <span style="color: #87cefa;">share</span>();
  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">retrieving the value</span>
  see <span style="color: #98fb98;">below</span> <span style="color: #87cefa;">get</span>();
  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">functions to check state</span>
  <span style="color: #98fb98;">bool</span> <span style="color: #87cefa;">valid</span>() <span style="color: #00ffff;">const</span> <span style="color: #98fb98;">noexcept</span>;
  <span style="color: #98fb98;">void</span> <span style="color: #87cefa;">wait</span>() <span style="color: #00ffff;">const</span>;
  <span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Rep</span>, <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Period</span>&gt;
  <span style="color: #98fb98;">future_status</span> <span style="color: #87cefa;">wait_for</span>(<span style="color: #00ffff;">const</span> <span style="color: #7fffd4;">chrono</span>::<span style="color: #98fb98;">duration</span>&lt;<span style="color: #98fb98;">Rep</span>, <span style="color: #98fb98;">Period</span>&gt;&amp; <span style="color: #eedd82;">rel_time</span>) <span style="color: #00ffff;">const</span>;
  <span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Clock</span>, <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Duration</span>&gt;
  <span style="color: #98fb98;">future_status</span> <span style="color: #87cefa;">wait_until</span>(<span style="color: #00ffff;">const</span> <span style="color: #7fffd4;">chrono</span>::<span style="color: #98fb98;">time_point</span>&lt;<span style="color: #98fb98;">Clock</span>, <span style="color: #98fb98;">Duration</span>&gt;&amp; <span style="color: #eedd82;">abs_time</span>) <span style="color: #00ffff;">const</span>;
};
}
</pre>
</div>
</div>
</div>
<div id="outline-container-sec-6-6" class="outline-3">
<h3 id="sec-6-6"><code>template shared_future</code> 类</h3>
<div class="outline-text-3" id="text-6-6">
<p>
模版类 <code>shared_future</code> 与 <code>future</code> 基本一样, 不同就是多个
<code>shared_future</code> 对象可以共享异步结果.
</p>

<div class="org-src-container">

<pre class="src src-c++"><span style="color: #00ffff;">namespace</span> <span style="color: #7fffd4;">std</span> {
<span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">R</span>&gt;
<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">shared_future</span> {
 <span style="color: #00ffff;">public</span>:
  shared_future() noexcept;
  <span style="color: #87cefa;">shared_future</span>(<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">shared_future</span>&amp; <span style="color: #eedd82;">rhs</span>);
  shared_future(<span style="color: #98fb98;">future</span>&lt;<span style="color: #98fb98;">R</span>&gt;&amp;&amp;) noexcept;
  shared_future(<span style="color: #98fb98;">shared_future</span>&amp;&amp; <span style="color: #eedd82;">rhs</span>) noexcept;
  ~<span style="color: #87cefa;">shared_future</span>();
  <span style="color: #98fb98;">shared_future</span>&amp; <span style="color: #00ffff;">operator</span><span style="color: #87cefa;">=</span>(<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">shared_future</span>&amp; <span style="color: #eedd82;">rhs</span>);
  shared_future&amp; <span style="color: #00ffff;">operator</span>=(<span style="color: #98fb98;">shared_future</span>&amp;&amp; rhs) noexcept;
  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">retrieving the value</span>
  see <span style="color: #98fb98;">below</span> <span style="color: #87cefa;">get</span>() <span style="color: #00ffff;">const</span>;
  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">functions to check state</span>
  <span style="color: #98fb98;">bool</span> <span style="color: #87cefa;">valid</span>() <span style="color: #00ffff;">const</span> <span style="color: #98fb98;">noexcept</span>;
  <span style="color: #98fb98;">void</span> <span style="color: #87cefa;">wait</span>() <span style="color: #00ffff;">const</span>;
  <span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Rep</span>, <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Period</span>&gt;
  <span style="color: #98fb98;">future_status</span> <span style="color: #87cefa;">wait_for</span>(<span style="color: #00ffff;">const</span> <span style="color: #7fffd4;">chrono</span>::<span style="color: #98fb98;">duration</span>&lt;<span style="color: #98fb98;">Rep</span>, <span style="color: #98fb98;">Period</span>&gt;&amp; <span style="color: #eedd82;">rel_time</span>) <span style="color: #00ffff;">const</span>;
  <span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Clock</span>, <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Duration</span>&gt;
  <span style="color: #98fb98;">future_status</span> <span style="color: #87cefa;">wait_until</span>(<span style="color: #00ffff;">const</span> <span style="color: #7fffd4;">chrono</span>::<span style="color: #98fb98;">time_point</span>&lt;<span style="color: #98fb98;">Clock</span>, <span style="color: #98fb98;">Duration</span>&gt;&amp; <span style="color: #eedd82;">abs_time</span>) <span style="color: #00ffff;">const</span>;
};
}
</pre>
</div>

<p>
实例:
</p>
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;iostream&gt;</span>  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">NOLINT</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;future&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;chrono&gt;</span>

<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">main</span>() {
  <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">promise</span>&lt;<span style="color: #98fb98;">void</span>&gt; <span style="color: #eedd82;">ready_promise</span>, <span style="color: #eedd82;">t1_ready_promise</span>, <span style="color: #eedd82;">t2_ready_promise</span>;
  <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">shared_future</span>&lt;<span style="color: #98fb98;">void</span>&gt; <span style="color: #eedd82;">ready_future</span>(ready_promise.get_future());
  <span style="color: #7fffd4;">std</span>::<span style="color: #7fffd4;">chrono</span>::<span style="color: #98fb98;">time_point</span>&lt;<span style="color: #7fffd4;">std</span>::<span style="color: #7fffd4;">chrono</span>::high_resolution_clock&gt; <span style="color: #eedd82;">start</span>;

  <span style="color: #00ffff;">auto</span> <span style="color: #98fb98;">fun1</span> = [&amp;]() -&gt; <span style="color: #7fffd4;">std</span>::<span style="color: #7fffd4;">chrono</span>::<span style="color: #98fb98;">duration</span>&lt;<span style="color: #98fb98;">double</span>, <span style="color: #7fffd4;">std</span>::milli&gt; {
    t1_ready_promise.set_value();
    ready_future.wait();  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">waits for the signal from main()</span>
    <span style="color: #00ffff;">return</span> <span style="color: #7fffd4;">std</span>::<span style="color: #7fffd4;">chrono</span>::<span style="color: #7fffd4;">high_resolution_clock</span>::now() - start;
  };

  <span style="color: #00ffff;">auto</span> <span style="color: #98fb98;">fun2</span> = [&amp;]() -&gt; <span style="color: #7fffd4;">std</span>::<span style="color: #7fffd4;">chrono</span>::<span style="color: #98fb98;">duration</span>&lt;<span style="color: #98fb98;">double</span>, <span style="color: #7fffd4;">std</span>::milli&gt; {
    t2_ready_promise.set_value();
    ready_future.wait();  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">waits for the signal from main()</span>
    <span style="color: #00ffff;">return</span> <span style="color: #7fffd4;">std</span>::<span style="color: #7fffd4;">chrono</span>::<span style="color: #7fffd4;">high_resolution_clock</span>::now() - start;
  };

  <span style="color: #00ffff;">auto</span> <span style="color: #98fb98;">result1</span> = <span style="color: #7fffd4;">std</span>::async(<span style="color: #7fffd4;">std</span>::<span style="color: #7fffd4;">launch</span>::async, fun1);
  <span style="color: #00ffff;">auto</span> <span style="color: #98fb98;">result2</span> = <span style="color: #7fffd4;">std</span>::async(<span style="color: #7fffd4;">std</span>::<span style="color: #7fffd4;">launch</span>::async, fun2);

  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">wait for the threads to become ready</span>
  t1_ready_promise.get_future().wait();
  t2_ready_promise.get_future().wait();

  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">the threads are ready, start the clock</span>
  start = <span style="color: #7fffd4;">std</span>::<span style="color: #7fffd4;">chrono</span>::<span style="color: #7fffd4;">high_resolution_clock</span>::now();

  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">signal the threads to go</span>
  ready_promise.set_value();

  <span style="color: #7fffd4;">std</span>::cout &lt;&lt; <span style="color: #ffa07a;">"Thread 1 received the signal "</span>
            &lt;&lt; result1.get().count() &lt;&lt; <span style="color: #ffa07a;">" ms after start\n"</span>
            &lt;&lt; <span style="color: #ffa07a;">"Thread 2 received the signal "</span>
            &lt;&lt; result2.get().count() &lt;&lt; <span style="color: #ffa07a;">" ms after start\n"</span>;
  <span style="color: #00ffff;">return</span> 0;
}
</pre>
</div>
</div>
</div>
<div id="outline-container-sec-6-7" class="outline-3">
<h3 id="sec-6-7">template async 函数</h3>
<div class="outline-text-3" id="text-6-7">
<p>
<a id="async" name="async"></a>
模版函数 <code>asnyc</code> 异步运行函数 f,并返回一个 <code>future</code> 对象来获取这个函数调用的结果.
</p>
</div>
<div id="outline-container-sec-6-7-1" class="outline-4">
<h4 id="sec-6-7-1">Launching policy for async</h4>
<div class="outline-text-4" id="text-6-7-1">
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #00ffff;">enum</span> <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">launch</span> : <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">unspecified */</span> {
    async =    <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">unspecified */</span>,
    deferred = <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">unspecified */</span>,
    <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">implementation-defined */</span>
};
</pre>
</div>

<p>
函数 <code>async</code> 有不同的策略来运行函数:
</p>
<ul class="org-ul">
<li><code>launch::async</code> :创建一个新的线程来调用函数ｆ.
</li>
<li><code>launch::deferred</code> :调用函数 f 延迟(deferred)到返回的 future 的 shared
state 被访问时(wait 或 get).
</li>
<li><code>launch::async|launch::deferred</code> :函数自动选择策略运行.与系统的库实现有关.
</li>
</ul>
</div>
</div>

<div id="outline-container-sec-6-7-2" class="outline-4">
<h4 id="sec-6-7-2">async</h4>
<div class="outline-text-4" id="text-6-7-2">
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">F</span>, <span style="color: #00ffff;">class</span>... Args&gt;
<span style="color: #98fb98;">future</span>&lt;<span style="color: #00ffff;">typename</span> <span style="color: #7fffd4;">result_of</span>&lt;<span style="color: #00ffff;">typename</span> <span style="color: #7fffd4;">decay</span>&lt;<span style="color: #98fb98;">F</span>&gt;::<span style="color: #98fb98;">type</span>(<span style="color: #00ffff;">typename</span> <span style="color: #7fffd4;">decay</span>&lt;Args&gt;::<span style="color: #98fb98;">type</span>...)&gt;::<span style="color: #98fb98;">type</span>&gt;
<span style="color: #87cefa;">async</span>(<span style="color: #98fb98;">F</span>&amp;&amp; <span style="color: #eedd82;">f</span>, Args&amp;&amp;... args);
<span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">F</span>, <span style="color: #00ffff;">class</span>... Args&gt;
<span style="color: #98fb98;">future</span>&lt;<span style="color: #00ffff;">typename</span> <span style="color: #7fffd4;">result_of</span>&lt;<span style="color: #00ffff;">typename</span> <span style="color: #7fffd4;">decay</span>&lt;<span style="color: #98fb98;">F</span>&gt;::<span style="color: #98fb98;">type</span>(<span style="color: #00ffff;">typename</span> <span style="color: #7fffd4;">decay</span>&lt;Args&gt;::<span style="color: #98fb98;">type</span>...)&gt;::<span style="color: #98fb98;">type</span>&gt;
<span style="color: #87cefa;">async</span>(<span style="color: #98fb98;">launch</span> <span style="color: #eedd82;">policy</span>, <span style="color: #98fb98;">F</span>&amp;&amp; <span style="color: #eedd82;">f</span>, Args&amp;&amp;... args);
</pre>
</div>

<p>
第一个接口没有 <code>policy</code> 作为传入参数, 相当于
<code>async(std::launch::async | std::launch::deferred, f, args...)</code>
</p>

<p>
实例:
</p>
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;iostream&gt;</span>  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">NOLINT</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;vector&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;algorithm&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;numeric&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;future&gt;</span>

<span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">typename</span> <span style="color: #98fb98;">RAIter</span>&gt;
<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">ParallelSum</span>(<span style="color: #98fb98;">RAIter</span> <span style="color: #eedd82;">beg</span>, <span style="color: #98fb98;">RAIter</span> <span style="color: #eedd82;">end</span>) {
  <span style="color: #00ffff;">auto</span> <span style="color: #98fb98;">len</span> = <span style="color: #7fffd4;">std</span>::distance(beg, end);
  <span style="color: #00ffff;">if</span> (len &lt; 1000)
    <span style="color: #00ffff;">return</span> <span style="color: #7fffd4;">std</span>::accumulate(beg, end, 0);

  <span style="color: #98fb98;">RAIter</span> <span style="color: #eedd82;">mid</span> = beg + len/2;
  <span style="color: #00ffff;">auto</span> <span style="color: #98fb98;">handle</span> = <span style="color: #7fffd4;">std</span>::async(<span style="color: #7fffd4;">std</span>::<span style="color: #7fffd4;">launch</span>::async,
                           <span style="color: #98fb98;">ParallelSum</span>&lt;<span style="color: #98fb98;">RAIter</span>&gt;, mid, end);
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">sum</span> = ParallelSum(beg, mid);
  <span style="color: #00ffff;">return</span> sum + handle.get();
}

<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">main</span>() {
    <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">vector</span>&lt;<span style="color: #98fb98;">int</span>&gt; <span style="color: #eedd82;">v</span>(10000, 1);
    <span style="color: #7fffd4;">std</span>::cout &lt;&lt; <span style="color: #ffa07a;">"The sum is "</span> &lt;&lt; ParallelSum(v.begin(), v.end()) &lt;&lt; <span style="color: #ffa07a;">'\n'</span>;
}
</pre>
</div>
</div>
</div>
</div>
</div>
<div id="outline-container-sec-7" class="outline-2">
<h2 id="sec-7">Header synopsis</h2>
<div class="outline-text-2" id="text-7">
</div><div id="outline-container-sec-7-1" class="outline-3">
<h3 id="sec-7-1"><code>&lt;thread&gt;</code></h3>
<div class="outline-text-3" id="text-7-1">
<p>
<a id="thread_header" name="thread_header"></a>
基本概要如下(§30.3 [thread.threads] of N3690):
</p>
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">Header &lt;thread&gt; synopsis</span>
<span style="color: #00ffff;">namespace</span> <span style="color: #7fffd4;">std</span> {
<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">thread</span>;
<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">swap</span>(<span style="color: #98fb98;">thread</span>&amp; <span style="color: #eedd82;">x</span>, <span style="color: #98fb98;">thread</span>&amp; <span style="color: #eedd82;">y</span>) noexcept;
<span style="color: #00ffff;">namespace</span> <span style="color: #7fffd4;">this_thread</span> {
<span style="color: #7fffd4;">thread</span>::<span style="color: #98fb98;">id</span> <span style="color: #87cefa;">get_id</span>() noexcept;
<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">yield</span>() noexcept;
<span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Clock</span>, <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Duration</span>&gt;
<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">sleep_until</span>(<span style="color: #00ffff;">const</span> <span style="color: #7fffd4;">chrono</span>::<span style="color: #98fb98;">time_point</span>&lt;<span style="color: #98fb98;">Clock</span>, <span style="color: #98fb98;">Duration</span>&gt;&amp; <span style="color: #eedd82;">abs_time</span>);
<span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Rep</span>, <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Period</span>&gt;
<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">sleep_for</span>(<span style="color: #00ffff;">const</span> <span style="color: #7fffd4;">chrono</span>::<span style="color: #98fb98;">duration</span>&lt;<span style="color: #98fb98;">Rep</span>, <span style="color: #98fb98;">Period</span>&gt;&amp; <span style="color: #eedd82;">rel_time</span>);
}
}
</pre>
</div>
</div>
</div>
<div id="outline-container-sec-7-2" class="outline-3">
<h3 id="sec-7-2"><code>&lt;mutex&gt;</code></h3>
<div class="outline-text-3" id="text-7-2">
<p>
<a id="mutex_header" name="mutex_header"></a>
</p>
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">Header &lt;mutex&gt; synopsis</span>
<span style="color: #00ffff;">namespace</span> <span style="color: #7fffd4;">std</span> {
<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">mutex</span>;
<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">recursive_mutex</span>;
<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">timed_mutex</span>;
<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">recursive_timed_mutex</span>;
<span style="color: #00ffff;">struct</span> <span style="color: #98fb98;">defer_lock_t</span> { };
<span style="color: #00ffff;">struct</span> <span style="color: #98fb98;">try_to_lock_t</span> { };
<span style="color: #00ffff;">struct</span> <span style="color: #98fb98;">adopt_lock_t</span> { };
constexpr <span style="color: #98fb98;">defer_lock_t</span> <span style="color: #eedd82;">defer_lock</span> { };
constexpr <span style="color: #98fb98;">try_to_lock_t</span> <span style="color: #eedd82;">try_to_lock</span> { };
constexpr <span style="color: #98fb98;">adopt_lock_t</span> <span style="color: #eedd82;">adopt_lock</span> { };
<span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Mutex</span>&gt; <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">lock_guard</span>;
<span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Mutex</span>&gt; <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">unique_lock</span>;
<span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Mutex</span>&gt;
<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">swap</span>(<span style="color: #98fb98;">unique_lock</span>&lt;<span style="color: #98fb98;">Mutex</span>&gt;&amp; <span style="color: #eedd82;">x</span>, <span style="color: #98fb98;">unique_lock</span>&lt;<span style="color: #98fb98;">Mutex</span>&gt;&amp; <span style="color: #eedd82;">y</span>) noexcept;
<span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">L1</span>, <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">L2</span>, <span style="color: #00ffff;">class</span>... L3&gt; <span style="color: #98fb98;">int</span> <span style="color: #87cefa;">try_lock</span>(<span style="color: #98fb98;">L1</span>&amp;, <span style="color: #98fb98;">L2</span>&amp;, L3&amp;...);
<span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">L1</span>, <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">L2</span>, <span style="color: #00ffff;">class</span>... L3&gt; <span style="color: #98fb98;">void</span> <span style="color: #87cefa;">lock</span>(<span style="color: #98fb98;">L1</span>&amp;, <span style="color: #98fb98;">L2</span>&amp;, L3&amp;...);
<span style="color: #00ffff;">struct</span> <span style="color: #98fb98;">once_flag</span> {
  <span style="color: #98fb98;">constexpr</span> <span style="color: #87cefa;">once_flag</span>() noexcept;
  <span style="color: #87cefa;">once_flag</span>(<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">once_flag</span>&amp;) = <span style="color: #00ffff;">delete</span>;
  <span style="color: #98fb98;">once_flag</span>&amp; <span style="color: #00ffff;">operator</span><span style="color: #87cefa;">=</span>(<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">once_flag</span>&amp;) = <span style="color: #00ffff;">delete</span>;
};
<span style="color: #00ffff;">template</span>&lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Callable</span>, <span style="color: #00ffff;">class</span> ...Args&gt;
<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">call_once</span>(<span style="color: #98fb98;">once_flag</span>&amp; <span style="color: #eedd82;">flag</span>, <span style="color: #98fb98;">Callable</span> <span style="color: #eedd82;">func</span>, Args&amp;&amp;... args);
}
</pre>
</div>
</div>
</div>
<div id="outline-container-sec-7-3" class="outline-3">
<h3 id="sec-7-3"><code>&lt;future&gt;</code></h3>
<div class="outline-text-3" id="text-7-3">
<p>
<a id="future_header" name="future_header"></a>
</p>
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #00ffff;">namespace</span> <span style="color: #7fffd4;">std</span> {
<span style="color: #00ffff;">enum</span> <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">future_errc</span> {
<span style="color: #eedd82;">broken_promise</span> = implementation-defined ,
<span style="color: #eedd82;">future_already_retrieved</span> = implementation-defined ,
<span style="color: #eedd82;">promise_already_satisfied</span> = implementation-defined ,
<span style="color: #eedd82;">no_state</span> = implementation-defined
};
<span style="color: #00ffff;">enum</span> <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">launch</span> : <span style="color: #98fb98;">unspecified</span> {
<span style="color: #eedd82;">async</span> = unspecified ,
<span style="color: #eedd82;">deferred</span> = unspecified ,
<span style="color: #eedd82;">implementation</span>-defined
};
<span style="color: #00ffff;">enum</span> <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">future_status</span> {
<span style="color: #eedd82;">ready</span>,
<span style="color: #eedd82;">timeout</span>,
<span style="color: #eedd82;">deferred</span>
};
<span style="color: #00ffff;">template</span> &lt;&gt; <span style="color: #00ffff;">struct</span> <span style="color: #98fb98;">is_error_code_enum</span>&lt;<span style="color: #98fb98;">future_errc</span>&gt; : <span style="color: #00ffff;">public</span> <span style="color: #98fb98;">true_type</span> { };
<span style="color: #98fb98;">error_code</span> <span style="color: #87cefa;">make_error_code</span>(<span style="color: #98fb98;">future_errc</span> <span style="color: #eedd82;">e</span>) noexcept;
<span style="color: #98fb98;">error_condition</span> <span style="color: #87cefa;">make_error_condition</span>(<span style="color: #98fb98;">future_errc</span> <span style="color: #eedd82;">e</span>) noexcept;
<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">error_category</span>&amp; <span style="color: #87cefa;">future_category</span>() noexcept;
<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">future_error</span>;
<span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">R</span>&gt; <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">promise</span>;
<span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">R</span>&gt; <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">promise</span>&lt;<span style="color: #98fb98;">R</span>&amp;&gt;;
<span style="color: #00ffff;">template</span> &lt;&gt; <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">promise</span>&lt;<span style="color: #98fb98;">void</span>&gt;;
<span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">R</span>&gt;
<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">swap</span>(<span style="color: #98fb98;">promise</span>&lt;<span style="color: #98fb98;">R</span>&gt;&amp; <span style="color: #eedd82;">x</span>, <span style="color: #98fb98;">promise</span>&lt;<span style="color: #98fb98;">R</span>&gt;&amp; <span style="color: #eedd82;">y</span>) noexcept;
<span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">R</span>, <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Alloc</span>&gt;
<span style="color: #00ffff;">struct</span> <span style="color: #98fb98;">uses_allocator</span>&lt;<span style="color: #98fb98;">promise</span>&lt;<span style="color: #98fb98;">R</span>&gt;, <span style="color: #98fb98;">Alloc</span>&gt;;
<span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">R</span>&gt; <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">future</span>;
<span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">R</span>&gt; <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">future</span>&lt;<span style="color: #98fb98;">R</span>&amp;&gt;;
<span style="color: #00ffff;">template</span> &lt;&gt; <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">future</span>&lt;<span style="color: #98fb98;">void</span>&gt;;
<span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">R</span>&gt; <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">shared_future</span>;
<span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">R</span>&gt; <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">shared_future</span>&lt;<span style="color: #98fb98;">R</span>&amp;&gt;;
<span style="color: #00ffff;">template</span> &lt;&gt; <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">shared_future</span>&lt;<span style="color: #98fb98;">void</span>&gt;;
<span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span>&gt; <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">packaged_task</span>; <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">undefined</span>
<span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">R</span>, <span style="color: #00ffff;">class</span>... ArgTypes&gt;
<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">packaged_task</span>&lt;R(<span style="color: #eedd82;">ArgTypes</span>...)&gt;;
<span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">R</span>&gt;
<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">swap</span>(<span style="color: #98fb98;">packaged_task</span>&lt;R(ArgTypes...)&gt;&amp;, <span style="color: #98fb98;">packaged_task</span>&lt;R(ArgTypes...)&gt;&amp;) noexcept;
<span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">R</span>, <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Alloc</span>&gt;
<span style="color: #00ffff;">struct</span> <span style="color: #98fb98;">uses_allocator</span>&lt;<span style="color: #98fb98;">packaged_task</span>&lt;<span style="color: #98fb98;">R</span>&gt;, <span style="color: #98fb98;">Alloc</span>&gt;;
<span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">F</span>, <span style="color: #00ffff;">class</span>... Args&gt;
<span style="color: #98fb98;">future</span>&lt;<span style="color: #00ffff;">typename</span> <span style="color: #7fffd4;">result_of</span>&lt;<span style="color: #00ffff;">typename</span> <span style="color: #7fffd4;">decay</span>&lt;<span style="color: #98fb98;">F</span>&gt;::<span style="color: #98fb98;">type</span>(<span style="color: #00ffff;">typename</span> <span style="color: #7fffd4;">decay</span>&lt;Args&gt;::<span style="color: #98fb98;">type</span>...)&gt;::<span style="color: #98fb98;">type</span>&gt;
<span style="color: #87cefa;">async</span>(<span style="color: #98fb98;">F</span>&amp;&amp; <span style="color: #eedd82;">f</span>, Args&amp;&amp;... args);
<span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">F</span>, <span style="color: #00ffff;">class</span>... Args&gt;
<span style="color: #98fb98;">future</span>&lt;<span style="color: #00ffff;">typename</span> <span style="color: #7fffd4;">result_of</span>&lt;<span style="color: #00ffff;">typename</span> <span style="color: #7fffd4;">decay</span>&lt;<span style="color: #98fb98;">F</span>&gt;::<span style="color: #98fb98;">type</span>(<span style="color: #00ffff;">typename</span> <span style="color: #7fffd4;">decay</span>&lt;Args&gt;::<span style="color: #98fb98;">type</span>...)&gt;::<span style="color: #98fb98;">type</span>&gt;
<span style="color: #87cefa;">async</span>(<span style="color: #98fb98;">launch</span> <span style="color: #eedd82;">policy</span>, <span style="color: #98fb98;">F</span>&amp;&amp; <span style="color: #eedd82;">f</span>, Args&amp;&amp;... args);
}
</pre>
</div>
</div>
</div>
</div>
<div id="outline-container-sec-8" class="outline-2">
<h2 id="sec-8">其他资料</h2>
<div class="outline-text-2" id="text-8">
<p>
<a id="reference" name="reference"></a>
</p>
</div>
<div id="outline-container-sec-8-1" class="outline-3">
<h3 id="sec-8-1">Books</h3>
<div class="outline-text-3" id="text-8-1">
<ul class="org-ul">
<li>Scott Meyers 的<a href="http://www.artima.com/shop/overview_of_the_new_cpp"> Overview of the New C++ (C++11/14)</a>
</li>
</ul>
</div>
</div>
<div id="outline-container-sec-8-2" class="outline-3">
<h3 id="sec-8-2">Online resources</h3>
<div class="outline-text-3" id="text-8-2">
<ul class="org-ul">
<li>Scott Meyers 的<a href="http://www.aristeia.com/C++11/C++11FeatureAvailability.htm">Summary of C++11 Feature Availability in gcc and MSVC</a>
</li>
<li><a href="http://en.cppreference.com/w/cpp">C++11 on cppreference</a>
</li>
<li><a href="http://www.cplusplus.com/reference/multithreading/">C++11 on cplusplus</a>
</li>
<li>Bjarne Stroustrup 的<a href="http://www.stroustrup.com/C++11FAQ.html">C++11 FAQ</a>
</li>
<li><a href="https://en.wikipedia.org/wiki/C++11">C++11 Wiki</a>
</li>
<li><a href="https://github.com/cplusplus/draft">C++ standards drafts on GitHub</a>
</li>
<li><a href="http://en.cppreference.com/w/c/thread">C documentation</a> for Thread support library
</li>
</ul>
</div>
</div>
</div>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[浅谈C++ Multithreading Programming]]></title>
    <link href="http://dreamrunner.org/blog/2014/08/07/C-multithreading-programming/"/>
    <updated>2014-08-07T00:00:00+08:00</updated>
    <id>http://dreamrunner.org/blog/2014/08/07/C-multithreading-programming</id>
    <content type="html"><![CDATA[<div id="outline-container-sec-1" class="outline-2">
<h2 id="sec-1">Overview</h2>
<div class="outline-text-2" id="text-1">
<p>
随着多核 CPU 随处可见,多线程(multithreading)可以被用来实现并行,提高 CPU 的利用率和性能显著的提高.掌握多线程编程也成为现代实现软件的基本要求技能之一.<a href="https://computing.llnl.gov/tutorials/parallel_comp/">Introduction to Parallel Computing</a>详细的介绍了 Parallel Computing;
为什么使用它;Parallel Computing 的分类;Parallel Computing 的 limits 和
costs; Parallel Computing 的程序模型;如何设计 Parallel 程序等.
</p>

<p>
这里先介绍多线程的概念,多线程中涉及的基本概念,然后用实例介绍 Pthread 库的使用,并介绍 Google Code 中如何把它封装成 C++类,最后介绍可移植并大量使用的
<a href="http://www.boost.org/doc/libs/1_55_0/doc/html/thread.html">Boost Thread 库</a>.
</p>

<p>
还有一些其他的 Thread 库:
</p>
<ul class="org-ul">
<li><a href="http://openmp.org/wp/">OpenMP</a> 是一个可移植的接口,在共享内存的多处理器上实现 fork-join 并行.
OpenMP 的 tutorial:<a href="https://computing.llnl.gov/tutorials/openMP/">这里</a> 和 <a href="http://vergil.chemistry.gatech.edu/resources/programming/OpenMP.pdf">这里</a>,
</li>
<li><a href="http://omniorb.sourceforge.net/omni42/omnithread.html">OMNI Thread</a>为 C++提供 Thread 操作的.
</li>
<li><a href="http://en.wikipedia.org/wiki/List_of_C%2B%2B_multi-threading_libraries">其他 multithreading libraries</a>.
</li>
</ul>

<!-- more -->
</div>
</div>
<div id="outline-container-sec-2" class="outline-2">
<h2 id="sec-2">Thread</h2>
<div class="outline-text-2" id="text-2">
</div><div id="outline-container-sec-2-1" class="outline-3">
<h3 id="sec-2-1">定义</h3>
<div class="outline-text-3" id="text-2-1">
<p>
A <b>thread</b> is defined as an independent stream of instructions that can
be scheduled to run as such by the operating system.所以它是在程序中独立于其他代码可由操作系统调度的一段指令.
</p>

<p>
那么是操作系统是如何具体实现这一独立性呢?
</p>

<p>
要理解 thread,必须先明白 process.进程由操作系统创建来运行相应的程序,进程包含程序资源和程序执行状态的信息.以 Linux 的进程为例包含:
</p>
<ul class="org-ul">
<li>Process ID, process group ID, user ID, and group ID
</li>
<li>Environment
</li>
<li>Working directory
</li>
<li>Program instructions
</li>
<li>Registers
</li>
<li>Stack
</li>
<li>Heap
</li>
<li>File descriptors
</li>
<li>Signal actions
</li>
<li>Shared libraries
</li>
<li>Inter-process communication tools (such as message queues, pipes,
semaphores, or shared memory).
</li>
</ul>

<img class="center" src="http://dreamrunner.org/images/blog/2014/c++_multithreaing/process_thread.png" />

<p>
Thread 使用 Process 的资源,并且能成为独立的元件被操作系统调度,是因为它仅重复那些使得它们能成为独立运行代码的必要资源.Thread 维护它自己如下的信息:
</p>
<ul class="org-ul">
<li>Stack pointer
</li>
<li>Registers
</li>
<li>Scheduling properties (such as policy or priority)
</li>
<li>Set of pending and blocked signals
</li>
<li>Thread specific data.
</li>
</ul>

<p>
与 Process 比较,Thread 可以总结如下:
</p>
<ul class="org-ul">
<li>Thread 相当于一个 lightweight 的 Process,拥有如 ID,properties 等相似信息,
但仅仅包含能使得它独立运行的信息即可.
</li>
<li>信息包含的不同,与需要复制大量信息来创建 Process 比,Thread 的创建比较快捷.
</li>
<li>独立的 Processes 不共享任何信息.每个 Process 运行在独立的地址空间.Threads 共享所在 Process 的资源,全局变量和文件描述符.
</li>
<li>Threads 可以直接与所在同一 Process 的 Threads 通信.而 Processes 必须使用
inter-process communication(IPC)来通信.
</li>
<li>因为 Threads 的资源共享性,增加并行操作资源的难度,需要引入 Thread 同步机制来达到资源并行性.
</li>
</ul>
</div>
</div>
<div id="outline-container-sec-2-2" class="outline-3">
<h3 id="sec-2-2">一些术语</h3>
<div class="outline-text-3" id="text-2-2">
<p>
Posix Thread 基本模型如下图,一些有关其中 Thread 的术语:
</p>

<img class="center" src="http://dreamrunner.org/images/blog/2014/c++_multithreaing/threads_model.png" />

<ul class="org-ul">
<li><b>Lightweight Process(LWP)</b> 可以被认为虚拟的 CPU,在系统中通常 LWP 的个数大于实际 CPU 个数.Thread 库通过与 LWP 沟通来调度 thread.LWP 也通常被称为
kernel threads.
</li>
<li><b><a href="http://en.wikipedia.org/wiki/System_Contention_Scope">Contention Scope</a></b> 是如何决定哪个线程得到调度.
</li>
<li><b>Bound threads</b> 拥有系统级别的 Contention Scope,也就是,它们与其他进程一同竞争.
</li>
<li><b>Unbound threads</b> 拥有进程级别的 Contention Scope.
</li>
<li><b>Thread-safe</b> 意味共享数据被得到保护,可以同时被多个 thread 调用而安全.
</li>
<li><b>Reentrant code</b> 意味程序可以被多个 thread 并行运行.
</li>
<li><b><a href="https://www.securecoding.cert.org/confluence/display/seccode/BB.+Definitions">asynchronous-safe function</a></b> 在 signal handler 下被安全调用并没有任何副作用.
</li>
<li><b>Concurrency vs. Parallelism</b> 并不一样.Parallelism 意味同时运行代码.而
Concurrency 意味许多任务可以以任何顺序执行或可以是并行运行.
</li>
</ul>
</div>
</div>
<div id="outline-container-sec-2-3" class="outline-3">
<h3 id="sec-2-3">Amdahl 法则和 Pareto 原则</h3>
<div class="outline-text-3" id="text-2-3">
<p>
Threads 能提供益处 <i>对于相适</i> 的应用.所以 thread 的并行性对于应用来说也有它的限制.
</p>
</div>

<div id="outline-container-sec-2-3-1" class="outline-4">
<h4 id="sec-2-3-1">Amdahl 法则</h4>
<div class="outline-text-4" id="text-2-3-1">
<p>
<a href="http://en.wikipedia.org/wiki/Amdahl%27s_law">Amdahl 法则</a> 陈述到潜在的程序加速由能被并行的代码率 P 定义为:
</p>

$$
\begin{align}
speedup = \dfrac{1}{1-P}
\end{align}
$$

<ul class="org-ul">
<li>如果代码中没有能并行的部分,P=0,那么 speedup=1.
</li>
<li>如果所有代码都能并行,P=1,那么 speedup 能达到无限(理论上).
</li>
<li>如果 50%的代码能并行,那么最大的 speedup=2,也就是最多 2 倍的加速.
</li>
</ul>

<p>
引入能并行的处理器个数,那么进一步可以定义为:
</p>

$$
\begin{align}
speedup = \dfrac{1}{\dfrac{P}{N} + (1-P)}
其中 P 并行率,N 处理器个数
\end{align}
$$

<img class="center" src="http://dreamrunner.org/images/blog/2014/c++_multithreaing/amdahl1.gif" />

<img class="center" src="http://dreamrunner.org/images/blog/2014/c++_multithreaing/amdahl2.gif" />
</div>
</div>

<div id="outline-container-sec-2-3-2" class="outline-4">
<h4 id="sec-2-3-2">Pareto 原则</h4>
<div class="outline-text-4" id="text-2-3-2">
<p>
<a href="http://en.wikipedia.org/wiki/Pareto_principle">Pareto 原则</a> 陈述到 80%的处理器时间花在 20%的代码中.所以仔细分析代码,不要把时间花在并行/优化那部分不重要的代码.
</p>
</div>
</div>
</div>
</div>
<div id="outline-container-sec-3" class="outline-2">
<h2 id="sec-3">Thread 设计模式<sup><a id="fnr.1" name="fnr.1" class="footref" href="#fn.1">1</a></sup></h2>
<div class="outline-text-2" id="text-3">
<p>
在程序中有不同的方法使用线程,这里讨论 3 种线程设计模式,没有哪一种模式最好,每种模式都有相应适合的应用场合.
</p>
</div>

<div id="outline-container-sec-3-1" class="outline-3">
<h3 id="sec-3-1">Boss/worker(Thread pool)</h3>
<div class="outline-text-3" id="text-3-1">
<img class="center" src="http://dreamrunner.org/images/blog/2014/c++_multithreaing/boss_workers_pattern.gif" />

<p>
如上图,一个 Boss 线程创建其他 Worker 线程,并给它们分配任务,必要的话,并等待其他线程运行结束.通常 Boss 线程会在初始建立 Thread Pool 来为之后分配.尽管线程是轻量级的,但是创建它们仍是有开销的.
</p>
</div>
</div>
<div id="outline-container-sec-3-2" class="outline-3">
<h3 id="sec-3-2">Peer(Workcrew)</h3>
<div class="outline-text-3" id="text-3-2">
<img class="center" src="http://dreamrunner.org/images/blog/2014/c++_multithreaing/peer_pattern.gif" />

<p>
Peer 模式又叫做 workcrew 模式,一个 thread 创建其他 peer threads 当程序开始,但是如上图,与 Boss/worker 模式不同,这个 thread 之后也变成 peer thread 去处理自己的任务.
</p>
</div>
</div>
<div id="outline-container-sec-3-3" class="outline-3">
<h3 id="sec-3-3">Pipeline</h3>
<div class="outline-text-3" id="text-3-3">
<img class="center" src="http://dreamrunner.org/images/blog/2014/c++_multithreaing/pipeline_pattern.gif" />

<p>
Pipeline 模式假定:
</p>
<ul class="org-ul">
<li>一串连续长输入.
</li>
<li>每个输入经过一连串的子操作(熟知为 stages 或 fliers).
</li>
<li>每个处理 stage 能一次处理个不同的输入.
</li>
</ul>

<p>
如上图, Pipeline 就像流水线一般,每个 thread 是一个长链中的一部分.每个
thread 处理由之前 thread 过的数据.
</p>
</div>
</div>
</div>
<div id="outline-container-sec-4" class="outline-2">
<h2 id="sec-4">线程同步原语</h2>
<div class="outline-text-2" id="text-4">
<p>
如上线程中的定义,线程们共享进程中的全局变量或资源,它们可以并行同时对这些数据和资源操作,如果没有一定的机制协调它们,那么数据或资源将处于一个不安全状态,引起诸如如下的一些问题:
</p>

<ul class="org-ul">
<li><a href="http://en.wikipedia.org/wiki/Race_condition#Software">Race condition</a>发生于不能决定行为的结果因为线程们操作共享数据或资源没有遵循一定的同步规则.
</li>
<li><a href="http://en.wikipedia.org/wiki/ABA_problem">ABA problem</a>发生于一个地方被读取两次,都读到相同的值,&#8217;值是相同的&#8217;被用来说明&#8217;没有东西被改变&#8217;.但是,另外一个线程能在这两次读取中间执行操作并修改这个位置的值,然后做一些其他操作,最后把这个值改回去,以致愚弄第一个线程让它认为&#8217;没有东西被改变&#8217;,即使第二个线程的操作已经破坏了这个假设.
</li>
</ul>

<p>
所以我们需要如下的一些线程同步原语满足不同的线程间同步需求.
</p>
</div>

<div id="outline-container-sec-4-1" class="outline-3">
<h3 id="sec-4-1">Mutex</h3>
<div class="outline-text-3" id="text-4-1">
<p>
<a href="http://en.wikipedia.org/wiki/Lock_%28computer_science%29">Mutex</a> 又被称为 Lock,所以它就像一把 Lock,一个线程 Lock 住一段资源,那么其他线程就不能去访问那段资源,只有等到第一个线程 Unlock 那么资源,它才能访问.
</p>

<p>
在 Lock 和 Unlock 之间的代码,一般被称为 <b>critical section</b>.
</p>

<p>
Mutex 也包含一些复杂的类型,如下:
</p>
<ul class="org-ul">
<li>Recursive: 允许占有锁的那一个线程再次获取同样的锁,对递归算法是必要的.
</li>
<li>Queuing: 使得 <b>公平</b> 的获取锁,通过 FIFO 排序锁的请求.
</li>
<li>Reader/Writer(rwlock): 允许多个 reader 同时获取锁,如果有 reader 占用锁,writer 只有等到 reader 释放锁.
</li>
<li>Scoped: <a href="http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization">RAII</a> 类型定义的锁获取和解锁.
</li>
</ul>

<p>
但 Mutex 也会引入其他一些问题,如<a href="http://en.wikipedia.org/wiki/Deadlock">deadlock</a> 和 <a href="http://en.wikipedia.org/wiki/Priority_inversion">priority inversion</a>.
</p>

<p>
在 Blog 中之前<a href="http://dreamrunner.org/blog/2014/06/29/qian-tan-mutex-lock/">浅谈 Mutex (Lock)</a>中可以看到更多有关 Mutex 的性能和开销分析,并如何实现一个轻量级的 Mutex.
</p>
</div>
</div>
<div id="outline-container-sec-4-2" class="outline-3">
<h3 id="sec-4-2">Join</h3>
<div class="outline-text-3" id="text-4-2">
<p>
线程 join 机制能让一个线程 join 到另外一个线程中.比如一个子线程 join 回主线程,那么主线程就会等待子线程运行结束.从而达到线程间等待的同步机制.
</p>
</div>
</div>
<div id="outline-container-sec-4-3" class="outline-3">
<h3 id="sec-4-3">Condition Variable</h3>
<div class="outline-text-3" id="text-4-3">
<p>
Condition variable 允许线程同步到某个共享资源的某个值.
</p>

<p>
比如,程序有一个计数器,当计数器达到某一个值时去激活某个线程运行.把计数器当成一个 Condition variable.这个线程可以等待这个 Condition variable,其他 active 线程操作完这个 Condition variable,可以通过 signal/broadcast 去唤醒那些等待这个 Condition variable 睡眠的线程.
</p>
</div>
</div>
<div id="outline-container-sec-4-4" class="outline-3">
<h3 id="sec-4-4">Barrier</h3>
<div class="outline-text-3" id="text-4-4">
<p>
Barrier 是一种能让一系列线程在某个点得到同步的方法,通过让参与 barrier 的线程等待直到所有参与线程都调用了这个 barrier 函数.本质上就是,阻塞所有参与 barrier 的线程直到最慢的那个参与线程调用 barrier.
</p>
</div>
</div>

<div id="outline-container-sec-4-5" class="outline-3">
<h3 id="sec-4-5">Spinlock</h3>
<div class="outline-text-3" id="text-4-5">
<p>
Spinlock 与 mutex 类似,是种锁,但当获取锁失败时,spinlock 不会让线程进入睡眠,而是不断 poll 去获取这个锁直到获取成功.更多<a href="http://dreamrunner.org/blog/2014/06/29/qian-tan-mutex-lock/#mutex-vs-spinlock">Mutex 与 Spinlock 的区别</a>.
</p>
</div>
</div>
<div id="outline-container-sec-4-6" class="outline-3">
<h3 id="sec-4-6">Semaphore</h3>
<div class="outline-text-3" id="text-4-6">
<p>
当某些资源具有多个时,简单的 Mutex 不能满足,引入 Semphore,Semphore 可以根据资源个数初始化为任意值.当线程们占有所有资源,使得 Semphore 为 0,那么其他线程再获取资源只有等待.当 Semphore 值只能是 1 或 0 时,它相当于简单的 Mutex.
</p>
</div>
</div>
</div>
<div id="outline-container-sec-5" class="outline-2">
<h2 id="sec-5">Pthread</h2>
<div class="outline-text-2" id="text-5">
</div><div id="outline-container-sec-5-1" class="outline-3">
<h3 id="sec-5-1">Overview</h3>
<div class="outline-text-3" id="text-5-1">
<p>
原始的 Pthread API 由 ANSI/IEEE POSIX 1003.1 - 1995 standard 定义.POSIX 标准也随着时间不断改进.
</p>

<p>
接下来主要把 Pthread API 分成如下主要 5 部分:
</p>
<ol class="org-ol">
<li>Thread Management
</li>
<li>Mutex Variables
</li>
<li>Condition Variables
</li>
<li>Synchronization
</li>
<li>Miscellaneous
</li>
</ol>

<p>
如果想把 Pthread 封装成类对象或 Scoped Lock,可以参考之后
<a href="#google-wrap">Google wrap the Pthread</a>,或直接使用之后介绍的<a href="#boost-thread">Boost thread library</a>.
</p>

<p>
如果更全面的 API 参考文章最后的<a href="#pthread-library">Pthread Library Routines Reference</a>.更多有关资料参考文章后的<i>其他资料</i>.
</p>
</div>
<div id="outline-container-sec-5-1-1" class="outline-4">
<h4 id="sec-5-1-1">编译 Pthread 程序</h4>
<div class="outline-text-4" id="text-5-1-1">
</div><div id="outline-container-sec-5-1-1-1" class="outline-5">
<h5 id="sec-5-1-1-1">include</h5>
<div class="outline-text-5" id="text-5-1-1-1">
<p>
对于 POSIX 系统,包含头文件 <code>pthread.h</code>. 如果使用 <code>semaphore</code>, 包含
<code>semaphore.h</code>.
</p>

<div class="org-src-container">

<pre class="src src-c"><span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;pthread.h&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;semaphore.h&gt;</span>
</pre>
</div>
</div>
</div>

<div id="outline-container-sec-5-1-1-2" class="outline-5">
<h5 id="sec-5-1-1-2">compile</h5>
<div class="outline-text-5" id="text-5-1-1-2">
<p>
对于 Gcc 编译器,使用选项 <code>-l</code>,如下:
</p>
<div class="org-src-container">

<pre class="src src-sh">gcc Program.o -o Program -lpthread
</pre>
</div>
</div>
</div>
</div>
</div>
<div id="outline-container-sec-5-2" class="outline-3">
<h3 id="sec-5-2">Thread Management</h3>
<div class="outline-text-3" id="text-5-2">
</div><div id="outline-container-sec-5-2-1" class="outline-4">
<h4 id="sec-5-2-1">Creating and Terminating Threads</h4>
<div class="outline-text-4" id="text-5-2-1">
</div><div id="outline-container-sec-5-2-1-1" class="outline-5">
<h5 id="sec-5-2-1-1">APIs</h5>
<div class="outline-text-5" id="text-5-2-1-1">
<div class="org-src-container">

<pre class="src src-c"><span style="color: #98fb98;">int</span> <span style="color: #87cefa;">pthread_create</span>(<span style="color: #98fb98;">pthread_t</span> *<span style="color: #eedd82;">thread</span>,
              <span style="color: #00ffff;">const</span> <span style="color: #98fb98;">pthread_attr_t</span> *<span style="color: #eedd82;">attr</span>,
              <span style="color: #98fb98;">void</span> *(*<span style="color: #eedd82;">start_routine</span>)(<span style="color: #98fb98;">void</span>*), <span style="color: #98fb98;">void</span> *<span style="color: #eedd82;">arg</span>);
<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">pthread_exit</span>(<span style="color: #98fb98;">void</span> *<span style="color: #eedd82;">value_ptr</span>);
<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">pthread_cancel</span>(<span style="color: #98fb98;">pthread_t</span> <span style="color: #eedd82;">thread</span>);
<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">pthread_attr_init</span>(<span style="color: #98fb98;">pthread_attr_t</span> *<span style="color: #eedd82;">attr</span>);
<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">pthread_attr_destroy</span>(<span style="color: #98fb98;">pthread_attr_t</span> *<span style="color: #eedd82;">attr</span>);
</pre>
</div>
</div>
</div>

<div id="outline-container-sec-5-2-1-2" class="outline-5">
<h5 id="sec-5-2-1-2">Creating Threads</h5>
<div class="outline-text-5" id="text-5-2-1-2">
<p>
<code>pthread_create</code> 创建一个新的线程并运行它.它能在代码的任何处被多次调用.
</p>

<p>
<code>pthread_create</code> 的参数:
</p>
<ul class="org-ul">
<li><code>thread</code>:返回新 thread 程的唯一标识.
</li>
<li><code>attr</code>:设置 thread 的性质.NULL 为默认性质.
</li>
<li><code>start_routine</code>: 新 thread 运行的函数指针.
</li>
<li><code>arg</code>:传给 <code>start_routine</code> 的参数,必须强制转换成 <code>void *</code>.NULL 为没有参数传入.
</li>
</ul>

<p>
Process 能创建的最大 thread 个数由系统配置决定.如下 Ubuntu 打印出的结果:
</p>
<div class="org-src-container">

<pre class="src src-sh">$ limit
cputime         unlimited
filesize        unlimited
datasize        unlimited
stacksize       8MB
coredumpsize    0kB
memoryuse       unlimited
maxproc         62694
descriptors     1024
memorylocked    64kB
addressspace    unlimited
maxfilelocks    unlimited
sigpending      62694
msgqueue        819200
nice            0
rt_priority     0
rt_time         unlimited
</pre>
</div>
</div>
</div>

<div id="outline-container-sec-5-2-1-3" class="outline-5">
<h5 id="sec-5-2-1-3">Thread Attributes</h5>
<div class="outline-text-5" id="text-5-2-1-3">
<p>
<code>pthread_attr_init</code> 和 <code>pthread_attr_destroy</code> 被用来初始化/销毁 thread
性质对象.
</p>

<p>
性质包括:
</p>
<ul class="org-ul">
<li>Detached or joinable state
</li>
<li>Scheduling inheritance
</li>
<li>Scheduling policy
</li>
<li>Scheduling parameters
</li>
<li>Scheduling contention scope
</li>
<li>Stack size
</li>
<li>Stack address
</li>
<li>Stack guard (overflow) size
</li>
</ul>
</div>
</div>

<div id="outline-container-sec-5-2-1-4" class="outline-5">
<h5 id="sec-5-2-1-4">Thread Binding</h5>
<div class="outline-text-5" id="text-5-2-1-4">
<p>
Pthread APIs 并没有提供 binding threads 到特定 cpus/cores 的接口.但不同系统可能包含这功能,比如提供非标准的<a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_setaffinity_np.txt"><code>pthread_setaffinity_np</code> </a> 接口.
</p>

<p>
比如设置两个线程都在 core0 上运行,如下设置:
</p>
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #98fb98;">cpu_set_t</span> <span style="color: #eedd82;">cpus</span>;
CPU_ZERO(&amp;cpus);
CPU_SET(0, &amp;cpus);
pthread_setaffinity_np(thread[0], <span style="color: #00ffff;">sizeof</span>(cpu_set_t), &amp;cpus);
pthread_setaffinity_np(thread[1], <span style="color: #00ffff;">sizeof</span>(cpu_set_t), &amp;cpus);
</pre>
</div>
</div>
</div>

<div id="outline-container-sec-5-2-1-5" class="outline-5">
<h5 id="sec-5-2-1-5">Terminating Threads</h5>
<div class="outline-text-5" id="text-5-2-1-5">
<p>
一个线程有很多种方法终止:
</p>
<ul class="org-ul">
<li>线程从它的运行中正常放回.它的工作完成.
</li>
<li>线程调用 <code>pthread_exit</code> 无论它的工作完成否.
</li>
<li>线程被另外一个线程调用 <code>pthread_cancel</code> 来取消.
</li>
<li>整个线程终止因为调用 <code>exec()</code> 或 <code>exit()</code>.
</li>
<li><code>main()</code> 函数先完成,没有调用 <code>pthread_exit</code>.
</li>
</ul>

<p>
<code>pthread_exit()</code> 允许指定一个可选的终止 <code>status parameter</code>.这个可选参数一般返回给线程&#8221;joining&#8221;到这个终止线程.
</p>

<p>
<code>pthread_exit()</code> 不关闭文件,在线程打开的任何文件将继续打开在线程终止后.
</p>

<p>
在 <code>main()</code> 调用 <code>pthread_exit()</code> :
</p>
<ul class="org-ul">
<li>如果 <code>main()</code> 在它创建的 threads 之前终止,并没有显示的调用
<code>pthread_exit()</code>,这将是个问题.所有创建的线程将终止因为 main()结束,不再存在支持这些线程.
</li>
<li>通过 main()在最后调用 <code>pthread_exit()</code>, main()将阻塞并保持存活来支持它创建的线程运行直到它们完成.
</li>
</ul>
</div>
</div>
<div id="outline-container-sec-5-2-1-6" class="outline-5">
<h5 id="sec-5-2-1-6">Example: Pthread Creation and Termination</h5>
<div class="outline-text-5" id="text-5-2-1-6">
<p>
如果注释掉 main()中最后的 <code>pthread_exit(NULL);</code> ,那么它创建的线程将会完成不了所有的打印而被强制退出.
</p>

<div class="org-src-container">

<pre class="src src-c++"><span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;pthread.h&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;cstdio&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;cstdlib&gt;</span>

<span style="color: #98fb98;">void</span> *<span style="color: #87cefa;">ThreadProc</span>(<span style="color: #98fb98;">void</span> *<span style="color: #eedd82;">param</span>) {
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">id</span>;
  id = *(<span style="color: #00ffff;">static_cast</span>&lt;<span style="color: #98fb98;">int</span> *&gt;(param));
  <span style="color: #00ffff;">for</span> (<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span> = 0; i &lt; 10; ++i) {
    printf(<span style="color: #ffa07a;">"thread %d: run %d \n"</span>, id, i);
  }
  pthread_exit(<span style="color: #7fffd4;">NULL</span>);
}

<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">main</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">argc</span>, <span style="color: #98fb98;">char</span> *<span style="color: #eedd82;">argv</span>[]) {
  <span style="color: #00ffff;">const</span> <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">kNumThreads</span> = 4;
  <span style="color: #98fb98;">pthread_t</span> <span style="color: #eedd82;">threads</span>[kNumThreads];
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">thread_ids</span>[kNumThreads];
  <span style="color: #00ffff;">for</span> (<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span> = 0; i &lt; kNumThreads; ++i) {
    thread_ids[i] = i;
    <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">rt</span> = pthread_create(&amp;threads[i], <span style="color: #7fffd4;">NULL</span>, ThreadProc,
                            <span style="color: #00ffff;">static_cast</span>&lt;<span style="color: #98fb98;">void</span> *&gt;(&amp;thread_ids[i]));
    <span style="color: #00ffff;">if</span> (rt) {
      printf(<span style="color: #ffa07a;">"ERROR: pthread_create failed, rt=%d\n"</span>, rt);
      exit(1);
    }
  }
  pthread_exit(<span style="color: #7fffd4;">NULL</span>);
}
</pre>
</div>
</div>
</div>
</div>
<div id="outline-container-sec-5-2-2" class="outline-4">
<h4 id="sec-5-2-2">Joining and Detaching Threads</h4>
<div class="outline-text-4" id="text-5-2-2">
</div><div id="outline-container-sec-5-2-2-1" class="outline-5">
<h5 id="sec-5-2-2-1">APIs</h5>
<div class="outline-text-5" id="text-5-2-2-1">
<div class="org-src-container">

<pre class="src src-c"><span style="color: #98fb98;">int</span> <span style="color: #87cefa;">pthread_join</span>(<span style="color: #98fb98;">pthread_t</span> <span style="color: #eedd82;">thread</span>, <span style="color: #98fb98;">void</span> **<span style="color: #eedd82;">value_ptr</span>);
<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">pthread_detach</span>(<span style="color: #98fb98;">pthread_t</span> <span style="color: #eedd82;">thread</span>);
<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">pthread_attr_setdetachstate</span>(<span style="color: #98fb98;">pthread_attr_t</span> *<span style="color: #eedd82;">attr</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">detachstate</span>);
<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">pthread_attr_getdetachstate</span>(<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">pthread_attr_t</span> *<span style="color: #eedd82;">attr</span>,
              <span style="color: #98fb98;">int</span> *<span style="color: #eedd82;">detachstate</span>);
</pre>
</div>
</div>
</div>

<div id="outline-container-sec-5-2-2-2" class="outline-5">
<h5 id="sec-5-2-2-2">Joining</h5>
<div class="outline-text-5" id="text-5-2-2-2">
<p>
Joining 是同步不同线程的方法之一,原理如下图:
</p>

<img class="center" src="http://dreamrunner.org/images/blog/2014/c++_multithreaing/join.png" />

<ul class="org-ul">
<li><code>pthread_join()</code> 阻塞调用它的线程直到指定的 <code>threadid</code> 的线程终止.
</li>
<li>调用的线程能获取目标线程终止返回的 <code>status</code> 只要目标线程调用
  <code>pthread_exit()</code>.
</li>
<li>当一个线程被创建,它的属性之一是它是否可以 join.只有创建的能被 join 的线程才能被 join.如果线程线程以 detached 创建,它永远都不能被 join.
</li>
<li>显示的创建一个线程可 join 或 detached,使用在 <code>pthread_create()</code> 中的 <code>attr</code>
参数.典型的步骤是:
<ol class="org-ol">
<li>定义 <code>pthread_attr_t</code> 类型的 pthread 属性;
</li>
<li>用 <code>pthread_attr_init()</code> 初始化属性变量;
</li>
<li>用 <code>pthread_attr_setdetachstate()</code> 设置 detached 属性;
</li>
<li>用 <code>pthread_attr_destroy()</code> 释放属性使用的资源.
</li>
</ol>
</li>
</ul>
</div>
</div>

<div id="outline-container-sec-5-2-2-3" class="outline-5">
<h5 id="sec-5-2-2-3">Detaching</h5>
<div class="outline-text-5" id="text-5-2-2-3">
<ul class="org-ul">
<li><code>pthread_detach()</code> 能显示的 detach 一个线程即使它是以可 join 创建.
</li>
<li>没有相反的操作.
</li>
</ul>
</div>
</div>

<div id="outline-container-sec-5-2-2-4" class="outline-5">
<h5 id="sec-5-2-2-4">Example: Pthread Joining</h5>
<div class="outline-text-5" id="text-5-2-2-4">
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;pthread.h&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;cstdio&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;cstdlib&gt;</span>

<span style="color: #98fb98;">void</span> *<span style="color: #87cefa;">ThreadProc</span>(<span style="color: #98fb98;">void</span> *<span style="color: #eedd82;">param</span>) {
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">id</span>;
  id = *(<span style="color: #00ffff;">static_cast</span>&lt;<span style="color: #98fb98;">int</span> *&gt;(param));
  <span style="color: #00ffff;">for</span> (<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span> = 0; i &lt; 10; ++i) {
    printf(<span style="color: #ffa07a;">"thread %d: run %d \n"</span>, id, i);
  }
  pthread_exit(param);
}

<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">main</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">argc</span>, <span style="color: #98fb98;">char</span> *<span style="color: #eedd82;">argv</span>[]) {
  <span style="color: #00ffff;">const</span> <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">kNumThreads</span> = 4;
  <span style="color: #98fb98;">pthread_t</span> <span style="color: #eedd82;">threads</span>[kNumThreads];
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">thread_ids</span>[kNumThreads];
  <span style="color: #98fb98;">pthread_attr_t</span> <span style="color: #eedd82;">attr</span>;

  pthread_attr_init(&amp;attr);
  pthread_attr_setdetachstate(&amp;attr, PTHREAD_CREATE_JOINABLE);

  <span style="color: #00ffff;">for</span> (<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span> = 0; i &lt; kNumThreads; ++i) {
    thread_ids[i] = i;
    <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">rt</span> = pthread_create(&amp;threads[i], &amp;attr, ThreadProc,
                            <span style="color: #00ffff;">static_cast</span>&lt;<span style="color: #98fb98;">void</span> *&gt;(&amp;thread_ids[i]));
    <span style="color: #00ffff;">if</span> (rt) {
      printf(<span style="color: #ffa07a;">"ERROR: pthread_create failed, rt=%d\n"</span>, rt);
      exit(1);
    }
  }
  <span style="color: #00ffff;">for</span> (<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span> = 0; i &lt; kNumThreads; ++i) {
    <span style="color: #98fb98;">void</span> *<span style="color: #eedd82;">status</span>;
    <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">rt</span> = pthread_join(threads[i], &amp;status);
    <span style="color: #00ffff;">if</span> (rt) {
      printf(<span style="color: #ffa07a;">"ERROR: pthread_join failed, rt=%d\n"</span>, rt);
      exit(1);
    }
    printf(<span style="color: #ffa07a;">"completed join with thread %d having a status of %d\n"</span>
           , i, *<span style="color: #00ffff;">static_cast</span>&lt;<span style="color: #98fb98;">int</span> *&gt;(status));
  }
  pthread_exit(<span style="color: #7fffd4;">NULL</span>);
}
</pre>
</div>
</div>
</div>
</div>
<div id="outline-container-sec-5-2-3" class="outline-4">
<h4 id="sec-5-2-3">Stack Management</h4>
<div class="outline-text-4" id="text-5-2-3">
</div><div id="outline-container-sec-5-2-3-1" class="outline-5">
<h5 id="sec-5-2-3-1">APIs</h5>
<div class="outline-text-5" id="text-5-2-3-1">
<div class="org-src-container">

<pre class="src src-c"><span style="color: #98fb98;">int</span> <span style="color: #87cefa;">pthread_attr_getstacksize</span>(<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">pthread_attr_t</span> *<span style="color: #00ffff;">restrict</span> <span style="color: #eedd82;">attr</span>,
              <span style="color: #98fb98;">size_t</span> *<span style="color: #00ffff;">restrict</span> <span style="color: #eedd82;">stacksize</span>);
<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">pthread_attr_setstacksize</span>(<span style="color: #98fb98;">pthread_attr_t</span> *<span style="color: #eedd82;">attr</span>, <span style="color: #98fb98;">size_t</span> <span style="color: #eedd82;">stacksize</span>);
<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">pthread_attr_getstackaddr</span>(<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">pthread_attr_t</span> *<span style="color: #00ffff;">restrict</span> <span style="color: #eedd82;">attr</span>,
              <span style="color: #98fb98;">void</span> **<span style="color: #00ffff;">restrict</span> <span style="color: #eedd82;">stackaddr</span>);
<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">pthread_attr_setstackaddr</span>(<span style="color: #98fb98;">pthread_attr_t</span> *<span style="color: #eedd82;">attr</span>, <span style="color: #98fb98;">void</span> *<span style="color: #eedd82;">stackaddr</span>);
</pre>
</div>

<p>
每个线程都有各自独立的 stack, <code>pthread_attr_getstackaddr</code> 和
<code>pthread_attr_setstackaddr</code> 分别获取和设置线程的 stack 属性.
</p>
</div>
</div>

<div id="outline-container-sec-5-2-3-2" class="outline-5">
<h5 id="sec-5-2-3-2">Example: Stack Management</h5>
<div class="outline-text-5" id="text-5-2-3-2">
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;pthread.h&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;cstdio&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;cstdlib&gt;</span>

<span style="color: #98fb98;">pthread_attr_t</span> <span style="color: #eedd82;">attr</span>;

<span style="color: #98fb98;">void</span> *<span style="color: #87cefa;">ThreadProc</span>(<span style="color: #98fb98;">void</span> *<span style="color: #eedd82;">param</span>) {
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">id</span>;
  <span style="color: #98fb98;">size_t</span> <span style="color: #eedd82;">thread_stack_size</span>;
  id = *(<span style="color: #00ffff;">static_cast</span>&lt;<span style="color: #98fb98;">int</span> *&gt;(param));
  pthread_attr_getstacksize(&amp;attr, &amp;thread_stack_size);
  printf(<span style="color: #ffa07a;">"thread %d: stack size = %d\n"</span>, id, thread_stack_size);
  <span style="color: #00ffff;">for</span> (<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span> = 0; i &lt; 10; ++i) {
    printf(<span style="color: #ffa07a;">"thread %d: run %d \n"</span>, id, i);
  }
  pthread_exit(<span style="color: #7fffd4;">NULL</span>);
}

<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">main</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">argc</span>, <span style="color: #98fb98;">char</span> *<span style="color: #eedd82;">argv</span>[]) {
  <span style="color: #00ffff;">const</span> <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">kNumThreads</span> = 4;
  <span style="color: #00ffff;">const</span> <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">kThround</span> = 1000;
  <span style="color: #98fb98;">pthread_t</span> <span style="color: #eedd82;">threads</span>[kNumThreads];
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">thread_ids</span>[kNumThreads];
  <span style="color: #98fb98;">size_t</span> <span style="color: #eedd82;">stack_size</span>;

  pthread_attr_init(&amp;attr);
  pthread_attr_getstacksize(&amp;attr, &amp;stack_size);
  printf(<span style="color: #ffa07a;">"Default stack size = %d\n"</span>, stack_size);
  stack_size = <span style="color: #00ffff;">sizeof</span>(<span style="color: #98fb98;">double</span>) * kThround * kThround;
  printf(<span style="color: #ffa07a;">"Setting stack size = %d\n"</span>, stack_size);
  pthread_attr_setstacksize(&amp;attr, stack_size);
  <span style="color: #00ffff;">for</span> (<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span> = 0; i &lt; kNumThreads; ++i) {
    thread_ids[i] = i;
    <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">rt</span> = pthread_create(&amp;threads[i], &amp;attr, ThreadProc,
                            <span style="color: #00ffff;">static_cast</span>&lt;<span style="color: #98fb98;">void</span> *&gt;(&amp;thread_ids[i]));
    <span style="color: #00ffff;">if</span> (rt) {
      printf(<span style="color: #ffa07a;">"ERROR: pthread_create failed, rt=%d\n"</span>, rt);
      exit(1);
    }
  }
  pthread_exit(<span style="color: #7fffd4;">NULL</span>);
  pthread_attr_destroy(&amp;attr);
  <span style="color: #00ffff;">return</span> 0;
}
</pre>
</div>
</div>
</div>
</div>

<div id="outline-container-sec-5-2-4" class="outline-4">
<h4 id="sec-5-2-4">Miscellaneous</h4>
<div class="outline-text-4" id="text-5-2-4">
<div class="org-src-container">

<pre class="src src-c"><span style="color: #98fb98;">pthread_t</span> <span style="color: #87cefa;">pthread_self</span>(<span style="color: #98fb98;">void</span>);
<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">pthread_equal</span>(<span style="color: #98fb98;">pthread_t</span> <span style="color: #eedd82;">t1</span>, <span style="color: #98fb98;">pthread_t</span> <span style="color: #eedd82;">t2</span>);
<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">pthread_once</span>(<span style="color: #98fb98;">pthread_once_t</span> *<span style="color: #eedd82;">once_control</span>,
              <span style="color: #98fb98;">void</span> (*<span style="color: #eedd82;">init_routine</span>)(<span style="color: #98fb98;">void</span>));
<span style="color: #98fb98;">pthread_once_t</span> <span style="color: #eedd82;">once_control</span> = PTHREAD_ONCE_INIT;
</pre>
</div>

<ul class="org-ul">
<li><code>pthread_self</code> 返回调用线程的唯一 thread ID.
</li>
<li><code>pthread_equal</code> 比较两个线程 ID 是否相等.
</li>
<li><code>pthread_once</code> 只执行 <code>init_routine</code> 仅仅一次在进程中.
</li>
</ul>
</div>
</div>
</div>
<div id="outline-container-sec-5-3" class="outline-3">
<h3 id="sec-5-3">Mutex Variables</h3>
<div class="outline-text-3" id="text-5-3">
</div><div id="outline-container-sec-5-3-1" class="outline-4">
<h4 id="sec-5-3-1">Overview</h4>
<div class="outline-text-4" id="text-5-3-1">
<p>
Mutex 以&#8221;mutual exclusion&#8221;(互斥)简称.
</p>

<p>
Mutex variable 就像一把&#8221;锁&#8221;一样保护共享数据资源.mutex 的基本概念就是,只有一个线程能 lock 一个 mutex 变量在任何时候.所以,即使很多线程尝试去锁一个
mute,也仅仅只有一个线程能成功.
</p>

<p>
典型使用 mutex 的顺序如下:
</p>
<ol class="org-ol">
<li>创建和初始化 mutex 变量;
</li>
<li>许多线程尝试锁住 mutex;
</li>
<li>只有一个线程成功锁住 mutex,其他线程等待;
</li>
<li>拥有 mutex 的线程进行自己的操作;
</li>
<li>拥有线程解锁 mutex;
</li>
<li>其他线程继续获取 mutex 并持续如上步骤;
</li>
<li>最后 mutex 销毁.
</li>
</ol>
</div>
</div>
<div id="outline-container-sec-5-3-2" class="outline-4">
<h4 id="sec-5-3-2">Creating and Destroying Mutexes</h4>
<div class="outline-text-4" id="text-5-3-2">
<div class="org-src-container">

<pre class="src src-c"><span style="color: #98fb98;">int</span> <span style="color: #87cefa;">pthread_mutex_destroy</span>(<span style="color: #98fb98;">pthread_mutex_t</span> *<span style="color: #eedd82;">mutex</span>);
<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">pthread_mutex_init</span>(<span style="color: #98fb98;">pthread_mutex_t</span> *<span style="color: #00ffff;">restrict</span> <span style="color: #eedd82;">mutex</span>,
          <span style="color: #00ffff;">const</span> <span style="color: #98fb98;">pthread_mutexattr_t</span> *<span style="color: #00ffff;">restrict</span> <span style="color: #eedd82;">attr</span>);
<span style="color: #98fb98;">pthread_mutex_t</span> <span style="color: #eedd82;">mutex</span> = PTHREAD_MUTEX_INITIALIZER;
<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">pthread_mutexattr_destroy</span>(<span style="color: #98fb98;">pthread_mutexattr_t</span> *<span style="color: #eedd82;">attr</span>);
<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">pthread_mutexattr_init</span>(<span style="color: #98fb98;">pthread_mutexattr_t</span> *<span style="color: #eedd82;">attr</span>);
</pre>
</div>

<p>
Mutex 变量由 <code>pthread_mutex_t</code> 声明定义,而且必须初始化在使用前.两种方法初始:
</p>
<ol class="org-ol">
<li>静态的,当声明时.如:
</li>
</ol>
<div class="org-src-container">

<pre class="src src-c"><span style="color: #98fb98;">pthread_mutex_t</span> <span style="color: #eedd82;">mutex</span> = PTHREAD_MUTEX_INITIALIZER;
</pre>
</div>
<ol class="org-ol">
<li>动态的,使用 <code>pthread_mutex_init()</code> 函数,并能设置 mutex 的属性 <code>attr</code>.
</li>
</ol>

<p>
<code>attr</code> 用来设置 mutex 变量的属性,必须是 <code>pthread_mutexattr_t</code> 类型.Pthread 标准中定义的 3 种可选 mutex 属性:
</p>

<ul class="org-ul">
<li>Protocol: Specifies the protocol used to prevent priority inversions
for a mutex.
</li>
<li>Prioceiling: Specifies the priority ceiling of a mutex.
</li>
<li>Process-shared: Specifies the process sharing of a mutex.(Pthread
mutex 能被 process 间使用).
</li>
</ul>
</div>
</div>
<div id="outline-container-sec-5-3-3" class="outline-4">
<h4 id="sec-5-3-3">Locking and Unlocking Mutexes</h4>
<div class="outline-text-4" id="text-5-3-3">
<div class="org-src-container">

<pre class="src src-c"><span style="color: #98fb98;">int</span> <span style="color: #87cefa;">pthread_mutex_lock</span>(<span style="color: #98fb98;">pthread_mutex_t</span> *<span style="color: #eedd82;">mutex</span>);
<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">pthread_mutex_trylock</span>(<span style="color: #98fb98;">pthread_mutex_t</span> *<span style="color: #eedd82;">mutex</span>);
<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">pthread_mutex_unlock</span>(<span style="color: #98fb98;">pthread_mutex_t</span> *<span style="color: #eedd82;">mutex</span>);
</pre>
</div>

<p>
<code>pthread_mutex_lock()</code> 函数被用来获取传入的 mutex 变量,如果 mutex 已经被其他线程占用,那么这个调用就阻塞调用线程,使它进入睡眠等待这个 mutex 直到它被释放.
</p>

<p>
<code>pthread_mutex_trylock()</code> 仅尝试获取锁,若不成功也立即返回&#8217;busy&#8217;信号.
</p>
</div>
</div>
<div id="outline-container-sec-5-3-4" class="outline-4">
<h4 id="sec-5-3-4">Example: Using Mutexes</h4>
<div class="outline-text-4" id="text-5-3-4">
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;pthread.h&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;cstdio&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;cstdlib&gt;</span>

<span style="color: #00ffff;">struct</span> <span style="color: #98fb98;">ThreadData</span> {
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">tid</span>;
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">data</span>;
};

<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">shared_x</span>;
<span style="color: #98fb98;">pthread_mutex_t</span> <span style="color: #eedd82;">lock</span>;

<span style="color: #98fb98;">void</span> *<span style="color: #87cefa;">ThreadProc</span>(<span style="color: #98fb98;">void</span> *<span style="color: #eedd82;">param</span>) {
  <span style="color: #98fb98;">ThreadData</span> *<span style="color: #eedd82;">data</span> = <span style="color: #00ffff;">static_cast</span>&lt;ThreadData *&gt;(param);
  printf(<span style="color: #ffa07a;">"begin from thread id: %d\n"</span>, data-&gt;tid);
  pthread_mutex_lock(&amp;lock);
  shared_x += data-&gt;data;
  printf(<span style="color: #ffa07a;">"thread %d: x = %d\n"</span>, data-&gt;tid, shared_x);
  pthread_mutex_unlock(&amp;lock);
  pthread_exit(<span style="color: #7fffd4;">NULL</span>);
}

<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">main</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">argc</span>, <span style="color: #98fb98;">char</span> *<span style="color: #eedd82;">argv</span>[]) {
  <span style="color: #00ffff;">const</span> <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">kNumThreads</span> = 4;
  <span style="color: #98fb98;">pthread_t</span> <span style="color: #eedd82;">threads</span>[kNumThreads];
  <span style="color: #98fb98;">ThreadData</span> <span style="color: #eedd82;">threads_data</span>[kNumThreads];
  <span style="color: #98fb98;">pthread_attr_t</span> <span style="color: #eedd82;">attr</span>;

  shared_x = 0;
  pthread_mutex_init(&amp;lock, <span style="color: #7fffd4;">NULL</span>);
  pthread_attr_init(&amp;attr);
  pthread_attr_setdetachstate(&amp;attr, PTHREAD_CREATE_JOINABLE);
  <span style="color: #00ffff;">for</span> (<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span> = 0; i &lt; kNumThreads; ++i) {
    threads_data[i].tid = i;
    threads_data[i].data = i * i;
    <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">rt</span> = pthread_create(&amp;threads[i], &amp;attr, ThreadProc,
                            <span style="color: #00ffff;">static_cast</span>&lt;<span style="color: #98fb98;">void</span> *&gt;(&amp;threads_data[i]));
    <span style="color: #00ffff;">if</span> (rt) {
      printf(<span style="color: #ffa07a;">"ERROR: pthread_create failed, rt=%d\n"</span>, rt);
      exit(1);
    }
  }
  <span style="color: #00ffff;">for</span> (<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span> = 0; i &lt; kNumThreads; ++i) {
    <span style="color: #98fb98;">void</span> *<span style="color: #eedd82;">status</span>;
    pthread_join(threads[i], &amp;status);
  }
  pthread_attr_destroy(&amp;attr);
  pthread_exit(<span style="color: #7fffd4;">NULL</span>);
  <span style="color: #00ffff;">return</span> 0;
}
</pre>
</div>
</div>
</div>
</div>

<div id="outline-container-sec-5-4" class="outline-3">
<h3 id="sec-5-4">Condition Variables</h3>
<div class="outline-text-3" id="text-5-4">
</div><div id="outline-container-sec-5-4-1" class="outline-4">
<h4 id="sec-5-4-1">Overview</h4>
<div class="outline-text-4" id="text-5-4-1">
<p>
Mutex 变量如锁一般防止多个线程访问共享数据资源,如果某个线程等待某个共享数据达到某个数值才进行相应的操作,那么这个线程需要不断的去 poll,查看是否满足需要的值,这样开销很大,因为线程需要一直处于忙状态.
</p>

<p>
引入 Condition Variables 来完成这样的同步到某个实际数据值而不要不断 poll.
</p>

<p>
Condition 变量一般与 mutex 一起使用.锁住查看的共享数据资源.
</p>

<p>
使用 Condition 的一般步骤如下:
</p>
<ul class="org-ul">
<li>声明和定义需要同步的共享数据;
</li>
<li>声明和定义 condition 变量;
</li>
<li>声明和定义相对应的 mutex;
</li>
<li>创建线程使用 condition 变量同步.
</li>
</ul>
</div>
</div>
<div id="outline-container-sec-5-4-2" class="outline-4">
<h4 id="sec-5-4-2">Creating and Destroying Condition Variables</h4>
<div class="outline-text-4" id="text-5-4-2">
<div class="org-src-container">

<pre class="src src-c"><span style="color: #98fb98;">int</span> <span style="color: #87cefa;">pthread_cond_destroy</span>(<span style="color: #98fb98;">pthread_cond_t</span> *<span style="color: #eedd82;">cond</span>);
<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">pthread_cond_init</span>(<span style="color: #98fb98;">pthread_cond_t</span> *<span style="color: #00ffff;">restrict</span> <span style="color: #eedd82;">cond</span>,
                      <span style="color: #00ffff;">const</span> <span style="color: #98fb98;">pthread_condattr_t</span> *<span style="color: #00ffff;">restrict</span> <span style="color: #eedd82;">attr</span>);
<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">pthread_condattr_destroy</span>(<span style="color: #98fb98;">pthread_condattr_t</span> *<span style="color: #eedd82;">attr</span>);
<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">pthread_condattr_init</span>(<span style="color: #98fb98;">pthread_condattr_t</span> *<span style="color: #eedd82;">attr</span>);
</pre>
</div>

<p>
Condition 变量由 <code>pthread_cond_t</code> 声明定义,而且必须初始化在使用前.两种方法初始:
</p>
<ol class="org-ol">
<li>静态的,当声明时.如:
</li>
</ol>
<div class="org-src-container">

<pre class="src src-c"><span style="color: #98fb98;">pthread_cond_t</span> <span style="color: #eedd82;">convar</span> = PTHREAD_COND_INITIALIZER;
</pre>
</div>
<ol class="org-ol">
<li>动态的,使用 <code>pthread_cond_init()</code> 函数,并能设置 condition 的属性 <code>attr</code>.
</li>
</ol>

<p>
<code>attr</code> 用来设置 condition 变量的属性,必须是 <code>pthread_condattr_t</code> 类型.只有一种属性可选:是否进程共享,也就是允许其他进程中的线程也能看到它.
</p>
</div>
</div>
<div id="outline-container-sec-5-4-3" class="outline-4">
<h4 id="sec-5-4-3">Waiting and Signaling on Condition Variables</h4>
<div class="outline-text-4" id="text-5-4-3">
<div class="org-src-container">

<pre class="src src-c"><span style="color: #98fb98;">int</span> <span style="color: #87cefa;">pthread_cond_wait</span>(<span style="color: #98fb98;">pthread_cond_t</span> *<span style="color: #eedd82;">cond</span>,
                      <span style="color: #98fb98;">pthread_mutex_t</span> *<span style="color: #eedd82;">mutex</span>);
<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">pthread_cond_signal</span>(<span style="color: #98fb98;">pthread_cond_t</span> *<span style="color: #eedd82;">cond</span>);
<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">pthread_cond_broadcast</span>(<span style="color: #98fb98;">pthread_cond_t</span> *<span style="color: #eedd82;">cond</span>);
</pre>
</div>

<p>
<code>pthread_cond_wait()</code> 阻塞调用它的线程直到其中 <code>cond</code> 被 signal.这个函数需要在占有 <i>mutex</i> 时被调用,而它将 <b>自动释放</b> mutex 当它等待时.等到
signal 收到,线程被唤醒, <i>mutex</i> 将 <b>自动被占有</b> .最后当线程完成
condition 的操作,要负责对 mutex 解锁.
</p>

<p>
<code>pthread_cond_signal()</code> 用来 signal 其他等待这个 <code>cond</code> 的线程.它需要在占有 <i>mutex</i> 时被调用.然后必须对 mutex 解锁来完成 <code>pthread_cond_wait</code>
的等待.
</p>

<p>
如果有多余一个线程处于等待 <code>cond</code> 而阻塞, 应该用
<code>pthread_cond_broadcast()</code> 替换 <code>pthread_cond_signal()</code>.
</p>
</div>
</div>
<div id="outline-container-sec-5-4-4" class="outline-4">
<h4 id="sec-5-4-4">Example: Using Condition Variables</h4>
<div class="outline-text-4" id="text-5-4-4">
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;pthread.h&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;cstdio&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;cstdlib&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;unistd.h&gt;</span>

<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">kNumThreads</span> = 3;
<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">kLoops</span> = 10;
<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">kCountLimit</span> = 15;

<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">g_count</span>;
<span style="color: #98fb98;">pthread_mutex_t</span> <span style="color: #eedd82;">count_mutex</span>;
<span style="color: #98fb98;">pthread_cond_t</span> <span style="color: #eedd82;">count_cv</span>;

<span style="color: #98fb98;">void</span> *<span style="color: #87cefa;">IncreaseCount</span>(<span style="color: #98fb98;">void</span> *<span style="color: #eedd82;">param</span>) {
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">id</span>;
  id = *(<span style="color: #00ffff;">static_cast</span>&lt;<span style="color: #98fb98;">int</span> *&gt;(param));
  <span style="color: #00ffff;">for</span> (<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span> = 0; i &lt; kLoops; ++i) {
    pthread_mutex_lock(&amp;count_mutex);
    g_count++;
    <span style="color: #00ffff;">if</span> (g_count == kCountLimit) {
      pthread_cond_signal(&amp;count_cv);
      printf(<span style="color: #ffa07a;">"increse thread %d: count = %d, signal cond\n"</span>, id, g_count);
    }
    printf(<span style="color: #ffa07a;">"increse thread %d: count = %d, unlock mutex\n"</span>, id, g_count);
    pthread_mutex_unlock(&amp;count_mutex);
    sleep(1);
  }
  pthread_exit(<span style="color: #7fffd4;">NULL</span>);
}

<span style="color: #98fb98;">void</span> *<span style="color: #87cefa;">WatchCount</span>(<span style="color: #98fb98;">void</span> *<span style="color: #eedd82;">param</span>) {
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">id</span>;
  id = *(<span style="color: #00ffff;">static_cast</span>&lt;<span style="color: #98fb98;">int</span> *&gt;(param));
  pthread_mutex_lock(&amp;count_mutex);
  <span style="color: #00ffff;">while</span> (g_count &lt; kCountLimit) {
    pthread_cond_wait(&amp;count_cv, &amp;count_mutex);
    printf(<span style="color: #ffa07a;">"watch thread %d: count = %d, receive signal\n"</span>, id, g_count);
  }
  pthread_mutex_unlock(&amp;count_mutex);
  pthread_exit(<span style="color: #7fffd4;">NULL</span>);
}

<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">main</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">argc</span>, <span style="color: #98fb98;">char</span> *<span style="color: #eedd82;">argv</span>[]) {
  <span style="color: #98fb98;">pthread_t</span> <span style="color: #eedd82;">threads</span>[kNumThreads];
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">thread_ids</span>[kNumThreads];
  <span style="color: #98fb98;">pthread_attr_t</span> <span style="color: #eedd82;">attr</span>;

  pthread_mutex_init(&amp;count_mutex, <span style="color: #7fffd4;">NULL</span>);
  pthread_cond_init(&amp;count_cv, <span style="color: #7fffd4;">NULL</span>);
  pthread_attr_init(&amp;attr);
  pthread_attr_setdetachstate(&amp;attr, PTHREAD_CREATE_JOINABLE);
  <span style="color: #00ffff;">for</span> (<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span> = 0; i &lt; kNumThreads; ++i) {
    thread_ids[i] = i;
  }
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">rt</span>;
  rt = pthread_create(&amp;threads[0], &amp;attr, WatchCount,
                            <span style="color: #00ffff;">static_cast</span>&lt;<span style="color: #98fb98;">void</span> *&gt;(&amp;thread_ids[0]));
  <span style="color: #00ffff;">if</span> (rt) {
    printf(<span style="color: #ffa07a;">"ERROR: pthread_create failed, rt=%d\n"</span>, rt);
    exit(1);
  }
  rt = pthread_create(&amp;threads[1], &amp;attr, IncreaseCount,
                            <span style="color: #00ffff;">static_cast</span>&lt;<span style="color: #98fb98;">void</span> *&gt;(&amp;thread_ids[1]));
  <span style="color: #00ffff;">if</span> (rt) {
    printf(<span style="color: #ffa07a;">"ERROR: pthread_create failed, rt=%d\n"</span>, rt);
    exit(1);
  }
  rt = pthread_create(&amp;threads[2], &amp;attr, IncreaseCount,
                            <span style="color: #00ffff;">static_cast</span>&lt;<span style="color: #98fb98;">void</span> *&gt;(&amp;thread_ids[2]));
  <span style="color: #00ffff;">if</span> (rt) {
    printf(<span style="color: #ffa07a;">"ERROR: pthread_create failed, rt=%d\n"</span>, rt);
    exit(1);
  }
  <span style="color: #00ffff;">for</span> (<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span> = 0; i &lt; kNumThreads; ++i) {
    pthread_join(threads[i], <span style="color: #7fffd4;">NULL</span>);
  }
  pthread_attr_destroy(&amp;attr);
  pthread_cond_destroy(&amp;count_cv);
  pthread_mutex_destroy(&amp;count_mutex);
  pthread_exit(<span style="color: #7fffd4;">NULL</span>);
}
</pre>
</div>
</div>
</div>
</div>

<div id="outline-container-sec-5-5" class="outline-3">
<h3 id="sec-5-5">Barrier</h3>
<div class="outline-text-3" id="text-5-5">
</div><div id="outline-container-sec-5-5-1" class="outline-4">
<h4 id="sec-5-5-1">Overview</h4>
<div class="outline-text-4" id="text-5-5-1">
<p>
Barrier 就是栅栏一样,调用等待 barrier 的线程需要等待直到满足调用 barrier 的线程个数达到要求的 <code>count</code>.
</p>
</div>
</div>

<div id="outline-container-sec-5-5-2" class="outline-4">
<h4 id="sec-5-5-2">Creating, Destroying and Wait Barrier</h4>
<div class="outline-text-4" id="text-5-5-2">
<div class="org-src-container">

<pre class="src src-c"><span style="color: #98fb98;">int</span> <span style="color: #87cefa;">pthread_barrier_init</span>(<span style="color: #98fb98;">pthread_barrier_t</span> *<span style="color: #eedd82;">barrier</span>,
                <span style="color: #00ffff;">const</span> <span style="color: #98fb98;">pthread_barrierattr_t</span> *<span style="color: #eedd82;">attr</span>, <span style="color: #98fb98;">unsigned</span> <span style="color: #eedd82;">count</span>);
<span style="color: #98fb98;">pthread_barrier_t</span> <span style="color: #eedd82;">barrier</span> = PTHREAD_BARRIER_INITIALIZER(count);
<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">pthread_barrier_destroy</span>(<span style="color: #98fb98;">pthread_barrier_t</span> *<span style="color: #eedd82;">barrier</span>);
<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">pthread_barrierattr_init</span>(<span style="color: #98fb98;">pthread_barrierattr_t</span> *<span style="color: #eedd82;">attr</span>);
<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">pthread_barrierattr_destroy</span>(<span style="color: #98fb98;">pthread_barrierattr_t</span> *<span style="color: #eedd82;">attr</span>);
<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">pthread_barrier_wait</span>(<span style="color: #98fb98;">pthread_barrier_t</span> *<span style="color: #eedd82;">barrier</span>);
</pre>
</div>

<p>
Barrier 变量由 <code>pthread_barrier_t</code> 声明定义,而且必须初始化在使用前.需要传入满足 barrier 等待的个数 <code>count</code>, 两种方法初始:
</p>
<ol class="org-ol">
<li>静态的,当声明时.如:
</li>
</ol>
<div class="org-src-container">

<pre class="src src-c"><span style="color: #98fb98;">pthread_barrier_t</span> <span style="color: #eedd82;">barrier</span> = PTHREAD_BARRIER_INITIALIZER(count);
</pre>
</div>
<ol class="org-ol">
<li>动态的,使用 <code>pthread_barrier_init()</code> 函数,并能设置 barrier 的属性 <code>attr</code>.
</li>
</ol>

<p>
线程调用 barrier,只需要调用 <code>pthread_barrier_wait</code> 来等待 barrier 达到满足条件.
</p>

<p>
<a id="google-wrap" name="google-wrap"></a>
</p>
</div>
</div>
</div>
</div>

<div id="outline-container-sec-6" class="outline-2">
<h2 id="sec-6">Google wrap the Pthread</h2>
<div class="outline-text-2" id="text-6">
</div><div id="outline-container-sec-6-1" class="outline-3">
<h3 id="sec-6-1">Mutex 类和 CondVar 类</h3>
<div class="outline-text-3" id="text-6-1">
<p>
Google api 的 base 包里封装了 Mutex 类和 CondVar 类.
</p>
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #00ffff;">namespace</span> <span style="color: #7fffd4;">base</span> {
<span style="color: #00ffff;">enum</span> <span style="color: #98fb98;">LinkerInitialized</span> { <span style="color: #eedd82;">LINKER_INITIALIZED</span> };
}

<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">LOCKABLE</span> <span style="color: #eedd82;">PThreadMutex</span> {
 <span style="color: #00ffff;">public</span>:
  <span style="color: #00ffff;">explicit</span> <span style="color: #eedd82;">PThreadMutex</span>(<span style="color: #7fffd4;">base</span>::LinkerInitialized) {
    pthread_mutex_init(&amp;mutex_, <span style="color: #7fffd4;">NULL</span>);
  }
  <span style="color: #eedd82;">PThreadMutex</span>()   { pthread_mutex_init(&amp;mutex_, <span style="color: #7fffd4;">NULL</span>); }
  ~<span style="color: #eedd82;">PThreadMutex</span>()  { pthread_mutex_destroy(&amp;mutex_); }

  <span style="color: #98fb98;">void</span> <span style="color: #eedd82;">Lock</span>()     { CHECK_EQ(0, pthread_mutex_lock(&amp;mutex_)); }
  <span style="color: #98fb98;">void</span> <span style="color: #eedd82;">Unlock</span>()   { CHECK_EQ(0, pthread_mutex_unlock(&amp;mutex_)); }

 <span style="color: #00ffff;">private</span>:
  <span style="color: #00ffff;">friend</span> <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">PThreadCondVar</span>;
  <span style="color: #98fb98;">pthread_mutex_t</span> <span style="color: #eedd82;">mutex_</span>;

  DISALLOW_COPY_AND_ASSIGN(PThreadMutex);
};

<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">PThreadCondVar</span> {
 <span style="color: #00ffff;">public</span>:
  <span style="color: #87cefa;">PThreadCondVar</span>()  { pthread_cond_init(&amp;cv_, <span style="color: #7fffd4;">NULL</span>); }
  ~<span style="color: #87cefa;">PThreadCondVar</span>() { CHECK_EQ(0, <span style="color: #98fb98;">pthread_cond_destroy</span>(&amp;<span style="color: #eedd82;">cv_</span>)); }

  <span style="color: #98fb98;">void</span> <span style="color: #87cefa;">Signal</span>()        { CHECK_EQ(0, <span style="color: #98fb98;">pthread_cond_signal</span>(&amp;<span style="color: #eedd82;">cv_</span>)); }
  <span style="color: #98fb98;">void</span> <span style="color: #87cefa;">SignalAll</span>()     { CHECK_EQ(0, <span style="color: #98fb98;">pthread_cond_broadcast</span>(&amp;<span style="color: #eedd82;">cv_</span>)); }
  <span style="color: #98fb98;">void</span> <span style="color: #87cefa;">Wait</span>(<span style="color: #98fb98;">PThreadMutex</span>* <span style="color: #eedd82;">mu</span>) {
    CHECK_EQ(0, pthread_cond_wait(&amp;cv_, &amp;mu-&gt;mutex_));
  }
  <span style="color: #98fb98;">bool</span> <span style="color: #87cefa;">WaitWithTimeout</span>(<span style="color: #98fb98;">PThreadMutex</span>* <span style="color: #eedd82;">mu</span>, <span style="color: #98fb98;">int64</span> <span style="color: #eedd82;">millis</span>) {
    <span style="color: #00ffff;">struct</span> <span style="color: #98fb98;">timeval</span> <span style="color: #eedd82;">tv</span>;
    <span style="color: #00ffff;">struct</span> <span style="color: #98fb98;">timespec</span> <span style="color: #eedd82;">ts</span>;
    gettimeofday(&amp;tv, <span style="color: #7fffd4;">NULL</span>);
    ts.tv_sec = tv.tv_sec + millis / 1000;
    ts.tv_nsec = millis % 1000;
    <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">result</span> = pthread_cond_timedwait(&amp;cv_, &amp;mu-&gt;mutex_, &amp;ts);
    <span style="color: #00ffff;">if</span> (!result) <span style="color: #00ffff;">return</span> <span style="color: #7fffd4;">true</span>;

    CHECK_EQ(ETIMEDOUT, result);
    <span style="color: #00ffff;">return</span> <span style="color: #7fffd4;">false</span>;
  }

 <span style="color: #00ffff;">private</span>:
  <span style="color: #98fb98;">pthread_cond_t</span> <span style="color: #eedd82;">cv_</span>;
  DISALLOW_COPY_AND_ASSIGN(<span style="color: #98fb98;">PThreadCondVar</span>);
};

<span style="color: #00ffff;">typedef</span> <span style="color: #98fb98;">PThreadCondVar</span> <span style="color: #98fb98;">CondVar</span>;
<span style="color: #00ffff;">typedef</span> <span style="color: #98fb98;">PThreadMutex</span> <span style="color: #98fb98;">Mutex</span>;
</pre>
</div>
</div>
</div>

<div id="outline-container-sec-6-2" class="outline-3">
<h3 id="sec-6-2">GoogleOnceInit 类</h3>
<div class="outline-text-3" id="text-6-2">
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #00ffff;">typedef</span> <span style="color: #98fb98;">pthread_once_t</span> <span style="color: #98fb98;">GoogleOnceType</span>;
<span style="color: #b0c4de;">#define</span> <span style="color: #eedd82;">GOOGLE_ONCE_INIT</span> PTHREAD_ONCE_INIT

<span style="color: #00ffff;">inline</span> <span style="color: #98fb98;">void</span> <span style="color: #87cefa;">GoogleOnceInit</span>(<span style="color: #98fb98;">GoogleOnceType</span>* <span style="color: #eedd82;">once</span>, <span style="color: #98fb98;">void</span> (*<span style="color: #eedd82;">initializer</span>)()) {
  CHECK_EQ(0, pthread_once(once, initializer));
}
</pre>
</div>
</div>
</div>
</div>

<div id="outline-container-sec-7" class="outline-2">
<h2 id="sec-7">Monitoring, Debugging and Performance Analysis Tools for Pthreads</h2>
<div class="outline-text-2" id="text-7">
</div><div id="outline-container-sec-7-1" class="outline-3">
<h3 id="sec-7-1">Monitoring</h3>
<div class="outline-text-3" id="text-7-1">
</div><div id="outline-container-sec-7-1-1" class="outline-4">
<h4 id="sec-7-1-1">Linux <b>ps</b> command</h4>
<div class="outline-text-4" id="text-7-1-1">
<p>
使用 Linux 自带的 <code>ps</code> 命令查看运行的 thread 情况,<a href="http://unixhelp.ed.ac.uk/CGI/man-cgi?ps">ps 的 man 手册</a>.
</p>
<div class="org-src-container">

<pre class="src src-sh">&#10140;$ ps -Lf
UID        PID  PPID   LWP  C NLWP STIME TTY          TIME CMD
shougang 13103  8814 13103  0    1 23:30 pts/17   00:00:00 /bin/zsh
shougang 13237 13103 13237  0    6 23:30 pts/17   00:00:00 [thread]
shougang 13237 13103 13240  0    6 23:30 pts/17   00:00:00 [thread]
shougang 13237 13103 13241  0    6 23:30 pts/17   00:00:00 [thread]
shougang 13237 13103 13242  0    6 23:30 pts/17   00:00:00 [thread]
shougang 13237 13103 13243  0    6 23:30 pts/17   00:00:00 [thread]
shougang 13237 13103 13244  0    6 23:30 pts/17   00:00:00 [thread]
</pre>
</div>
</div>
</div>

<div id="outline-container-sec-7-1-2" class="outline-4">
<h4 id="sec-7-1-2">Linux <b>top</b> command</h4>
<div class="outline-text-4" id="text-7-1-2">
<p>
Linux 的 <code>top</code> 命令加上 <code>-H</code> 参数, process 中的 threads 也能看到.
如下是 <code>top -H</code> 的一个例子:
</p>

<img class="center" src="http://dreamrunner.org/images/blog/2014/c++_multithreaing/top.png" />
</div>
</div>
</div>
<div id="outline-container-sec-7-2" class="outline-3">
<h3 id="sec-7-2">Debugging</h3>
<div class="outline-text-3" id="text-7-2">
</div><div id="outline-container-sec-7-2-1" class="outline-4">
<h4 id="sec-7-2-1">GDB</h4>
<div class="outline-text-4" id="text-7-2-1">
<ul class="org-ul">
<li><a href="http://sources.redhat.com/gdb/current/onlinedocs/gdb/Threads.html#Threads">Debugging Programs with Multiple Threads</a>
</li>
<li><a href="http://sources.redhat.com/gdb/current/onlinedocs/gdb/Thread-Stops.html#Thread-Stops">GDB: Stopping and starting multi-thread programs</a>
</li>
<li><a href="http://sources.redhat.com/gdb/current/onlinedocs/gdb/GDB_002fMI-Thread-Commands.html#GDB_002fMI-Thread-Commands">GDB/MI: Threads commands</a>
</li>
</ul>
</div>
</div>
<div id="outline-container-sec-7-2-2" class="outline-4">
<h4 id="sec-7-2-2">DDD</h4>
<div class="outline-text-4" id="text-7-2-2">
<ul class="org-ul">
<li><a href="http://www.gnu.org/software/ddd/manual/html_mono/ddd.html#Threads">Examining Threads</a>
</li>
</ul>
</div>
</div>
</div>

<div id="outline-container-sec-7-3" class="outline-3">
<h3 id="sec-7-3">Performance Analysis Tools<sup><a id="fnr.2" name="fnr.2" class="footref" href="#fn.2">2</a></sup></h3>
<div class="outline-text-3" id="text-7-3">
<ul class="org-ul">
<li><a href="http://www.openspeedshop.org/wp/">Open|SpeedShop</a>
</li>
<li><a href="http://www.cs.uoregon.edu/research/tau/home.php">TAU</a>
</li>
<li><a href="https://software.intel.com/en-us/intel-advisor-xe">Intel Advisor</a>
</li>
</ul>

<p>
<a id="boost-thread" name="boost-thread"></a>
</p>
</div>
</div>
</div>

<div id="outline-container-sec-8" class="outline-2">
<h2 id="sec-8">Boost thread library</h2>
<div class="outline-text-2" id="text-8">
</div><div id="outline-container-sec-8-1" class="outline-3">
<h3 id="sec-8-1">Overview</h3>
<div class="outline-text-3" id="text-8-1">
<p>
直到 C++11 库才比较好的支持 thread,之前 C++程序使用操作系统支持的 thread 库(如
Pthread).但这样做至少有个主要的问题:(1) 这些库基本是 C 的库,需要很小心的
C++中使用,和(2) 每个操作系统提供自己的一套对 thread 支持的库.以致,编写的代码既不标准又不可移植.
</p>

<p>
<a href="http://www.boost.org/doc/libs/1_55_0/doc/html/thread.html">Boost Thread</a>可以解决这两个主要问题. Boost Thread 不是通过继承来使用线程,而是 Boost 的 thread 类使用一个 Callable 的对象创建.
</p>
</div>

<div id="outline-container-sec-8-1-1" class="outline-4">
<h4 id="sec-8-1-1">编译 Boost Thread 程序</h4>
<div class="outline-text-4" id="text-8-1-1">
</div><div id="outline-container-sec-8-1-1-1" class="outline-5">
<h5 id="sec-8-1-1-1">include</h5>
<div class="outline-text-5" id="text-8-1-1-1">
<p>
根据使用到的 Boost Thread 中的类型包含不同头文件:
</p>
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;boost/thread/thread.hpp&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;boost/thread/mutex.hpp&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;boost/thread/condition.hpp&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;boost/thread/locks.hpp&gt;</span> 
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;boost/thread/once.hpp&gt;</span>
</pre>
</div>
</div>
</div>

<div id="outline-container-sec-8-1-1-2" class="outline-5">
<h5 id="sec-8-1-1-2">compile</h5>
<div class="outline-text-5" id="text-8-1-1-2">
<p>
对于 Gcc 编译器,使用选项 <code>-l</code>,如下:
</p>
<div class="org-src-container">

<pre class="src src-sh">g++ Program.o -o Program -lboost_thread -lboost_system
</pre>
</div>
</div>
</div>
</div>
</div>

<div id="outline-container-sec-8-2" class="outline-3">
<h3 id="sec-8-2">Thread Management</h3>
<div class="outline-text-3" id="text-8-2">
</div><div id="outline-container-sec-8-2-1" class="outline-4">
<h4 id="sec-8-2-1">Thread 类</h4>
<div class="outline-text-4" id="text-8-2-1">
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #b0c4de;">  #include</span> <span style="color: #ffa07a;">&lt;boost/thread/thread.hpp&gt;</span>
  <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">thread</span>
  {
  <span style="color: #00ffff;">public</span>:
      <span style="color: #87cefa;">thread</span>() noexcept;
      <span style="color: #87cefa;">thread</span>(<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">thread</span>&amp;) = <span style="color: #00ffff;">delete</span>;
      <span style="color: #98fb98;">thread</span>&amp; <span style="color: #00ffff;">operator</span><span style="color: #87cefa;">=</span>(<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">thread</span>&amp;) = <span style="color: #00ffff;">delete</span>;

      <span style="color: #87cefa;">thread</span>(<span style="color: #98fb98;">thread</span>&amp;&amp;) noexcept;
      <span style="color: #98fb98;">thread</span>&amp; <span style="color: #00ffff;">operator</span><span style="color: #87cefa;">=</span>(<span style="color: #98fb98;">thread</span>&amp;&amp;) noexcept;
      ~<span style="color: #87cefa;">thread</span>();

      <span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">F</span>&gt;
      <span style="color: #00ffff;">explicit</span> <span style="color: #87cefa;">thread</span>(<span style="color: #98fb98;">F</span> <span style="color: #eedd82;">f</span>);
      <span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">F</span>&gt;
      <span style="color: #87cefa;">thread</span>(<span style="color: #98fb98;">F</span> &amp;&amp;<span style="color: #eedd82;">f</span>);

      <span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">F</span>,<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">A1</span>,<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">A2</span>,...&gt;
      <span style="color: #87cefa;">thread</span>(<span style="color: #98fb98;">F</span> <span style="color: #eedd82;">f</span>,<span style="color: #98fb98;">A1</span> <span style="color: #eedd82;">a1</span>,<span style="color: #98fb98;">A2</span> <span style="color: #eedd82;">a2</span>,...);
      <span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">F</span>, <span style="color: #00ffff;">class</span> ...Args&gt;
      <span style="color: #00ffff;">explicit</span> <span style="color: #87cefa;">thread</span>(<span style="color: #98fb98;">F</span>&amp;&amp; <span style="color: #eedd82;">f</span>, <span style="color: #98fb98;">Args</span>&amp;&amp;... args);

      <span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">F</span>&gt;
      <span style="color: #00ffff;">explicit</span> <span style="color: #87cefa;">thread</span>(<span style="color: #98fb98;">attributes</span>&amp; <span style="color: #eedd82;">attrs</span>, <span style="color: #98fb98;">F</span> <span style="color: #eedd82;">f</span>); <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">EXTENSION</span>
      <span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">F</span>&gt;
      <span style="color: #87cefa;">thread</span>(<span style="color: #98fb98;">attributes</span>&amp; <span style="color: #eedd82;">attrs</span>, <span style="color: #98fb98;">F</span> &amp;&amp;<span style="color: #eedd82;">f</span>); <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">EXTENSION</span>
      <span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">F</span>, <span style="color: #00ffff;">class</span> ...Args&gt;
      <span style="color: #00ffff;">explicit</span> <span style="color: #87cefa;">thread</span>(<span style="color: #98fb98;">attributes</span>&amp; <span style="color: #eedd82;">attrs</span>, <span style="color: #98fb98;">F</span>&amp;&amp; <span style="color: #eedd82;">f</span>, <span style="color: #98fb98;">Args</span>&amp;&amp;... args);
      <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">id</span>;
      <span style="color: #98fb98;">id</span> <span style="color: #87cefa;">get_id</span>() <span style="color: #00ffff;">const</span> <span style="color: #98fb98;">noexcept</span>;

      <span style="color: #98fb98;">bool</span> <span style="color: #87cefa;">joinable</span>() <span style="color: #00ffff;">const</span> <span style="color: #98fb98;">noexcept</span>;
      <span style="color: #98fb98;">void</span> <span style="color: #87cefa;">join</span>();
...
};
</pre>
</div>

<p>
整个 thread 类包含 thread 的所有特性,如 thread id, join, detach 等.
</p>
</div>
<div id="outline-container-sec-8-2-1-1" class="outline-5">
<h5 id="sec-8-2-1-1">Create Thread</h5>
<div class="outline-text-5" id="text-8-2-1-1">
<p>
Callable 对象既可以是一个函数又可以是类中的 <code>operator()</code> 实现,如下:
</p>

<div class="org-src-container">

<pre class="src src-c++"><span style="color: #98fb98;">void</span> <span style="color: #87cefa;">hello</span>() {
  cout &lt;&lt; <span style="color: #ffa07a;">"hello world"</span> &lt;&lt; endl;
}

<span style="color: #00ffff;">struct</span> <span style="color: #98fb98;">Hello</span> {
 <span style="color: #00ffff;">public</span>:
  <span style="color: #98fb98;">void</span> <span style="color: #00ffff;">operator</span><span style="color: #87cefa;">()</span> () {
    cout &lt;&lt; <span style="color: #ffa07a;">"hello world"</span> &lt;&lt; endl;
  }
};

<span style="color: #98fb98;">Hello</span> <span style="color: #eedd82;">h</span>;
<span style="color: #7fffd4;">boost</span>::<span style="color: #98fb98;">thread</span> <span style="color: #87cefa;">thread_hello</span>(h);
<span style="color: #7fffd4;">boost</span>::<span style="color: #98fb98;">thread</span> <span style="color: #87cefa;">thread_hello</span>(hello);
</pre>
</div>
</div>
</div>

<div id="outline-container-sec-8-2-1-2" class="outline-5">
<h5 id="sec-8-2-1-2">Passing data</h5>
<div class="outline-text-5" id="text-8-2-1-2">
<p>
传递参数给线程
</p>
<ol class="org-ol">
<li>thread 创建时附加后面
</li>
</ol>
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #98fb98;">void</span> <span style="color: #87cefa;">hello</span>(<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">string</span> &amp;<span style="color: #eedd82;">str</span>) {
  cout &lt;&lt; str &lt;&lt; endl;
}
<span style="color: #98fb98;">string</span> <span style="color: #eedd82;">str</span> = <span style="color: #ffa07a;">"hello"</span>;
<span style="color: #7fffd4;">boost</span>::<span style="color: #98fb98;">thread</span> <span style="color: #87cefa;">thrd</span>(hello, str);
</pre>
</div>
<ol class="org-ol">
<li>利用 <code>Boost.bind</code> 库接口
</li>
</ol>
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #98fb98;">void</span> <span style="color: #87cefa;">hello</span>(<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">string</span> &amp;<span style="color: #eedd82;">str</span>) {
  cout &lt;&lt; str &lt;&lt; endl;
}
<span style="color: #98fb98;">string</span> <span style="color: #eedd82;">str</span> = <span style="color: #ffa07a;">"hello"</span>;
<span style="color: #98fb98;">string</span> <span style="color: #eedd82;">str</span> = <span style="color: #ffa07a;">"hello"</span>;
<span style="color: #7fffd4;">boost</span>::<span style="color: #98fb98;">thread</span> <span style="color: #87cefa;">thrd</span>(bind(hello, str));
</pre>
</div>
</div>
</div>
</div>
<div id="outline-container-sec-8-2-2" class="outline-4">
<h4 id="sec-8-2-2">Thread group 类</h4>
<div class="outline-text-4" id="text-8-2-2">
<p>
可以使用 thread group 类管理 thread,通过 <code>add_thread</code> 和 <code>create_thread</code>
添加线程到管理类中, 可以直接 <code>join_all</code> 将所有管理类中的线程 join.
</p>
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;boost/thread/thread.hpp&gt;</span>

<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">thread_group</span>
{
<span style="color: #00ffff;">public</span>:
    <span style="color: #87cefa;">thread_group</span>(<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">thread_group</span>&amp;) = <span style="color: #00ffff;">delete</span>;
    <span style="color: #98fb98;">thread_group</span>&amp; <span style="color: #00ffff;">operator</span><span style="color: #87cefa;">=</span>(<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">thread_group</span>&amp;) = <span style="color: #00ffff;">delete</span>;

    <span style="color: #87cefa;">thread_group</span>();
    ~<span style="color: #87cefa;">thread_group</span>();

    <span style="color: #00ffff;">template</span>&lt;<span style="color: #00ffff;">typename</span> <span style="color: #98fb98;">F</span>&gt;
    <span style="color: #98fb98;">thread</span>* <span style="color: #87cefa;">create_thread</span>(<span style="color: #98fb98;">F</span> <span style="color: #eedd82;">threadfunc</span>);
    <span style="color: #98fb98;">void</span> <span style="color: #87cefa;">add_thread</span>(<span style="color: #98fb98;">thread</span>* <span style="color: #eedd82;">thrd</span>);
    <span style="color: #98fb98;">void</span> <span style="color: #87cefa;">remove_thread</span>(<span style="color: #98fb98;">thread</span>* <span style="color: #eedd82;">thrd</span>);
    <span style="color: #98fb98;">bool</span> <span style="color: #87cefa;">is_this_thread_in</span>();
    <span style="color: #98fb98;">bool</span> <span style="color: #87cefa;">is_thread_in</span>(<span style="color: #98fb98;">thread</span>* <span style="color: #eedd82;">thrd</span>);
    <span style="color: #98fb98;">void</span> <span style="color: #87cefa;">join_all</span>();
    <span style="color: #98fb98;">void</span> <span style="color: #87cefa;">interrupt_all</span>();
    <span style="color: #98fb98;">int</span> <span style="color: #87cefa;">size</span>() <span style="color: #00ffff;">const</span>;
};
</pre>
</div>
</div>
</div>

<div id="outline-container-sec-8-2-3" class="outline-4">
<h4 id="sec-8-2-3">Miscellaneous</h4>
<div class="outline-text-4" id="text-8-2-3">
<p>
Boost Thread 中还有 <code>strict_scoped_thread</code> 类和 <code>scoped_thread</code> 类,提供线程结束不是调用 <code>terminate</code> ,而是调用传入的参数来执行特定行为.
</p>
</div>
</div>
<div id="outline-container-sec-8-2-4" class="outline-4">
<h4 id="sec-8-2-4">Example: Thread Creation</h4>
<div class="outline-text-4" id="text-8-2-4">
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;iostream&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;string&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;boost/thread/thread.hpp&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;boost/bind.hpp&gt;</span>

<span style="color: #00ffff;">using</span> <span style="color: #00ffff;">namespace</span> <span style="color: #7fffd4;">std</span>;
<span style="color: #00ffff;">using</span> <span style="color: #00ffff;">namespace</span> <span style="color: #7fffd4;">boost</span>;

<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">hello</span>(<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">string</span> &amp;<span style="color: #eedd82;">str</span>) {
  cout &lt;&lt; str &lt;&lt; endl;
}

<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">main</span>(){
  <span style="color: #98fb98;">string</span> <span style="color: #eedd82;">str</span> = <span style="color: #ffa07a;">"hello"</span>;
  <span style="color: #7fffd4;">boost</span>::<span style="color: #98fb98;">thread</span> <span style="color: #eedd82;">thrd</span>(bind(hello, str));
  thrd.join();
  <span style="color: #00ffff;">return</span> 0;
}
</pre>
</div>
</div>
</div>
</div>

<div id="outline-container-sec-8-3" class="outline-3">
<h3 id="sec-8-3">Mutex Variables</h3>
<div class="outline-text-3" id="text-8-3">
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;boost/thread/mutex.hpp&gt;</span>

<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">mutex</span>:
    <span style="color: #7fffd4;">boost</span>::<span style="color: #98fb98;">noncopyable</span>
{
<span style="color: #00ffff;">public</span>:
    <span style="color: #87cefa;">mutex</span>();
    ~<span style="color: #87cefa;">mutex</span>();

    <span style="color: #98fb98;">void</span> <span style="color: #87cefa;">lock</span>();
    <span style="color: #98fb98;">bool</span> <span style="color: #87cefa;">try_lock</span>();
    <span style="color: #98fb98;">void</span> <span style="color: #87cefa;">unlock</span>();

    <span style="color: #00ffff;">typedef</span> <span style="color: #98fb98;">platform</span>-specific-type native_handle_type;
    <span style="color: #98fb98;">native_handle_type</span> <span style="color: #87cefa;">native_handle</span>();

    <span style="color: #00ffff;">typedef</span> <span style="color: #98fb98;">unique_lock</span>&lt;<span style="color: #98fb98;">mutex</span>&gt; <span style="color: #98fb98;">scoped_lock</span>;
    <span style="color: #00ffff;">typedef</span> <span style="color: #98fb98;">unspecified</span>-type scoped_try_lock;
};
</pre>
</div>

<ul class="org-ul">
<li><code>lock()</code> 来获取锁.
</li>
<li><code>unlock()</code> 释放锁.
</li>
<li><code>typedef unique_lock&lt;mutex&gt; scoped_lock;</code> 定义了 <code>scoped_lock</code> 的类型,通过 <code>boost::mutex::scoped_lock</code> 来定义一个 RAII-style 锁,离开定义区域自动释放锁.
</li>
</ul>
</div>

<div id="outline-container-sec-8-3-1" class="outline-4">
<h4 id="sec-8-3-1"><code>lock_guard</code></h4>
<div class="outline-text-4" id="text-8-3-1">
<p>
<code>boost::lock_guard</code> 非常简单:
</p>
<ul class="org-ul">
<li>构造时,它获取锁.
</li>
<li>析构时,它释放锁.
</li>
</ul>

<p>
它提供了一个简单的 RAII-style 锁对象,使得 exception-safe 锁和解锁更容易.
</p>
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #00ffff;">namespace</span> <span style="color: #7fffd4;">boost</span>
{
  <span style="color: #00ffff;">template</span>&lt;<span style="color: #00ffff;">typename</span> <span style="color: #98fb98;">Lockable</span>&gt;
  <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">lock_guard</span>
<span style="color: #b0c4de;">#if</span> ! <span style="color: #b0c4de;">defined</span> BOOST_THREAD_NO_MAKE_LOCK_GUARD
  <span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">typename</span> <span style="color: #98fb98;">Lockable</span>&gt;
  <span style="color: #98fb98;">lock_guard</span>&lt;<span style="color: #98fb98;">Lockable</span>&gt; <span style="color: #87cefa;">make_lock_guard</span>(<span style="color: #98fb98;">Lockable</span>&amp; <span style="color: #eedd82;">mtx</span>); <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">EXTENSION</span>
  <span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">typename</span> <span style="color: #98fb98;">Lockable</span>&gt;
  <span style="color: #98fb98;">lock_guard</span>&lt;<span style="color: #98fb98;">Lockable</span>&gt; <span style="color: #87cefa;">make_lock_guard</span>(<span style="color: #98fb98;">Lockable</span>&amp; <span style="color: #eedd82;">mtx</span>, <span style="color: #98fb98;">adopt_lock_t</span>); <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">EXTENSION</span>
<span style="color: #b0c4de;">#endif</span>
}
</pre>
</div>

<p>
基本使用,传入可 <code>Lockable</code> 的 mutex 类型:
</p>
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #7fffd4;">boost</span>::<span style="color: #98fb98;">mutex</span> <span style="color: #eedd82;">count_mutex</span>;
<span style="color: #7fffd4;">boost</span>::<span style="color: #98fb98;">lock_guard</span>&lt;<span style="color: #98fb98;">mutex</span>&gt; <span style="color: #87cefa;">lock</span>(count_mutex) ;
</pre>
</div>
</div>
</div>

<div id="outline-container-sec-8-3-2" class="outline-4">
<h4 id="sec-8-3-2">Example: Using Mutexes</h4>
<div class="outline-text-4" id="text-8-3-2">
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;iostream&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;boost/thread/thread.hpp&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;boost/thread/mutex.hpp&gt;</span>

<span style="color: #00ffff;">using</span> <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">cout</span>;
<span style="color: #00ffff;">using</span> <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">endl</span>;
<span style="color: #7fffd4;">boost</span>::<span style="color: #98fb98;">mutex</span> <span style="color: #eedd82;">count_mutex</span>;

<span style="color: #00ffff;">struct</span> <span style="color: #98fb98;">count</span> {
  <span style="color: #87cefa;">count</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">id</span>) : id_(id) {
  }
  <span style="color: #98fb98;">void</span> <span style="color: #00ffff;">operator</span><span style="color: #87cefa;">()</span> () {
    <span style="color: #00ffff;">for</span> (<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span> = 0; i &lt; 10; ++i) {
      <span style="color: #7fffd4;">boost</span>::<span style="color: #7fffd4;">mutex</span>::<span style="color: #98fb98;">scoped_lock</span> <span style="color: #eedd82;">lock</span>(count_mutex);
      cout &lt;&lt; id_ &lt;&lt; <span style="color: #ffa07a;">": "</span> &lt;&lt; i &lt;&lt; endl;
    }
  }
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">id_</span>;
};

<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">main</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">argc</span>, <span style="color: #98fb98;">char</span> *<span style="color: #eedd82;">argv</span>[]) {
  <span style="color: #7fffd4;">boost</span>::<span style="color: #98fb98;">thread</span> <span style="color: #eedd82;">thread1</span>(count(1));
  <span style="color: #7fffd4;">boost</span>::<span style="color: #98fb98;">thread</span> <span style="color: #eedd82;">thread2</span>(count(2));
  thread1.join();
  thread2.join();
  <span style="color: #00ffff;">return</span> 0;
}
</pre>
</div>
</div>
</div>
</div>

<div id="outline-container-sec-8-4" class="outline-3">
<h3 id="sec-8-4">Condition Variables</h3>
<div class="outline-text-3" id="text-8-4">
<p>
与 Pthread, Boost Condition Variable 功能更全面,如不同条件的
<code>wait_until</code> , <code>wait_for</code> 等功能.
</p>
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #00ffff;">namespace</span> <span style="color: #7fffd4;">boost</span>
{
    <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">condition_variable</span>
    {
    <span style="color: #00ffff;">public</span>:
        <span style="color: #87cefa;">condition_variable</span>();
        ~<span style="color: #87cefa;">condition_variable</span>();

        <span style="color: #98fb98;">void</span> <span style="color: #87cefa;">notify_one</span>() noexcept;
        <span style="color: #98fb98;">void</span> <span style="color: #87cefa;">notify_all</span>() noexcept;

        <span style="color: #98fb98;">void</span> <span style="color: #87cefa;">wait</span>(<span style="color: #7fffd4;">boost</span>::<span style="color: #98fb98;">unique_lock</span>&lt;<span style="color: #7fffd4;">boost</span>::mutex&gt;&amp; <span style="color: #eedd82;">lock</span>);

        <span style="color: #00ffff;">template</span>&lt;<span style="color: #00ffff;">typename</span> <span style="color: #98fb98;">predicate_type</span>&gt;
        <span style="color: #98fb98;">void</span> <span style="color: #87cefa;">wait</span>(<span style="color: #7fffd4;">boost</span>::<span style="color: #98fb98;">unique_lock</span>&lt;<span style="color: #7fffd4;">boost</span>::mutex&gt;&amp; <span style="color: #eedd82;">lock</span>,<span style="color: #eedd82;">predicate_type</span> predicate);

        <span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Clock</span>, <span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Duration</span>&gt;
        <span style="color: #00ffff;">typename</span> <span style="color: #7fffd4;">cv_status</span>::<span style="color: #98fb98;">type</span>
        <span style="color: #87cefa;">wait_until</span>(
            <span style="color: #98fb98;">unique_lock</span>&lt;mutex&gt;&amp; <span style="color: #eedd82;">lock</span>,
            <span style="color: #00ffff;">const</span> <span style="color: #7fffd4;">chrono</span>::<span style="color: #98fb98;">time_point</span>&lt;<span style="color: #98fb98;">Clock</span>, <span style="color: #98fb98;">Duration</span>&gt;&amp; <span style="color: #eedd82;">t</span>);
...
};
</pre>
</div>
</div>

<div id="outline-container-sec-8-4-1" class="outline-4">
<h4 id="sec-8-4-1">Example: Using Condition Variables</h4>
<div class="outline-text-4" id="text-8-4-1">
<p>
利用 Condition Variables 实现一个简单的 read/writer Buffer.
</p>

<div class="org-src-container">

<pre class="src src-c++"><span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;boost/thread/thread.hpp&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;boost/thread/mutex.hpp&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;boost/thread/condition.hpp&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;iostream&gt;</span>
<span style="color: #00ffff;">using</span> <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">cout</span>;
<span style="color: #00ffff;">using</span> <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">endl</span>;
<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">kBufSize</span> = 10;
<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">kIters</span> = 100;

<span style="color: #7fffd4;">boost</span>::<span style="color: #98fb98;">mutex</span> <span style="color: #eedd82;">io_mutex</span>;

<span style="color: #00ffff;">class</span> <span style="color: #98fb98;">Buffer</span> {
 <span style="color: #00ffff;">public</span>:
  <span style="color: #00ffff;">typedef</span> <span style="color: #7fffd4;">boost</span>::<span style="color: #7fffd4;">mutex</span>::<span style="color: #98fb98;">scoped_lock</span> <span style="color: #98fb98;">scoped_lock</span>;
  <span style="color: #87cefa;">Buffer</span>() : p(0), c(0), full(0) {
  }

  <span style="color: #98fb98;">void</span> <span style="color: #87cefa;">Put</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">m</span>) {
    <span style="color: #98fb98;">scoped_lock</span> <span style="color: #eedd82;">lock</span>(<span style="color: #98fb98;">mutex</span>);
    <span style="color: #00ffff;">if</span> (full == kBufSize) {
      {
        <span style="color: #98fb98;">scoped_lock</span> <span style="color: #eedd82;">lock</span>(io_mutex);
        cout &lt;&lt; <span style="color: #ffa07a;">"Buffer is full."</span> &lt;&lt; endl;
      }
      <span style="color: #00ffff;">while</span> (full == kBufSize) {
        cond.wait(lock);
      }
    }
    buf[p] = m;
    p = (p + 1) % kBufSize;
    ++full;
    cond.notify_one();
  }

  <span style="color: #98fb98;">int</span> <span style="color: #87cefa;">Get</span>() {
    <span style="color: #98fb98;">scoped_lock</span> <span style="color: #eedd82;">lock</span>(<span style="color: #98fb98;">mutex</span>);
    <span style="color: #00ffff;">if</span> (full == 0) {
      {
        <span style="color: #98fb98;">scoped_lock</span> <span style="color: #eedd82;">lock</span>(io_mutex);
        cout &lt;&lt; <span style="color: #ffa07a;">"Buffer is empty."</span> &lt;&lt; endl;
      }
      <span style="color: #00ffff;">while</span> (full == 0) {
        cond.wait(lock);
      }
    }
    <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span> = buf[c];
    c = (c + 1) % kBufSize;
    --full;
    cond.notify_one();
    <span style="color: #00ffff;">return</span> i;
  }
 <span style="color: #00ffff;">private</span>:
  <span style="color: #7fffd4;">boost</span>::<span style="color: #98fb98;">mutex</span> <span style="color: #eedd82;">mutex</span>;
  <span style="color: #7fffd4;">boost</span>::<span style="color: #98fb98;">condition</span> <span style="color: #eedd82;">cond</span>;
  <span style="color: #98fb98;">unsigned</span> <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">p</span>, <span style="color: #eedd82;">c</span>, <span style="color: #eedd82;">full</span>;
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">buf</span>[kBufSize];
};

<span style="color: #98fb98;">Buffer</span> <span style="color: #eedd82;">buf</span>;

<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">writer</span>() {
  <span style="color: #00ffff;">for</span> (<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span> = 0; i &lt; kIters; ++i) {
    {
      <span style="color: #7fffd4;">boost</span>::<span style="color: #7fffd4;">mutex</span>::<span style="color: #98fb98;">scoped_lock</span> <span style="color: #eedd82;">lock</span>(io_mutex);
      cout &lt;&lt; <span style="color: #ffa07a;">"sending: "</span> &lt;&lt; i &lt;&lt; endl;
    }
    buf.Put(i);
  }
}

<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">reader</span>() {
  <span style="color: #00ffff;">for</span> (<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span> = 0; i &lt; kIters; ++i) {
    <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">n</span> = buf.Get();
    {
      <span style="color: #7fffd4;">boost</span>::<span style="color: #7fffd4;">mutex</span>::<span style="color: #98fb98;">scoped_lock</span> <span style="color: #eedd82;">lock</span>(io_mutex);
      cout &lt;&lt; <span style="color: #ffa07a;">"received: "</span> &lt;&lt; n &lt;&lt; endl;
    }
  }
}

<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">main</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">argc</span>, <span style="color: #98fb98;">char</span> *<span style="color: #eedd82;">argv</span>[]) {
  <span style="color: #7fffd4;">boost</span>::thread <span style="color: #98fb98;">thread_reader</span>(&amp;<span style="color: #eedd82;">reader</span>);
  <span style="color: #7fffd4;">boost</span>::thread <span style="color: #98fb98;">thread_writer</span>(&amp;<span style="color: #eedd82;">writer</span>);
  thread_reader.join();
  thread_writer.join();
  <span style="color: #00ffff;">return</span> 0;
}
</pre>
</div>
</div>
</div>
</div>
<div id="outline-container-sec-8-5" class="outline-3">
<h3 id="sec-8-5">Miscellaneous</h3>
<div class="outline-text-3" id="text-8-5">
</div><div id="outline-container-sec-8-5-1" class="outline-4">
<h4 id="sec-8-5-1">Barrier</h4>
<div class="outline-text-4" id="text-8-5-1">
<p>
基本使用:
</p>
<ol class="org-ol">
<li>定义 barrier,传入参与 thread 个数: <code>barrier b(num_threads)</code>.
</li>
<li>thread 中等待 barrier: <code>b.wait()</code>.
</li>
</ol>

<div class="org-src-container">

<pre class="src src-c++"><span style="color: #00ffff;">class</span> <span style="color: #98fb98;">barrier</span>
{
<span style="color: #00ffff;">public</span>:
    <span style="color: #87cefa;">barrier</span>(<span style="color: #98fb98;">barrier</span> <span style="color: #00ffff;">const</span>&amp;) = <span style="color: #00ffff;">delete</span>;
    <span style="color: #98fb98;">barrier</span>&amp; <span style="color: #00ffff;">operator</span><span style="color: #87cefa;">=</span>(<span style="color: #98fb98;">barrier</span> <span style="color: #00ffff;">const</span>&amp;) = <span style="color: #00ffff;">delete</span>;

    <span style="color: #87cefa;">barrier</span>(<span style="color: #98fb98;">unsigned</span> <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">count</span>);
    <span style="color: #00ffff;">template</span> &lt;<span style="color: #00ffff;">typename</span> <span style="color: #98fb98;">F</span>&gt;
    <span style="color: #87cefa;">barrier</span>(<span style="color: #98fb98;">unsigned</span> <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">count</span>, <span style="color: #98fb98;">F</span>&amp;&amp;);

    ~<span style="color: #87cefa;">barrier</span>();

    <span style="color: #98fb98;">bool</span> <span style="color: #87cefa;">wait</span>();
    <span style="color: #98fb98;">void</span> <span style="color: #87cefa;">count_down_and_wait</span>();
};
</pre>
</div>


<p>
<a id="other-materials" name="other-materials"></a>
</p>
</div>
</div>

<div id="outline-container-sec-8-5-2" class="outline-4">
<h4 id="sec-8-5-2">Once Routines</h4>
<div class="outline-text-4" id="text-8-5-2">
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;boost/thread/once.hpp&gt;</span>

<span style="color: #00ffff;">namespace</span> <span style="color: #7fffd4;">boost</span>
{
  <span style="color: #00ffff;">struct</span> <span style="color: #98fb98;">once_flag</span>;
  <span style="color: #00ffff;">template</span>&lt;<span style="color: #00ffff;">typename</span> <span style="color: #98fb98;">Function</span>, <span style="color: #00ffff;">class</span> ...ArgTypes&gt;
  <span style="color: #00ffff;">inline</span> <span style="color: #98fb98;">void</span> <span style="color: #87cefa;">call_once</span>(<span style="color: #98fb98;">once_flag</span>&amp; <span style="color: #eedd82;">flag</span>, <span style="color: #98fb98;">Function</span>&amp;&amp; <span style="color: #eedd82;">f</span>, <span style="color: #98fb98;">ArgTypes</span>&amp;&amp;... args);

<span style="color: #b0c4de;">#if</span> <span style="color: #b0c4de;">defined</span> BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0
  <span style="color: #98fb98;">void</span> <span style="color: #87cefa;">call_once</span>(<span style="color: #98fb98;">void</span> (*<span style="color: #eedd82;">func</span>)(),<span style="color: #98fb98;">once_flag</span>&amp; <span style="color: #eedd82;">flag</span>);
<span style="color: #b0c4de;">#endif</span>

}
</pre>
</div>
</div>
<div id="outline-container-sec-8-5-2-1" class="outline-5">
<h5 id="sec-8-5-2-1">Example: Call once</h5>
<div class="outline-text-5" id="text-8-5-2-1">
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;boost/thread/thread.hpp&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;boost/thread/once.hpp&gt;</span>
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;iostream&gt;</span>

<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span> = 0;
<span style="color: #7fffd4;">boost</span>::<span style="color: #98fb98;">once_flag</span> <span style="color: #eedd82;">flag</span> = BOOST_ONCE_INIT;

<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">init</span>()
{
  ++i;
}

<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">thread</span>()
{
  <span style="color: #7fffd4;">boost</span>::call_once(&amp;init, flag);
}

<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">main</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">argc</span>, <span style="color: #98fb98;">char</span>* <span style="color: #eedd82;">argv</span>[])
{
  <span style="color: #7fffd4;">boost</span>::thread <span style="color: #98fb98;">thrd1</span>(&amp;<span style="color: #eedd82;">thread</span>);
  <span style="color: #7fffd4;">boost</span>::thread <span style="color: #98fb98;">thrd2</span>(&amp;<span style="color: #eedd82;">thread</span>);
  thrd1.join();
  thrd2.join();
  <span style="color: #7fffd4;">std</span>::cout &lt;&lt; i &lt;&lt; <span style="color: #7fffd4;">std</span>::endl;
  <span style="color: #00ffff;">return</span> 0;
}
</pre>
</div>
</div>
</div>
</div>
</div>
</div>

<div id="outline-container-sec-9" class="outline-2">
<h2 id="sec-9">其他资料</h2>
<div class="outline-text-2" id="text-9">
</div><div id="outline-container-sec-9-1" class="outline-3">
<h3 id="sec-9-1">Books:</h3>
<div class="outline-text-3" id="text-9-1">
<ul class="org-ul">
<li><a href="http://shop.oreilly.com/product/9781565921153.do">PThreads Programming</a> and <a href="http://wiki.dreamrunner.org/public_html/Books%20Review/Pthreads%20Programming/Pthreads%20Programming.html">Its notes</a>
</li>
<li><a href="http://www.justsoftwaresolutions.co.uk/blog/">Anthony Williams’ blog</a> and his book, <a href="http://www.amazon.com/gp/product/1933988770/ref=as_li_ss_tl?ie=UTF8&amp;tag=preshonprogr-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=1933988770">C++ Concurrency in Action</a>
</li>
<li>Herlihy &amp; Shavit&#8217;s <i>The Art of Multiprocessor Programming</i>
</li>
</ul>
</div>
</div>
<div id="outline-container-sec-9-2" class="outline-3">
<h3 id="sec-9-2">Online resources:</h3>
<div class="outline-text-3" id="text-9-2">
<ul class="org-ul">
<li><i>Dmitriy V’jukov’s website</i> and various <a href="https://groups.google.com/forum/?fromgroups#!forum/lock-free">forum discussions</a>
</li>
<li><a href="http://bartoszmilewski.com/">Bartosz Milewski’s blog</a>
</li>
<li>Charles Bloom’s <a href="http://cbloomrants.blogspot.ca/2012/06/06-12-12-another-threading-post-index.html">Threading Posts</a> on his blog
</li>
<li>Doug Lea&#8217;s <a href="http://g.oswego.edu/dl/jmm/cookbook.html">The JSR-133 Cookbook for Compiler Writers</a>
</li>
<li><a href="http://www.kernel.org/doc/Documentation/memory-barriers.txt">memory-barriers.txt document</a>
</li>
<li>Hans Boehm’s <a href="http://www.hboehm.info/c++mm/">collection of links about the C++11 memory model</a>
</li>
<li>Scott Meyers&#8217;s <a href="http://scottmeyers.blogspot.hk/2012/04/information-on-c11-memory-model.html">Information on the C++11 Memory Model </a>
</li>
<li>Herb Sutter’s <a href="http://www.gotw.ca/publications/">Effective Concurrency series</a>
</li>
<li>POSIX Standard: <a href="http://www.unix.org/version3/ieee_std.html">http://www.unix.org/version3/ieee_std.html</a>
</li>
</ul>
</div>
</div>
<div id="outline-container-sec-9-3" class="outline-3">
<h3 id="sec-9-3">有关 Mutex</h3>
<div class="outline-text-3" id="text-9-3">
<ul class="org-ul">
<li><a href="http://home.roadrunner.com/~hinnant/mutexes/locking.html">Handling mutexes in C++</a>
</li>
<li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2406.html">Mutex, Lock, Condition Variable Rationale</a>
</li>
</ul>

<p>
<a id="pthread-library" name="pthread-library"></a>
</p>
</div>
</div>
</div>

<div id="outline-container-sec-10" class="outline-2">
<h2 id="sec-10">Pthread Library Routines Reference</h2>
<div class="outline-text-2" id="text-10">
<p>
<a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_atfork.txt">pthread_atfork</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_attr_destroy.txt">pthread_attr_destroy</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_attr_getdetachstate.txt">pthread_attr_getdetachstate</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_attr_getguardsize.txt">pthread_attr_getguardsize</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_attr_getinheritsched.txt">pthread_attr_getinheritsched</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_attr_getschedparam.txt">pthread_attr_getschedparam</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_attr_getschedpolicy.txt">pthread_attr_getschedpolicy</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_attr_getscope.txt">pthread_attr_getscope</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_attr_getstack.txt">pthread_attr_getstack</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_attr_getstackaddr.txt">pthread_attr_getstackaddr</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_attr_getstacksize.txt">pthread_attr_getstacksize</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_attr_init.txt">pthread_attr_init</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_attr_setdetachstate.txt">pthread_attr_setdetachstate</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_attr_setguardsize.txt">pthread_attr_setguardsize</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_attr_setinheritsched.txt">pthread_attr_setinheritsched</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_attr_setschedparam.txt">pthread_attr_setschedparam</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_attr_setschedpolicy.txt">pthread_attr_setschedpolicy</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_attr_setscope.txt">pthread_attr_setscope</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_attr_setstack.txt">pthread_attr_setstack</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_attr_setstackaddr.txt">pthread_attr_setstackaddr</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_attr_setstacksize.txt">pthread_attr_setstacksize</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_barrier_destroy.txt">pthread_barrier_destroy</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_barrier_init.txt">pthread_barrier_init</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_barrier_wait.txt">pthread_barrier_wait</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_barrierattr_destroy.txt">pthread_barrierattr_destroy</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_barrierattr_getpshared.txt">pthread_barrierattr_getpshared</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_barrierattr_init.txt">pthread_barrierattr_init</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_barrierattr_setpshared.txt">pthread_barrierattr_setpshared</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_cancel.txt">pthread_cancel</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_cleanup_pop.txt">pthread_cleanup_pop</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_cleanup_push.txt">pthread_cleanup_push</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_cond_broadcast.txt">pthread_cond_broadcast</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_cond_destroy.txt">pthread_cond_destroy</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_cond_init.txt">pthread_cond_init</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_cond_signal.txt">pthread_cond_signal</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_cond_timedwait.txt">pthread_cond_timedwait</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_cond_wait.txt">pthread_cond_wait</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_condattr_destroy.txt">pthread_condattr_destroy</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_condattr_getclock.txt">pthread_condattr_getclock</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_condattr_getpshared.txt">pthread_condattr_getpshared</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_condattr_init.txt">pthread_condattr_init</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_condattr_setclock.txt">pthread_condattr_setclock</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_condattr_setpshared.txt">pthread_condattr_setpshared</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_create.txt">pthread_create</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_detach.txt">pthread_detach</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_equal.txt">pthread_equal</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_exit.txt">pthread_exit</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_getconcurrency.txt">pthread_getconcurrency</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_getcpuclockid.txt">pthread_getcpuclockid</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_getschedparam.txt">pthread_getschedparam</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_getspecific.txt">pthread_getspecific</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_join.txt">pthread_join</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_key_create.txt">pthread_key_create</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_key_delete.txt">pthread_key_delete</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_kill.txt">pthread_kill</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_mutex_destroy.txt">pthread_mutex_destroy</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_mutex_getprioceiling.txt">pthread_mutex_getprioceiling</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_mutex_init.txt">pthread_mutex_init</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_mutex_lock.txt">pthread_mutex_lock</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_mutex_setprioceiling.txt">pthread_mutex_setprioceiling</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_mutex_timedlock.txt">pthread_mutex_timedlock</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_mutex_trylock.txt">pthread_mutex_trylock</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_mutex_unlock.txt">pthread_mutex_unlock</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_mutexattr_destroy.txt">pthread_mutexattr_destroy</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_mutexattr_getprioceiling.txt">pthread_mutexattr_getprioceiling</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_mutexattr_getprotocol.txt">pthread_mutexattr_getprotocol</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_mutexattr_getpshared.txt">pthread_mutexattr_getpshared</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_mutexattr_gettype.txt">pthread_mutexattr_gettype</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_mutexattr_init.txt">pthread_mutexattr_init</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_mutexattr_setprioceiling.txt">pthread_mutexattr_setprioceiling</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_mutexattr_setprotocol.txt">pthread_mutexattr_setprotocol</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_mutexattr_setpshared.txt">pthread_mutexattr_setpshared</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_mutexattr_settype.txt">pthread_mutexattr_settype</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_once.txt">pthread_once</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_rwlock_destroy.txt">pthread_rwlock_destroy</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_rwlock_init.txt">pthread_rwlock_init</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_rwlock_rdlock.txt">pthread_rwlock_rdlock</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_rwlock_timedrdlock.txt">pthread_rwlock_timedrdlock</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_rwlock_timedwrlock.txt">pthread_rwlock_timedwrlock</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_rwlock_tryrdlock.txt">pthread_rwlock_tryrdlock</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_rwlock_trywrlock.txt">pthread_rwlock_trywrlock</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_rwlock_unlock.txt">pthread_rwlock_unlock</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_rwlock_wrlock.txt">pthread_rwlock_wrlock</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_rwlockattr_destroy.txt">pthread_rwlockattr_destroy</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_rwlockattr_getpshared.txt">pthread_rwlockattr_getpshared</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_rwlockattr_init.txt">pthread_rwlockattr_init</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_rwlockattr_setpshared.txt">pthread_rwlockattr_setpshared</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_self.txt">pthread_self</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_setcancelstate.txt">pthread_setcancelstate</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_setcanceltype.txt">pthread_setcanceltype</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_setconcurrency.txt">pthread_setconcurrency</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_setschedparam.txt">pthread_setschedparam</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_setschedprio.txt">pthread_setschedprio</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_setspecific.txt">pthread_setspecific</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_sigmask.txt">pthread_sigmask</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_spin_destroy.txt">pthread_spin_destroy</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_spin_init.txt">pthread_spin_init</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_spin_lock.txt">pthread_spin_lock</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_spin_trylock.txt">pthread_spin_trylock</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_spin_unlock.txt">pthread_spin_unlock</a>
<br /><a href="https://computing.llnl.gov/tutorials/pthreads/man/pthread_testcancel.txt">pthread_testcancel</a>
</p>
</div>
</div>
<div id="footnotes">
<h2 class="footnotes">Footnotes: </h2>
<div id="text-footnotes">

<div class="footdef"><sup><a id="fn.1" name="fn.1" class="footnum" href="#fnr.1">1</a></sup> <p class="footpara">
<a href="http://maxim.int.ru/bookshelf/PthreadsProgram/htm/r_19.html">http://maxim.int.ru/bookshelf/PthreadsProgram/htm/r_19.html</a>
</p></div>

<div class="footdef"><sup><a id="fn.2" name="fn.2" class="footnum" href="#fnr.2">2</a></sup> <p class="footpara">
<a href="https://computing.llnl.gov/?set=code&amp;page=software_tools#perftools">https://computing.llnl.gov/?set=code&amp;page=software_tools#perftools</a>
</p></div>


</div>
</div>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Multithreading相关术语总结]]></title>
    <link href="http://dreamrunner.org/blog/2014/07/05/multithreadingxiang-guan-zhu-yu-zong-jie/"/>
    <updated>2014-07-05T23:23:52+08:00</updated>
    <id>http://dreamrunner.org/blog/2014/07/05/multithreadingxiang-guan-zhu-yu-zong-jie</id>
    <content type="html"><![CDATA[<p>在谈到内存模型,Multithreading,尤其 lock-free programmming 等时,总会遇到一些相关术语来描述,如 Memory Barrier,Acquire semantics,Release
semantics,happens-before relation 等.在这里稍微整理一下.</p>

<!-- more -->

<h2 id="memory-barriers">Memory Barriers</h2>

<p>在之前
<a href="http://dreamrunner.org/blog/2014/06/28/qian-tan-memory-reordering/">浅谈 Memory Reordering</a>
中谈到编译器 reordering 和在多核下的处理器的 reordering,在 lock-free
programming 中,如果不控制好这两者的 reordering 就会引起上文中所不想的结果.</p>

<p>你可以通过指令强制 CPU 和编译器在内存处理上的顺序,这些指令就被成为
<a href="http://en.wikipedia.org/wiki/Memory_barrier">Memory Barrier</a>.</p>

<p>有很多指令作为 memory barriers,所以需要知道很多不同类型的 memory
barriers. <a href="http://g.oswego.edu/dl/jmm/cookbook.html">Doug Lea 指出</a>如下的四大类可以很好的归纳在 CPU 上的特殊指令.尽管不是完全,大多数时候,一个正真的 CPU 指令执行包含上面 barrier 类型的各种组合,或附带其他效果.无论如何,
一旦你理解了这四种类型的 memory barriers,你就很好的理解了大部分真正 CPU
的关于内存约束的指令.
<a href="http://preshing.com/20120710/memory-barriers-are-like-source-control-operations/">Memory Barriers Are Like Source Control Operations</a>
这篇把 Memory Barriers 与 Source Control 作类比,熟悉 Source Control 机制的可以很形象的理解各类 Memory Barriers 机制.</p>

<p><img class="center" src="http://dreamrunner.org/images/blog/2014/multithreading/memory_barriers_types.png" title="'memory_barriers_types'" /></p>

<h3 id="loadload">LoadLoad</h3>

<p>顺序: Load1; <strong>LoadLoad</strong>; Load2</p>

<p>保证 Load1 的数据加载在被 load2 和之后的 load 指令读取加载之前.是一个比较好的方法防止看到旧的数据.以这个经典的例子,CPU1 检查一个共享的标识变量 flag 来确认一些数据是否被 CPU1 更新.如果标识变量 flag 是 true 的话,把<code>LoadLoad</code>barrier
放在读取更新数据之前:</p>

<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
</pre></td><td class="code"><pre><code class="c++"><span class="line"><span class="k">if</span> <span class="p">(</span><span class="n">is_updated</span><span class="p">)</span> <span class="p">{</span>
</span><span class="line">    <span class="n">LOADLOAD_FENCE</span><span class="p">();</span>  <span class="c1">// Prevent reordering of loads</span>
</span><span class="line">    <span class="k">return</span> <span class="n">value</span><span class="p">;</span>  <span class="c1">// Load updated value</span>
</span><span class="line"><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure></notextile></div>

<p>只要<code>is_updated</code>被 CPU1 看到为 true, <code>LoadLoad</code>fence 防止 CPU1 读到比标识变量 flag 本身旧的<code>value</code>.</p>

<h3 id="storestore">StoreStore</h3>

<p>顺序: Store1; <strong>StoreStore</strong>; Store2</p>

<p>保证 Store1 的数据被其他 CPU 看到在与这数据相关的 Store2 和之后的 store 指令之前.同样,它足够的防止其他 CPU 看到自己的旧数据.同上一样的例子,CPU1 需要更新一些数据到共享的内存中,把<code>StoreStore</code> barrier 放在标识变量 flag 是 true
之前:</p>

<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
</pre></td><td class="code"><pre><code class="c++"><span class="line"><span class="n">value</span> <span class="o">=</span> <span class="n">x</span><span class="p">;</span>
</span><span class="line"><span class="n">STORESTORE_FENCE</span><span class="p">();</span>
</span><span class="line"><span class="n">is_updated</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>  <span class="c1">// Set shared flag to show the update of data</span>
</span></code></pre></td></tr></table></div></figure></notextile></div>

<p>一旦其他 CPU 看到<code>is_updated</code>为 true,它能自信它看到正确的<code>value</code>值.而且
<code>value</code>不需要原子类型,它可以是一个包含很多元素的大数据结构.</p>

<h3 id="loadstore">LoadStore</h3>

<p>顺序: Load1; <strong>LoadStore</strong>; Store2</p>

<p>保证 Load1 的数据被加载在与这数据相关的 Store2 和之后的 store 指令之前.</p>

<h3 id="storeload">StoreLoad</h3>

<p>顺序: Store1; <strong>StoreLoad</strong>; Load2</p>

<p>保证 Store1 的数据被其他 CPU 看到在数据被 Load2 和之后的 load 指令加载之前.也就是说,它有效的防止所有 barrier 之前的 stores 与所有 barrier 之后的 load 乱序.</p>

<p><code>StoreLoad</code>是唯一的.它是唯一的 memory barrier 类型来防止<code>r1=r2=0</code>在之前
<a href="http://dreamrunner.org/blog/2014/06/28/qian-tan-memory-reordering/#memory-ordering-at-processor-time">Memory ordering at processor time</a>
中给出的例子.</p>

<p><code>StoreLoad</code>有什么区别与<code>StoreStore</code>之后跟<code>LoadLoad</code>?虽然,<code>StoreStore</code>按序把存储改变推送到主内存中,<code>LoadLoad</code>按序把改变加载过来,但是这两种类型的 barrier 是不够的.Store 可以延迟任意的指令,以致在 Load
之后,Load 也可以不是加载最新 Store 之后的内容.这就是为啥 PowerPC 的指令
<code>lwsync</code>,包含这三种 memory barriers,<code>LoadLoad</code>,<code>LoadStore</code>和
<code>StoreStore</code>,但不包含<code>StoreLoad</code>,是不足以防止<code>r1=r2=0</code>在那个实例中.</p>

<h3 id="data-dependency-barriers">Data dependency barriers</h3>

<p>除了上面 4 大类,还有<code>Loadload</code>的弱化模式的<code>Data dependency barrier</code>.如
<code>LoadLoad</code>类似,在两个 load 顺序执行,load2 依赖于 load1 的结果,<code>Data
dependency barrier</code>需要插入保证两者的顺序.</p>

<p>但与<code>LoadLoad</code>不同,<code>Data dependency barrier</code>只是部分顺序约束在内在以来的 load,就是 load1 必须与 load2 是 <strong>data</strong> dependency 而不是仅仅是
<strong>control</strong> dependency.</p>

<ul>
  <li>data dependency</li>
</ul>

<p>r1 与 r2 之间是 data dependency.</p>

<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
</pre></td><td class="code"><pre><code class="c"><span class="line"><span class="n">r1</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
</span><span class="line"><span class="n">r2</span> <span class="o">=</span> <span class="n">r1</span><span class="p">;</span>
</span></code></pre></td></tr></table></div></figure></notextile></div>

<ul>
  <li>control dependency</li>
</ul>

<p>r1 与 r2 之间是 control dependency.</p>

<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
<span class="line-number">5</span>
<span class="line-number">6</span>
</pre></td><td class="code"><pre><code class="c"><span class="line"><span class="n">r1</span> <span class="o">=</span> <span class="n">value</span><span class="p">;</span>
</span><span class="line"><span class="k">if</span> <span class="p">(</span><span class="n">r1</span><span class="p">)</span> <span class="p">{</span>
</span><span class="line">    <span class="n">r2</span> <span class="o">=</span> <span class="n">r1</span><span class="p">;</span>
</span><span class="line"><span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span><span class="line">    <span class="n">r2</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
</span><span class="line"><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure></notextile></div>

<h3 id="more">More</h3>

<ul>
  <li><a href="https://www.kernel.org/doc/Documentation/memory-barriers.txt">LINUX KERNEL MEMORY BARRIERS</a> </li>
  <li><a href="www.rdrop.com/users/paulmck/scalability/paper/whymb.2010.07.23a.pdf">Memory Barriers: a Hardware View for Software Hackers</a></li>
</ul>

<h2 id="acquire-and-release-semantics">Acquire and Release semantics</h2>

<p>在 lock-free programming 中,共享内存被多个线程通过合作传递信息来处理,在这种处理下,acquire 和 release semantics 是关键技术保证可靠的传递信息在线程之间.</p>

<p>acqure 和 release semantics 并没有好的被定义,这里借用 Jeff Preshing 在
<a href="http://preshing.com/20120913/acquire-and-release-semantics/">这里</a>给予的定义:</p>

<p><img class="right" src="http://dreamrunner.org/images/blog/2014/multithreading/read_acquire.png" width="170" height="110" title="'read_acquire'" /></p>

<p><strong>Acquire semantics</strong> 是一种只能应用于如下操作的性质: 从共享内存读取,无论是
<a href="http://en.wikipedia.org/wiki/Read-modify-write">read-modify-write</a> 操作还是普通的加载.这一操作被认为是一个 <strong>read acquire</strong>. Acquire
semantics 防止 read acquire 程序上<strong>之后</strong>的任何读或写操作与它的内存乱序.</p>

<p><br /></p>

<p><img class="right" src="http://dreamrunner.org/images/blog/2014/multithreading/write_release.png" width="170" height="110" title="'write_release'" /></p>

<p><strong>Release semantics</strong> 是一种只能应用于如下操作的性质: 写入到共享内存,
无论是 read-modify-write 操作还是普通的存储.这一操作被认为是一个 <strong>write release</strong>.
Release semantics 防止 write release 程序上<strong>之前</strong>的任何读或写操作与它的乱序.</p>

<p>Acqure 和 release semantics 能通过之前四种 memory barrier 的简单组合来达到.</p>

<p><img class="center" src="http://dreamrunner.org/images/blog/2014/multithreading/acquire_release_semantics.png" title="'acquire_release_semantics'" /></p>

<p>Acqure 和 release semantics 可以基本划分为如下结构:</p>

<p><img class="center" src="http://dreamrunner.org/images/blog/2014/multithreading/acquire_release_semantics_category.png" title="'acquire_release_semantics_category'" /></p>

<h3 id="fence-">使用明确的平台相关 Fence 指令</h3>

<p>在 X86/64 使用<code>mefence</code>指令,mfence 是一个满足全部 memory barrier,防止任何类型的内存乱序.</p>

<p><img class="center" src="http://dreamrunner.org/images/blog/2014/multithreading/platform-specific_fence.png" title="'platform-specific_fence'" /></p>

<h3 id="c11--fences">可移植的 C++11 的 Fences</h3>

<p>C++11 的 atomic 库定义了一个可移植的函数<code>atomic_thread_fence()</code>,输入一个变量来指定什么类型的 fence.</p>

<p><img class="center" src="http://dreamrunner.org/images/blog/2014/multithreading/fence_in_c++11.png" title="'fence_in_c++11'" /></p>

<h3 id="c11--atomic-fence">可移植的 C++11 的 atomic,非明确的 fence</h3>

<p>在 C++11 中,可以直接对 atomic 变量直接约束 fence,而不是显示的明确 fence.与上面明确 fence 相比,这实际是更优的方法来表达 acquire and release semantics
在 C++11 中.</p>

<p><img class="center" src="http://dreamrunner.org/images/blog/2014/multithreading/without_fence_c++11.png" title="'without_fence_c++11'" /></p>

<h2 id="happens-before-relation">Happens-before relation</h2>

<p><em>Happens-before</em> 是一个术语来描述 C++11,Java,LLVM 之类背后的<a href="http://dreamrunner.org/blog/2014/06/28/qian-tan-memory-reordering/#weak-vs-strong-memory-models">软件内存模型</a>.</p>

<p>在之上每个语言里都能找到* happends-before *的定义,尽管每个都有不同的说法,但内在意思基本一致.粗略地讲,基本定义如下:</p>

<blockquote><p>A 和 B 表示一个多线程进行的操作.若 A <strong>happens-before</strong> B,那么,在 B 进行前,A 对 B 的内存影响有效的被 B 看到.</p></blockquote>

<p>无论使用任何编程语言,它们都有一个共同处:如果操作 A 和 B 被同一个进程进行,A
的语句在 B 的语句之前在程序顺序上,那么 A <em>优先发生(happens-before)</em>B.这也是在之前
<a href="http://dreamrunner.org/blog/2014/06/28/qian-tan-memory-reordering/#weak-vs-strong-memory-models">Memory ordering</a>
中谈到中心原则.</p>

<p>这里再次提一下指令重排序问题,有人有如下疑问: 指令重排序会破坏
happens-before 原则吗？happens-before 的程序次序原则说：在一个线程内，按照程序代码顺序，书写在前面的操作会先行发生于书写在后面的操作。如果线程内出现指令重排序，那不是破坏了程序次序原则了吗？</p>

<p>是会破坏程序次序的执行,但是并不破坏 happens-before 原则,并不造成内存对单线程有效性的破坏.这里主要的困惑是时间上顺序的发生之前(happening
before)与先行发生(happens-before)两者关系.</p>

<p>时间上顺序的发生在前于(happening before)与先行发生(happens-before)两者是不一样的,基本没太大关系.特别:</p>

<ol>
  <li>A 先行发生(happens-before)B 并不意味着 A 发生在前于(happening before)B.</li>
  <li>A 发生在前于(happening before)B 并不意味 A 先行发生(happens-before)B.</li>
</ol>

<p>谨记 happens-before 是由一系列编程语言特定定义的操作间的关系,它的存在独立于时间的概念.</p>

<h3 id="happens-before--happening-before">happens-before 并不意味 happening before</h3>

<p>如下例子有 happens-before 关系但并不是顺序执行,没有 happening before.如下代码:(1) 存储到 A,之后(2)存储到 B.根据程序顺序原则,(1) happens-before (2).</p>

<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
<span class="line-number">5</span>
</pre></td><td class="code"><pre><code class="c++"><span class="line"><span class="kt">int</span> <span class="n">A</span><span class="p">,</span> <span class="n">B</span><span class="p">;</span>
</span><span class="line"><span class="kt">void</span> <span class="n">test</span><span class="p">()</span> <span class="p">{</span>
</span><span class="line">  <span class="n">A</span> <span class="o">=</span> <span class="n">B</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>  <span class="c1">// (1)</span>
</span><span class="line">  <span class="n">B</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>  <span class="c1">// (2)</span>
</span><span class="line"><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure></notextile></div>

<p>用 O2 打开优化编译的如下:</p>

<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
<span class="line-number">5</span>
<span class="line-number">6</span>
</pre></td><td class="code"><pre><code class="sh"><span class="line"><span class="nv">$ </span>gcc -S -O2  -masm<span class="o">=</span>intel test.c
</span><span class="line">
</span><span class="line">	mov	eax, DWORD PTR B
</span><span class="line">	mov	DWORD PTR B, 0
</span><span class="line">	add	eax, 1
</span><span class="line">	mov	DWORD PTR A, eax
</span></code></pre></td></tr></table></div></figure></notextile></div>

<p>从汇编指令看出,第二句<code>mov DWORD PTR B, 0</code>就已经完成对<code>B</code>的存储,但是对<code>A</code>的存储还没进行.(1)顺序上并没有在(2)之前执行!</p>

<p>但是 happens-before 原则有被违背吗?根据定义,(1)的内存效用必须有效被看到在进行(2)之前.也就是存储 A 必须影响存储 B.</p>

<p>在这里,存储 A 实际并没有影响存储 B.(2)被提前执行与之后执行仍然一样,相当与
(1)的内存有效性是一样的.因此,这并不算违背 happens-before 原则.</p>

<h3 id="happening-before--happens-before">happening before 并不意味 happens-before</h3>

<p>这是个时间上发生于前但并含有 happens-before 关系的例子.如下的代码,想象一个线程调用<code>UpdateValue</code>,而另一个线程调用<code>ConsumeValue</code>.因为处理共享的数据并行的,为了简单,认为普通的读取和存储<code>int</code>是 atomic 的.因为程序顺序原则,在(1)和(2)之间 happens-before 关系,(3)和(4)之间 happens-before 关系.</p>

<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
<span class="line-number">5</span>
<span class="line-number">6</span>
<span class="line-number">7</span>
<span class="line-number">8</span>
<span class="line-number">9</span>
<span class="line-number">10</span>
<span class="line-number">11</span>
<span class="line-number">12</span>
</pre></td><td class="code"><pre><code class="c++"><span class="line"><span class="kt">int</span> <span class="n">value</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span><span class="line"><span class="kt">int</span> <span class="n">updated</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span><span class="line">
</span><span class="line"><span class="kt">void</span> <span class="n">UpdateValue</span><span class="p">()</span> <span class="p">{</span>
</span><span class="line">    <span class="n">value</span> <span class="o">=</span> <span class="mi">123</span><span class="p">;</span>  <span class="c1">// (1)</span>
</span><span class="line">    <span class="n">update</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>  <span class="c1">// (2)</span>
</span><span class="line"><span class="p">}</span>
</span><span class="line">
</span><span class="line"><span class="kt">void</span> <span class="n">ConsumeValue</span><span class="p">()</span> <span class="p">{</span>
</span><span class="line"><span class="k">if</span> <span class="p">(</span><span class="n">update</span><span class="p">)</span> <span class="p">{</span>  <span class="c1">// (3)</span>
</span><span class="line">    <span class="n">printf</span><span class="p">(</span><span class="s">&quot;%d</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">,</span> <span class="n">value</span><span class="p">);</span>  <span class="c1">// (4)</span>
</span><span class="line"><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure></notextile></div>

<p>进一步假设在运行开始的时候,(3)读取<code>update</code>到为 1,这个值是有(2)在另外个线程中存储的.这里,我们可以得出时间顺序上(2)必须发生前于(3).但是这里并没有规则意味着在(2)和(3)之间有 happens-before 关系.(2)和(3)之间没有
happens-before 关系,(1)和(4)之间也没有 happens-before 关系.因此,(1)和(4)
的内存可以重排序,因为编译器重排序或在 CPU 上内存重排序,以致(4)可以打印
“0”,即使(3)读到 1.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[浅谈Mutex (Lock)]]></title>
    <link href="http://dreamrunner.org/blog/2014/06/29/qian-tan-mutex-lock/"/>
    <updated>2014-06-29T20:52:09+08:00</updated>
    <id>http://dreamrunner.org/blog/2014/06/29/qian-tan-mutex-lock</id>
    <content type="html"><![CDATA[<p><a href="http://en.wikipedia.org/wiki/Mutual_exclusion">Mutex</a>(又叫 Lock),在多线程中,作为同步的基本类型,用来保证没有两个线程或进程同时在他们的关键区域.因为 Mutex 这种排它性,很多人认为 Mutex 开销很大,尽量避免使用它.就如这篇分析完共享数据问题后,进一步分析说明
<a href="http://courses.cs.washington.edu/courses/cse451/03wi/section/prodcons.htm">Avoiding locks</a>
来解决这个问题.但 Mutex 真的开销如此大,还是被大家误解了?Matthew
Dillon <a href="http://groups.google.com/group/net.micro.mac/msg/752d18de371bd65c?dmode=source">写道</a>,”Most
people have the misconception that locks are slow.”, Jeff Preshing 也
<a href="http://preshing.com/20111118/locks-arent-slow-lock-contention-is/">写了这篇”Locks Aren’t Slow; Lock Contention Is”</a>.</p>

<p>那么接下来做 3 个关于 Mutex 的 Benchmark,具体分析一下 Mutex 的开销如何,最后并利用原子操作和 semaphore 实现一个 lightweight Mutex.</p>

<!-- more -->

<p>一个 Mutex 仅仅从 Lock 到 Unlock 具体开销是多少,是不是占用很多时间,从
<a href="http://preshing.com/20111124/always-use-a-lightweight-mutex/">Always Use a Lightweight Mutex</a>
从可以看到在 windows 中有两种
Mutex:<a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms684266%28v=vs.85%29.aspx">Muetx</a>
和
<a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms682530%28v=vs.85%29.aspx">Critical Section</a>,
重量级和轻量级的区别,两者的时间开销相差 25 倍多,所以一直使用轻量级的 Mutex.</p>

<p><a href="http://ridiculousfish.com/blog/posts/barrier.html">这篇文章</a>在高强度下 lock 的性能:每个线程做任何事情都占用 lock(高冲突),lock 占用极短的时间
(高频率).值得一读,但是在实际应用中,基本避免如此使用 locks.这里对
Mutex Contention 和 Mutex Frequency 都做最好和最坏场景的使用测试.</p>

<p>Mutex 被灌以避免使用也因为其他原因.现在有很多大家熟知的
<a href="en.wikipedia.org/wiki/Non-blocking_algorithma">lock-free programming</a>
技术.Lock-free 编程非常具有挑战性,但在实际场景中获得巨大的性能.既然有
lock-free 的技术吸引我们使用它们,那么 locks 就显得索然无味了.</p>

<p>但也不能因此忽略 lock.因为在实际很多场景,它仍然是利器.</p>

<h2 id="lightweight-mutex-benchmark">Lightweight Mutex Benchmark</h2>

<p>Linux 下的 POSIX thread 是轻量级的 Mutex.基于 Linux 特有的
<a href="http://en.wikipedia.org/wiki/Futex">futex</a> 技术,当没有其他线程竞争锁时它被优化过.使用如下简单的例子,测试一个单线程 lock 和 unlock,所有代码在 <a href="https://github.com/shishougang/blog_multithreading/tree/master/mutex_time">Github 上</a>.</p>

<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
<span class="line-number">5</span>
<span class="line-number">6</span>
<span class="line-number">7</span>
</pre></td><td class="code"><pre><code class="c++"><span class="line"><span class="n">pthread_mutex_init</span><span class="p">(</span><span class="o">&amp;</span><span class="n">lock</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">);</span>
</span><span class="line"><span class="k">const</span> <span class="kt">int</span> <span class="n">kN</span> <span class="o">=</span> <span class="mi">1000000</span><span class="p">;</span>
</span><span class="line"><span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">kN</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
</span><span class="line">    <span class="n">pthread_mutex_lock</span><span class="p">(</span><span class="o">&amp;</span><span class="n">lock</span><span class="p">);</span>
</span><span class="line">    <span class="n">pthread_mutex_unlock</span><span class="p">(</span><span class="o">&amp;</span><span class="n">lock</span><span class="p">);</span>
</span><span class="line"><span class="p">}</span>
</span><span class="line"><span class="n">pthread_mutex_destroy</span><span class="p">(</span><span class="o">&amp;</span><span class="n">lock</span><span class="p">);</span>
</span></code></pre></td></tr></table></div></figure></notextile></div>

<p>插入相应的时间代码,算出 10 万次的单线程 lock/unlock 平均时间.在不同的处理器下,结果如下:</p>

<p><img class="center" src="http://dreamrunner.org/images/blog/2014/multithreading/mutex_benchmark.png" width="450" height="200" title="'mutex_benchmark'" /></p>

<p>如果假设一个线程每分钟获取 1e5 次 mutex,并且没有其他线程与它竞争.基于如下的图,可预计 0.2%到 0.4%的开销.不算差.在比较低频率下,开销基本忽略不计.之后 <a href="http://dreamrunner.org/blog/2014/06/29/qian-tan-mutex-lock#build-own-lightweight-mutex">Build own lightweight mutex</a>,会利用 <a href="http://en.wikipedia.org/wiki/Semaphore_%28programming%29">semaphore</a> 和一个原子操作,实现一个 lightweight mutex.</p>

<p>POSIX thread 与 Windows Critical Section 不同,它不仅支持线程间的同步,
还支持进程间的同步.实例代码如下:</p>

<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span>mutex_between_process.cc</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
<span class="line-number">5</span>
<span class="line-number">6</span>
<span class="line-number">7</span>
<span class="line-number">8</span>
<span class="line-number">9</span>
<span class="line-number">10</span>
<span class="line-number">11</span>
<span class="line-number">12</span>
<span class="line-number">13</span>
</pre></td><td class="code"><pre><code class="c++"><span class="line"><span class="n">pthread_mutex_t</span> <span class="n">mutex</span><span class="p">;</span>
</span><span class="line"><span class="n">pthread_mutexattr_t</span> <span class="n">attrmutex</span><span class="p">;</span>
</span><span class="line">
</span><span class="line"><span class="cm">/* Initialise attribute to mutex. */</span>
</span><span class="line"><span class="n">pthread_mutexattr_init</span><span class="p">(</span><span class="o">&amp;</span><span class="n">attrmutex</span><span class="p">);</span>
</span><span class="line"><span class="n">pthread_mutexattr_setpshared</span><span class="p">(</span><span class="o">&amp;</span><span class="n">attrmutex</span><span class="p">,</span> <span class="n">PTHREAD_PROCESS_SHARED</span><span class="p">);</span>
</span><span class="line"><span class="n">pthread_mutex_init</span><span class="p">(</span><span class="o">&amp;</span><span class="n">mutex</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">attrmutex</span><span class="p">);</span>
</span><span class="line">
</span><span class="line"><span class="cm">/* Use the mutex. */</span>
</span><span class="line">
</span><span class="line"><span class="cm">/* Clean up. */</span>
</span><span class="line"><span class="n">pthread_mutex_destroy</span><span class="p">(</span><span class="n">pmutex</span><span class="p">);</span>
</span><span class="line"><span class="n">pthread_mutexattr_destroy</span><span class="p">(</span><span class="o">&amp;</span><span class="n">attrmutex</span><span class="p">);</span>
</span></code></pre></td></tr></table></div></figure></notextile></div>

<h2 id="mutex-contention-benchmark">Mutex Contention Benchmark</h2>

<p>在测试中,产生一个不断生成随机数的线程,使用自己编制的线程安全的
<a href="http://en.wikipedia.org/wiki/Mersenne_twister">Mersenne Twister</a> 实现代码.每过一段时间,它获取和释放一个锁,获取和释放锁之间的时间每次是随机的,但是总的平均时间是提前设计好的.这个随机的过程就是个泊松分布过程,计算出产生一个随机数的平均时间 6.25 ns 在 2.93 GHz i7 上,把它作为运行单位.利用
<a href="http://wiki.dreamrunner.org/public_html/Algorithms/Theory%20of%20Algorithms/poisson-process.html">Poisson Process</a>
的算法决定运行多少个运行单位在获取和释放锁之间.并利用
<a href="http://dreamrunner.org/blog/2014/06/24/high-resolution-time/">High Resolution Time</a>API
计算时间.这个线程的代码如下,所有代码在 <a href="https://github.com/shishougang/blog_multithreading/tree/master/mutex_contention">Github 上</a>:</p>

<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
<span class="line-number">5</span>
<span class="line-number">6</span>
<span class="line-number">7</span>
<span class="line-number">8</span>
<span class="line-number">9</span>
<span class="line-number">10</span>
<span class="line-number">11</span>
<span class="line-number">12</span>
<span class="line-number">13</span>
<span class="line-number">14</span>
<span class="line-number">15</span>
<span class="line-number">16</span>
<span class="line-number">17</span>
<span class="line-number">18</span>
<span class="line-number">19</span>
<span class="line-number">20</span>
<span class="line-number">21</span>
<span class="line-number">22</span>
<span class="line-number">23</span>
<span class="line-number">24</span>
<span class="line-number">25</span>
<span class="line-number">26</span>
<span class="line-number">27</span>
<span class="line-number">28</span>
<span class="line-number">29</span>
<span class="line-number">30</span>
<span class="line-number">31</span>
<span class="line-number">32</span>
</pre></td><td class="code"><pre><code class="c++"><span class="line">  <span class="n">GetMonotonicTime</span><span class="p">(</span><span class="o">&amp;</span><span class="n">start</span><span class="p">);</span>
</span><span class="line">  <span class="k">for</span> <span class="p">(;;)</span> <span class="p">{</span>
</span><span class="line">    <span class="n">work_units</span> <span class="o">=</span> <span class="k">static_cast</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="p">(</span><span class="n">random</span><span class="p">.</span><span class="n">PoissonInterval</span><span class="p">(</span>
</span><span class="line">        <span class="n">global_state</span><span class="p">.</span><span class="n">average_unlock_count</span><span class="p">)</span> <span class="o">+</span> <span class="mf">0.5f</span><span class="p">);</span>
</span><span class="line">    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">work_units</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
</span><span class="line">      <span class="n">random</span><span class="p">.</span><span class="n">Integer</span><span class="p">();</span>
</span><span class="line">    <span class="p">}</span>
</span><span class="line">    <span class="n">thread_stats</span><span class="p">.</span><span class="n">workdone</span> <span class="o">+=</span> <span class="n">work_units</span><span class="p">;</span>
</span><span class="line">
</span><span class="line">    <span class="n">GetMonotonicTime</span><span class="p">(</span><span class="o">&amp;</span><span class="n">end</span><span class="p">);</span>
</span><span class="line">    <span class="n">elapsed_time</span> <span class="o">=</span> <span class="n">GetElapsedTime</span><span class="p">(</span><span class="o">&amp;</span><span class="n">start</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">end</span><span class="p">);</span>
</span><span class="line">    <span class="k">if</span> <span class="p">(</span><span class="n">elapsed_time</span> <span class="o">&gt;=</span> <span class="n">global_state</span><span class="p">.</span><span class="n">time_limit</span><span class="p">)</span> <span class="p">{</span>
</span><span class="line">      <span class="k">break</span><span class="p">;</span>
</span><span class="line">    <span class="p">}</span>
</span><span class="line">
</span><span class="line">    <span class="c1">// Do some work while holding the lock</span>
</span><span class="line">    <span class="n">pthread_mutex_lock</span><span class="p">(</span><span class="o">&amp;</span><span class="n">global_state</span><span class="p">.</span><span class="n">thread_mutex</span><span class="p">);</span>
</span><span class="line">    <span class="n">work_units</span> <span class="o">=</span> <span class="k">static_cast</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="p">(</span><span class="n">random</span><span class="p">.</span><span class="n">PoissonInterval</span><span class="p">(</span>
</span><span class="line">        <span class="n">global_state</span><span class="p">.</span><span class="n">average_locked_count</span><span class="p">)</span> <span class="o">+</span> <span class="mf">0.5f</span><span class="p">);</span>
</span><span class="line">    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">work_units</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
</span><span class="line">      <span class="n">random</span><span class="p">.</span><span class="n">Integer</span><span class="p">();</span>
</span><span class="line">    <span class="p">}</span>
</span><span class="line">    <span class="n">thread_stats</span><span class="p">.</span><span class="n">workdone</span> <span class="o">+=</span> <span class="n">work_units</span><span class="p">;</span>
</span><span class="line">    <span class="n">pthread_mutex_unlock</span><span class="p">(</span><span class="o">&amp;</span><span class="n">global_state</span><span class="p">.</span><span class="n">thread_mutex</span><span class="p">);</span>
</span><span class="line">
</span><span class="line">    <span class="n">thread_stats</span><span class="p">.</span><span class="n">iterations</span><span class="o">++</span><span class="p">;</span>
</span><span class="line">    <span class="n">GetMonotonicTime</span><span class="p">(</span><span class="o">&amp;</span><span class="n">end</span><span class="p">);</span>
</span><span class="line">    <span class="n">elapsed_time</span> <span class="o">=</span> <span class="n">GetElapsedTime</span><span class="p">(</span><span class="o">&amp;</span><span class="n">start</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">end</span><span class="p">);</span>
</span><span class="line">    <span class="k">if</span> <span class="p">(</span><span class="n">elapsed_time</span> <span class="o">&gt;=</span> <span class="n">global_state</span><span class="p">.</span><span class="n">time_limit</span><span class="p">)</span> <span class="p">{</span>
</span><span class="line">      <span class="k">break</span><span class="p">;</span>
</span><span class="line">    <span class="p">}</span>
</span><span class="line">  <span class="p">}</span>
</span></code></pre></td></tr></table></div></figure></notextile></div>

<p>这里模拟获取和释放 15000 次锁每秒,从 1 个线程运行到 2 个线程,最后到 4 个线程.并且验证占用锁的时间,从 0%到 100%的每次运行时间占用锁.把 1 个线程的完成的工作量作为基准数据,其他的去除以它,计算相对增益.基本测试方案如下:</p>

<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
<span class="line-number">5</span>
</pre></td><td class="code"><pre><code class="c++"><span class="line"><span class="c1">// Test 15000 locks per second: thread number, lock_interval</span>
</span><span class="line">    <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="o">/</span><span class="mf">15000.0f</span><span class="p">,</span>
</span><span class="line">    <span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="o">/</span><span class="mf">15000.0f</span><span class="p">,</span>
</span><span class="line">    <span class="mi">3</span><span class="p">,</span> <span class="mi">1</span><span class="o">/</span><span class="mf">15000.0f</span><span class="p">,</span>
</span><span class="line">    <span class="mi">4</span><span class="p">,</span> <span class="mi">1</span><span class="o">/</span><span class="mf">15000.0f</span><span class="p">,</span>
</span></code></pre></td></tr></table></div></figure></notextile></div>

<p><img src="http://dreamrunner.org/images/blog/2014/multithreading/lock_benchmark.png" title="lock_benchmark'" /></p>

<p>从图中看出,随着锁占用的时间增加,并行性越来越差,直到最后占用 60%以后,单线程运行的更好.可以说,短时间的占用锁的时间,以 10%以内,系统达到很高的并行性.虽然并不是完美的,但是也接近.锁总体很快.</p>

<p>把这个结果放到实际中,Jeff Preshing 在
<a href="http://preshing.com/20111118/locks-arent-slow-lock-contention-is/">这篇</a>
提到,实际的游戏程序中,15000 的锁每秒来自 3 个线程,占用锁的时间相对 2%.在图中很适中的区域.</p>

<h2 id="mutex-frequency-benchmark">Mutex Frequency Benchmark</h2>

<p>尽管一个 lightweight mutex 有开销,但如上测试在 2.40GHz i5 上,lock/unlock 锁开销约 <strong>34.2ns</strong> ,因此 15000 锁每秒开销很低以致不是严重影响结果.那么把锁的每秒频率提高呢?</p>

<p>只创建 2 个线程,进行一系列的锁的每秒频率测试在 2.40GHz i5 上,从占用锁时间
10 ns(1e8/s)到 100 us(1e4/s),用单线程的占用锁时间 10 ms 作为基准工作量,其他与它比较,测试方案如下:</p>

<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
<span class="line-number">5</span>
<span class="line-number">6</span>
<span class="line-number">7</span>
<span class="line-number">8</span>
<span class="line-number">9</span>
<span class="line-number">10</span>
<span class="line-number">11</span>
<span class="line-number">12</span>
<span class="line-number">13</span>
</pre></td><td class="code"><pre><code class="c++"><span class="line">  <span class="c1">// Reference</span>
</span><span class="line">  <span class="mi">1</span><span class="p">,</span> <span class="mf">10e-3</span><span class="n">f</span><span class="p">,</span>      <span class="c1">// 10 ms        100/s</span>
</span><span class="line">
</span><span class="line">    <span class="c1">// Test various lock rates with 2 threads</span>
</span><span class="line">    <span class="mi">2</span><span class="p">,</span> <span class="mf">10e-9</span><span class="n">f</span><span class="p">,</span>      <span class="c1">// 10 ns        100000000/s</span>
</span><span class="line">    <span class="mi">2</span><span class="p">,</span> <span class="mf">31.6e-9</span><span class="n">f</span><span class="p">,</span>    <span class="c1">// 31.6 ns      31600000/s</span>
</span><span class="line">    <span class="mi">2</span><span class="p">,</span> <span class="mf">100e-9</span><span class="n">f</span><span class="p">,</span>     <span class="c1">// 100 ns       10000000/s</span>
</span><span class="line">    <span class="mi">2</span><span class="p">,</span> <span class="mf">316e-9</span><span class="n">f</span><span class="p">,</span>     <span class="c1">// 316 ns       3160000/s</span>
</span><span class="line">    <span class="mi">2</span><span class="p">,</span> <span class="mf">1e-6</span><span class="n">f</span><span class="p">,</span>       <span class="c1">// 1 us         1000000/s</span>
</span><span class="line">    <span class="mi">2</span><span class="p">,</span> <span class="mf">3.16e-6</span><span class="n">f</span><span class="p">,</span>    <span class="c1">// 3.16 us      316000/s</span>
</span><span class="line">    <span class="mi">2</span><span class="p">,</span> <span class="mf">10e-6</span><span class="n">f</span><span class="p">,</span>      <span class="c1">// 10 us        100000/s</span>
</span><span class="line">    <span class="mi">2</span><span class="p">,</span> <span class="mf">31.6e-6</span><span class="n">f</span><span class="p">,</span>    <span class="c1">// 31.6 us      31600/s</span>
</span><span class="line">    <span class="mi">2</span><span class="p">,</span> <span class="mf">100e-6</span><span class="n">f</span><span class="p">,</span>     <span class="c1">// 100 us       10000/s</span>
</span></code></pre></td></tr></table></div></figure></notextile></div>

<p><img src="http://dreamrunner.org/images/blog/2014/multithreading/frequency_benchmark.png" title="'frequency_bechmark'" /></p>

<p>如预想一样,对于非常高频率的锁,锁的开销开始减少实际工作量.在网络上,可以找到很多同样的测试.图中下边的线条,对于这样高的频率,也就是占用锁的时间很短,就一些 CPU 的指令,这样的情况下,当锁之间的工作如此简单,那么一个
lock-free 的实现更适合.</p>

<p>我们获得了一大块关于锁的性能:从它进行很好的情况,到缓慢应用的情况.在考虑实际锁的使用情况,不能说所有锁都是慢的.必须承认,很容易乱用锁,但不用太担心,任何的瓶颈问题都会在细心的 profiling 中发现.当你考虑锁是如何的稳定,
相对容易的理解它们(与 lock-free 技术相比),锁有时候其实很好用.</p>

<h2 id="build-own-lightweight-mutex">Build own lightweight mutex</h2>

<p>我们也可以实现自己的简单轻量级的 mutex,但仅仅作为教育手段,理解 mutex 一些内在实现细节,实际现在操作系统都提供轻量级的 mutex,千万不要自己实现一个并实际使用,直接只用操作系统提供的即可.</p>

<p>网络上有很多种方法在用户层写自己的 mutex:</p>

<ul>
  <li><a href="http://preshing.com/20120226/roll-your-own-lightweight-mutex/">roll-your-own-lightweight-mutex</a> 利用 Windows 提供的 semaphore 和 atomic 操作实现的 mutex.</li>
  <li><a href="http://cbloomrants.blogspot.hk/2011/07/07-15-11-review-of-many-mutex.html">Review of many Mutex implementations</a> 很长的一篇文章,总结了很多种 mutex 的实现细节.</li>
</ul>

<p>这里利用
<a href="http://www.haiku-os.org/legacy-docs/benewsletter/Issue1-26.html#Engineering1-26">Benaphore</a>
技术,在 Linux 平台上利用 <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_init.html">semaphore</a> 和 <a href="https://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Atomic-Builtins.html">atomic</a> 操作实现自己的 C++版本的
lightweight mutex.这里并没有用
<a href="http://www.open-std.org/JTC1/sc22/wg21/docs/papers/2007/n2427.html">C++11 的原子库</a>.所有代码在 <a href="https://github.com/shishougang/blog_multithreading/tree/master/benaphore_mutex">Github 上</a>.</p>

<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
<span class="line-number">5</span>
<span class="line-number">6</span>
<span class="line-number">7</span>
<span class="line-number">8</span>
<span class="line-number">9</span>
<span class="line-number">10</span>
<span class="line-number">11</span>
<span class="line-number">12</span>
<span class="line-number">13</span>
<span class="line-number">14</span>
<span class="line-number">15</span>
<span class="line-number">16</span>
<span class="line-number">17</span>
<span class="line-number">18</span>
<span class="line-number">19</span>
<span class="line-number">20</span>
<span class="line-number">21</span>
<span class="line-number">22</span>
<span class="line-number">23</span>
<span class="line-number">24</span>
<span class="line-number">25</span>
<span class="line-number">26</span>
<span class="line-number">27</span>
</pre></td><td class="code"><pre><code class="c++"><span class="line"> <span class="err">#</span><span class="n">include</span> <span class="o">&lt;</span><span class="n">semaphore</span><span class="p">.</span><span class="n">h</span><span class="o">&gt;</span>
</span><span class="line"><span class="k">class</span> <span class="nc">Benaphore</span> <span class="p">{</span>
</span><span class="line"> <span class="k">public</span><span class="o">:</span>
</span><span class="line">  <span class="n">Benaphore</span><span class="p">()</span> <span class="o">:</span> <span class="n">counter_</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span><span class="line">    <span class="n">sem_init</span><span class="p">(</span><span class="o">&amp;</span><span class="n">semaphore_</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
</span><span class="line">  <span class="p">}</span>
</span><span class="line">  <span class="o">~</span><span class="n">Benaphore</span><span class="p">()</span> <span class="p">{</span>
</span><span class="line">    <span class="n">sem_destroy</span><span class="p">(</span><span class="o">&amp;</span><span class="n">semaphore_</span><span class="p">);</span>
</span><span class="line">  <span class="p">}</span>
</span><span class="line">  <span class="kt">void</span> <span class="n">Lock</span><span class="p">()</span> <span class="p">{</span>
</span><span class="line">    <span class="k">if</span> <span class="p">(</span><span class="n">__sync_add_and_fetch</span><span class="p">(</span><span class="o">&amp;</span><span class="n">counter_</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
</span><span class="line">      <span class="n">sem_wait</span><span class="p">(</span><span class="o">&amp;</span><span class="n">semaphore_</span><span class="p">);</span>
</span><span class="line">    <span class="p">}</span>
</span><span class="line">  <span class="p">}</span>
</span><span class="line">  <span class="kt">void</span> <span class="n">Unlock</span><span class="p">()</span> <span class="p">{</span>
</span><span class="line">    <span class="k">if</span> <span class="p">(</span><span class="n">__sync_sub_and_fetch</span><span class="p">(</span><span class="o">&amp;</span><span class="n">counter_</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span><span class="line">      <span class="n">sem_post</span><span class="p">(</span><span class="o">&amp;</span><span class="n">semaphore_</span><span class="p">);</span>
</span><span class="line">    <span class="p">}</span>
</span><span class="line">  <span class="p">}</span>
</span><span class="line">  <span class="kt">bool</span> <span class="n">TryLock</span><span class="p">()</span> <span class="p">{</span>
</span><span class="line">    <span class="k">return</span> <span class="n">__sync_bool_compare_and_swap</span><span class="p">(</span><span class="o">&amp;</span><span class="n">counter_</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>
</span><span class="line">  <span class="p">}</span>
</span><span class="line">
</span><span class="line"> <span class="k">private</span><span class="o">:</span>
</span><span class="line">  <span class="kt">long</span> <span class="n">counter_</span><span class="p">;</span>
</span><span class="line">  <span class="n">sem_t</span> <span class="n">semaphore_</span><span class="p">;</span>
</span><span class="line"><span class="p">};</span>
</span></code></pre></td></tr></table></div></figure></notextile></div>

<p><a href="https://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Atomic-Builtins.html"><code>__sync_add_and_fetch</code></a>
是一个由 GCC 内部提供的 <em>atomic read-modify-write (RMW)</em> 操作,它把 1 加到某个数并且返回新的数,在同一时间所有操作由一个线程原子操作完成,其他线程不能干涉,只能在后等待.这里<code>counter_</code>初始化为 0,第一个线程调用<code>Lock</code>将得到 1 从<code>__sync_add_and_fetch</code>,然后跳过<code>sem_wait</code>,一旦这个线程占用这个锁,
之后线程都将递增<code>counter_</code>,获得大于 1 的数,从而调用<code>sem_wait</code>等待.</p>

<p>之后,第一个线程完成自己的操作,调用<code>Unlock</code>,<code>__sync_sub_and_fetch</code>的返回值大于 1 说明有其他线程在等待这个 mutex,调用<code>sem_post</code>唤醒其他线程.</p>

<h3 id="section">底层分析与性能</h3>

<p>上面使用了<code>__sync_add_and_fetch</code>,它编译成<code>lock xadd</code>指令如下.在没有竞争下的 lock/unlock 操作性能与 pthread mutex 相当.但是在 mutex 多线程竞争情况下,这个 mutex 性能没有 pthread mutex 好.</p>

<p><img src="http://dreamrunner.org/images/blog/2014/multithreading/lightweight_mutex_assembly.png" title="'lightweight_mutex_assembly'" /></p>

<h3 id="mutex-">增强 Mutex 支持递归</h3>

<p>上面简单的 lightweight mutex 的局限性是它不能递归.也就是同一个线程试图获取同样的锁两次以上,将造成死锁(deadlock).递归锁在函数调用自己时很有用.比如在内存管理代码中,可能会遇到如下代码:</p>

<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
<span class="line-number">5</span>
<span class="line-number">6</span>
<span class="line-number">7</span>
<span class="line-number">8</span>
<span class="line-number">9</span>
<span class="line-number">10</span>
<span class="line-number">11</span>
<span class="line-number">12</span>
<span class="line-number">13</span>
<span class="line-number">14</span>
<span class="line-number">15</span>
<span class="line-number">16</span>
<span class="line-number">17</span>
<span class="line-number">18</span>
<span class="line-number">19</span>
<span class="line-number">20</span>
<span class="line-number">21</span>
<span class="line-number">22</span>
<span class="line-number">23</span>
</pre></td><td class="code"><pre><code class="c++"><span class="line"><span class="n">Realloc</span><span class="p">(</span><span class="kt">void</span><span class="o">*</span> <span class="n">ptr</span><span class="p">,</span> <span class="n">size_t</span> <span class="n">size</span><span class="p">)</span>
</span><span class="line"><span class="p">{</span>
</span><span class="line">    <span class="n">LOCK</span><span class="p">;</span>
</span><span class="line">
</span><span class="line">    <span class="k">if</span> <span class="p">(</span><span class="n">ptr</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span>
</span><span class="line">    <span class="p">{</span>
</span><span class="line">        <span class="k">return</span> <span class="n">Alloc</span><span class="p">(</span><span class="n">size</span><span class="p">);</span>
</span><span class="line">    <span class="p">}</span>
</span><span class="line">    <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">size</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span>
</span><span class="line">    <span class="p">{</span>
</span><span class="line">        <span class="n">Free</span><span class="p">(</span><span class="n">size</span><span class="p">);</span>
</span><span class="line">        <span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span>
</span><span class="line">    <span class="p">}</span>
</span><span class="line">    <span class="k">else</span>
</span><span class="line">        <span class="p">...</span>
</span><span class="line"><span class="p">}</span>
</span><span class="line">
</span><span class="line"><span class="n">Alloc</span><span class="p">(</span><span class="n">size_t</span> <span class="n">size</span><span class="p">)</span>
</span><span class="line"><span class="p">{</span>
</span><span class="line">    <span class="n">LOCK</span><span class="p">;</span>
</span><span class="line">
</span><span class="line">    <span class="p">...</span>
</span><span class="line"><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure></notextile></div>

<p><code>Lock</code>是个封装好的 C++宏,用来获取锁和自动结果当退出函数.</p>

<p>可以看到,当传递<code>NULL</code>给<code>Realloc</code>,锁被<code>Realloc</code>函数获取,然后第二次被获取当<code>Alloc</code>被调用.</p>

<p>把它扩展成可递归的锁如下,加入 2 个新成员变量,<code>owner_</code>,存储当前占有线程的
ID(TID),和<code>recursion_</code>,存储递归的层数.基本代码如下:</p>

<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
<span class="line-number">5</span>
<span class="line-number">6</span>
<span class="line-number">7</span>
<span class="line-number">8</span>
<span class="line-number">9</span>
<span class="line-number">10</span>
<span class="line-number">11</span>
<span class="line-number">12</span>
<span class="line-number">13</span>
<span class="line-number">14</span>
<span class="line-number">15</span>
<span class="line-number">16</span>
<span class="line-number">17</span>
<span class="line-number">18</span>
<span class="line-number">19</span>
<span class="line-number">20</span>
<span class="line-number">21</span>
<span class="line-number">22</span>
<span class="line-number">23</span>
<span class="line-number">24</span>
<span class="line-number">25</span>
<span class="line-number">26</span>
<span class="line-number">27</span>
<span class="line-number">28</span>
<span class="line-number">29</span>
<span class="line-number">30</span>
<span class="line-number">31</span>
<span class="line-number">32</span>
<span class="line-number">33</span>
<span class="line-number">34</span>
<span class="line-number">35</span>
<span class="line-number">36</span>
<span class="line-number">37</span>
<span class="line-number">38</span>
<span class="line-number">39</span>
<span class="line-number">40</span>
<span class="line-number">41</span>
<span class="line-number">42</span>
<span class="line-number">43</span>
<span class="line-number">44</span>
<span class="line-number">45</span>
<span class="line-number">46</span>
<span class="line-number">47</span>
<span class="line-number">48</span>
<span class="line-number">49</span>
<span class="line-number">50</span>
<span class="line-number">51</span>
<span class="line-number">52</span>
<span class="line-number">53</span>
<span class="line-number">54</span>
<span class="line-number">55</span>
<span class="line-number">56</span>
<span class="line-number">57</span>
<span class="line-number">58</span>
<span class="line-number">59</span>
<span class="line-number">60</span>
<span class="line-number">61</span>
</pre></td><td class="code"><pre><code class="c++"><span class="line"> <span class="err">#</span><span class="n">include</span> <span class="o">&lt;</span><span class="n">semaphore</span><span class="p">.</span><span class="n">h</span><span class="o">&gt;</span>
</span><span class="line"> <span class="err">#</span><span class="n">include</span> <span class="o">&lt;</span><span class="n">pthread</span><span class="p">.</span><span class="n">h</span><span class="o">&gt;</span>
</span><span class="line"> <span class="err">#</span><span class="n">define</span> <span class="n">LIGHT_ASSERT</span><span class="p">(</span><span class="n">x</span><span class="p">)</span> <span class="p">{</span> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="p">(</span><span class="n">x</span><span class="p">))</span> <span class="n">__builtin_trap</span><span class="p">();</span> <span class="p">}</span>
</span><span class="line">
</span><span class="line"><span class="k">class</span> <span class="nc">RecursiveBenaphore</span> <span class="p">{</span>
</span><span class="line"> <span class="k">public</span><span class="o">:</span>
</span><span class="line">  <span class="n">RecursiveBenaphore</span><span class="p">()</span> <span class="o">:</span> <span class="n">counter_</span><span class="p">(</span><span class="mi">0</span><span class="p">),</span> <span class="n">owner_</span><span class="p">(</span><span class="mi">0</span><span class="p">),</span> <span class="n">recursion_</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span><span class="line">    <span class="n">sem_init</span><span class="p">(</span><span class="o">&amp;</span><span class="n">semaphore_</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
</span><span class="line">  <span class="p">}</span>
</span><span class="line">  <span class="o">~</span><span class="n">RecursiveBenaphore</span><span class="p">()</span> <span class="p">{</span>
</span><span class="line">    <span class="n">sem_destroy</span><span class="p">(</span><span class="o">&amp;</span><span class="n">semaphore_</span><span class="p">);</span>
</span><span class="line">  <span class="p">}</span>
</span><span class="line">  <span class="kt">void</span> <span class="n">Lock</span><span class="p">()</span> <span class="p">{</span>
</span><span class="line">    <span class="n">pthread_t</span> <span class="n">thread_id</span> <span class="o">=</span> <span class="n">pthread_self</span><span class="p">();</span>
</span><span class="line">    <span class="k">if</span> <span class="p">(</span><span class="n">__sync_add_and_fetch</span><span class="p">(</span><span class="o">&amp;</span><span class="n">counter_</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
</span><span class="line">      <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">pthread_equal</span><span class="p">(</span><span class="n">thread_id</span><span class="p">,</span> <span class="n">owner_</span><span class="p">))</span> <span class="p">{</span>
</span><span class="line">        <span class="n">sem_wait</span><span class="p">(</span><span class="o">&amp;</span><span class="n">semaphore_</span><span class="p">);</span>
</span><span class="line">      <span class="p">}</span>
</span><span class="line">    <span class="p">}</span>
</span><span class="line">    <span class="n">owner_</span> <span class="o">=</span> <span class="n">thread_id</span><span class="p">;</span>
</span><span class="line">    <span class="n">recursion_</span><span class="o">++</span><span class="p">;</span>
</span><span class="line">  <span class="p">}</span>
</span><span class="line">  <span class="kt">void</span> <span class="n">Unlock</span><span class="p">()</span> <span class="p">{</span>
</span><span class="line">    <span class="n">pthread_t</span> <span class="n">thread_id</span> <span class="o">=</span> <span class="n">pthread_self</span><span class="p">();</span>
</span><span class="line">    <span class="n">LIGHT_ASSERT</span><span class="p">(</span><span class="n">pthread_equal</span><span class="p">(</span><span class="n">thread_id</span><span class="p">,</span> <span class="n">owner_</span><span class="p">));</span>
</span><span class="line">    <span class="kt">long</span> <span class="n">recur</span> <span class="o">=</span> <span class="o">--</span><span class="n">recursion_</span><span class="p">;</span>
</span><span class="line">    <span class="k">if</span> <span class="p">(</span><span class="n">recur</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span><span class="line">      <span class="n">owner_</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span><span class="line">    <span class="p">}</span>
</span><span class="line">    <span class="kt">long</span> <span class="n">result</span> <span class="o">=</span> <span class="n">__sync_sub_and_fetch</span><span class="p">(</span><span class="o">&amp;</span><span class="n">counter_</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>
</span><span class="line">    <span class="k">if</span> <span class="p">(</span><span class="n">result</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span><span class="line">      <span class="k">if</span> <span class="p">(</span><span class="n">recur</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span><span class="line">        <span class="kt">int</span> <span class="n">sem_value</span><span class="p">;</span>
</span><span class="line">        <span class="n">sem_getvalue</span><span class="p">(</span><span class="o">&amp;</span><span class="n">semaphore_</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">sem_value</span><span class="p">);</span>
</span><span class="line">        <span class="k">if</span> <span class="p">(</span><span class="n">sem_value</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span><span class="line">          <span class="n">sem_post</span><span class="p">(</span><span class="o">&amp;</span><span class="n">semaphore_</span><span class="p">);</span>
</span><span class="line">        <span class="p">}</span>
</span><span class="line">      <span class="p">}</span>
</span><span class="line">    <span class="p">}</span>
</span><span class="line">  <span class="p">}</span>
</span><span class="line">  <span class="kt">bool</span> <span class="n">TryLock</span><span class="p">()</span> <span class="p">{</span>
</span><span class="line">    <span class="n">pthread_t</span> <span class="n">thread_id</span> <span class="o">=</span> <span class="n">pthread_self</span><span class="p">();</span>
</span><span class="line">    <span class="k">if</span> <span class="p">(</span><span class="n">pthread_equal</span><span class="p">(</span><span class="n">thread_id</span><span class="p">,</span> <span class="n">owner_</span><span class="p">))</span> <span class="p">{</span>
</span><span class="line">      <span class="n">__sync_add_and_fetch</span><span class="p">(</span><span class="o">&amp;</span><span class="n">counter_</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>
</span><span class="line">    <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span><span class="line">      <span class="kt">bool</span> <span class="n">result</span> <span class="o">=</span> <span class="n">__sync_bool_compare_and_swap</span><span class="p">(</span><span class="o">&amp;</span><span class="n">counter_</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>
</span><span class="line">      <span class="k">if</span> <span class="p">(</span><span class="n">result</span> <span class="o">==</span> <span class="kc">false</span><span class="p">)</span> <span class="p">{</span>
</span><span class="line">        <span class="k">return</span> <span class="kc">false</span><span class="p">;</span>
</span><span class="line">      <span class="p">}</span>
</span><span class="line">      <span class="n">owner_</span> <span class="o">=</span> <span class="n">thread_id</span><span class="p">;</span>
</span><span class="line">    <span class="p">}</span>
</span><span class="line">    <span class="n">recursion_</span><span class="o">++</span><span class="p">;</span>
</span><span class="line">    <span class="k">return</span> <span class="kc">true</span><span class="p">;</span>
</span><span class="line">  <span class="p">}</span>
</span><span class="line">
</span><span class="line"> <span class="k">private</span><span class="o">:</span>
</span><span class="line">  <span class="kt">long</span> <span class="n">counter_</span><span class="p">;</span>
</span><span class="line">  <span class="n">sem_t</span> <span class="n">semaphore_</span><span class="p">;</span>
</span><span class="line">  <span class="n">pthread_t</span> <span class="n">owner_</span><span class="p">;</span>
</span><span class="line">  <span class="kt">long</span> <span class="n">recursion_</span><span class="p">;</span>
</span><span class="line"><span class="p">};</span>
</span></code></pre></td></tr></table></div></figure></notextile></div>

<p>如之前一样,第一个线程调用<code>Lock</code>,设置<code>owner_</code>为自己的 TID,增加
<code>recursion_</code>到 1.如果同一个线程再次调用<code>Lock</code>,它将同时增加
<code>recursion_</code>和<code>counter_</code>.</p>

<p>之后,第一个线程完成自己的操作,调用<code>Unlock</code>,同时减少<code>recursion_</code>和<code>counter_</code>,
仅仅调用<code>sem_post</code>唤醒其他线程当<code>recursion_</code>减少到<code>0</code>.如果
<code>recursion_</code>仍然大于 0,意味着当前的线程仍然占有此锁在外层程序.</p>

<p>最后进行<strong>压力测试</strong>,建立一些线程,每个随机获取锁,随机的递归层次.代码在
<a href="https://github.com/shishougang/blog_multithreading/tree/master/benaphore_mutex">Github 上</a>.</p>

<p>一些细节问题:
* 在<code>Unlock</code>中,设置<code>owner_</code>为 0 在调用<code>__sync_sub_and_fetch</code>之前,否则可能发生死锁(deadlock).比如,有两个线程 TID 是 111 和 222.
    1. 线程 111 完成操作调用<code>Unlock</code>,先调用<code>__sync_sub_and_fetch</code>把<code>counter_</code>减到 0
    2. 在设置<code>owner_</code>为 0 被中断,线程 222 得到运行,它调用<code>Lock</code>,发现<code>counter_</code>为 0,跳过<code>sem_wait</code>,设置<code>owner_=222</code>,完成<code>Lock</code>操作.
    3. 线程 222 被中断调出,线程 111 重新得到运行,设置<code>owner_</code>为 0,然后完成<code>Unlock</code>操作.
    4. 因为此时<code>owner_</code>为 0,线程 222 不能在递归占用锁,一旦它再次获取锁,形成死锁.</p>

<ul>
  <li>
    <p>在<code>Unlock</code>中,<code>recursion_</code>被拷贝到本地变量一次,之后只本地变量,比如没有在<code>__sync_sub_and_fetch</code>之后重新读取她.因为在那之后它能被其他线程已经改变. </p>
  </li>
  <li>
    <p><code>recursion_</code>和<code>owner_</code>没有原子操作.因为它们在调用<code>Lock</code>的
<code>__sync_add_and_fetch</code>和调用<code>Unlock</code>的<code>__sync_sub_and_fetch</code>之间,线程占有锁,独占<code>recursion_</code>和<code>owner_</code>的读写操作,并拥有所有的 acquire
and release semantics.对<code>recursion_</code>和<code>owner_</code>使用原子操作没必要.因为在 X86/84 的平台上,<code>__sync_add_and_fetch</code>生成<code>lock xadd</code>的指令,保证全部的 memory barrier,也就保证 acquire and release semantics.</p>
  </li>
</ul>

<h2 id="mutex-vs-spinlock">Mutex VS Spinlock</h2>

<p>提到 Mutex,往往会提到 Spinlock,因为在使用 Lock 时,会遇到如何在 Mutex 与 Spinlock 之间选择.那么接下来对比一下两者.</p>

<h3 id="section-1">定义</h3>

<p>Mutex: 如果一个线程试图获取一个 mutex,但是没有成功,因为 mutex 已经被占用,
它将进入睡眠,让其他进程运行,直到 mutex 被其他进程释放.</p>

<p>Spinlock: 如果一个线程试图获取一个 Spinlock, 但是没有成功,它将持续试着去获取它,直到它最终成功获取,因为它将不允许其他线程运行(然而,操作系统将强制调度其他线程).</p>

<h3 id="section-2">各自缺点</h3>

<p>Mutex: Mutex 将使得线程睡眠,然后再唤醒它们,两者都是开销比较大的操作,也就是 context switch 的开销.如果锁只是被其他线程占用非常短的时间,那么时间花在使的线程睡眠并唤醒它可能超过它使用 spinlock 持续获取锁的时间.</p>

<p>Spinlock: Spinlock 持续获取锁,浪费很多 CPU 时间,如果锁被其他线程占用很长时间,那么它将浪费很多时间,不如使得线程进入睡眠,让出 CPU.<a href="http://jfdube.wordpress.com/2011/09/24/lessons-learnt-while-spinning/">Spinlock 的确能优化 context switches</a>
但会在没有
<a href="http://en.wikipedia.org/wiki/Priority_inversion">threads priority inversion</a>
的平台上产生副作用.(但一个高优先级的线程自旋一个锁来等待一个低优先级的线程释放这个锁,就会造成死锁).在没有 Preemption 的 Uniprocessor,使用
spinlock 是没有意义的,当前只有一个线程运行,没有必要保护关键区域,也没有其他线程同时运行,释放锁给它.</p>

<p>所以在 Linux 下,Spinlock 在 kernel 这样实现:</p>

<ul>
  <li>没有打开<code>CONFIG_SMP</code>和<code>CONFIG_PREEMPT</code>,spinlock 实现代码是空的.</li>
  <li>没有打开<code>CONFIG_SMP</code>,打开<code>CONFIG_PREEMPT</code>,spinlock 仅仅是简单的关闭
preemption,足够来防止任何的
<a href="http://en.wikipedia.org/wiki/Race_condition">races</a>. </li>
  <li>打开<code>CONFIG_SMP</code>,打开<code>CONFIG_PREEMPT</code>,spinlock 实现如下代码,不断检查
lock 是否被其他线程释放: </li>
</ul>

<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
<span class="line-number">5</span>
<span class="line-number">6</span>
<span class="line-number">7</span>
<span class="line-number">8</span>
<span class="line-number">9</span>
<span class="line-number">10</span>
<span class="line-number">11</span>
<span class="line-number">12</span>
<span class="line-number">13</span>
<span class="line-number">14</span>
<span class="line-number">15</span>
<span class="line-number">16</span>
<span class="line-number">17</span>
<span class="line-number">18</span>
<span class="line-number">19</span>
<span class="line-number">20</span>
</pre></td><td class="code"><pre><code class="c"><span class="line">  <span class="k">extern</span> <span class="kr">inline</span> <span class="kt">void</span> <span class="nf">spin_lock</span><span class="p">(</span><span class="n">spinlock_t</span> <span class="o">*</span><span class="n">plock</span><span class="p">)</span>
</span><span class="line">  <span class="p">{</span>
</span><span class="line">    <span class="n">__asm__</span> <span class="n">__volatile__</span><span class="p">(</span>
</span><span class="line">        <span class="n">spin_lock_string</span>
</span><span class="line">        <span class="o">:</span><span class="s">&quot;=m&quot;</span> <span class="p">(</span><span class="n">__dummy_lock</span><span class="p">(</span><span class="n">plock</span><span class="p">)));</span>
</span><span class="line">  <span class="p">}</span>
</span><span class="line">  <span class="c1">// Macro spin_lock_string expand</span>
</span><span class="line">  <span class="k">extern</span> <span class="kr">inline</span> <span class="kt">void</span> <span class="nf">spin_lock</span><span class="p">(</span><span class="n">spinlock_t</span> <span class="o">*</span><span class="n">plock</span><span class="p">)</span>
</span><span class="line"> <span class="p">{</span>
</span><span class="line">  <span class="mi">1</span><span class="o">:</span>
</span><span class="line">    <span class="n">lock</span> <span class="p">;</span> <span class="n">btsl</span> <span class="p">,</span><span class="n">plock</span><span class="p">;</span>
</span><span class="line">    <span class="n">jc</span> <span class="mf">2f</span><span class="p">;</span>
</span><span class="line">    <span class="p">.</span><span class="n">section</span> <span class="p">.</span><span class="n">text</span><span class="p">.</span><span class="n">lock</span><span class="p">,</span><span class="s">&quot;ax&quot;</span>
</span><span class="line">  <span class="mi">2</span><span class="o">:</span>
</span><span class="line">    <span class="n">testb</span> <span class="p">,</span><span class="n">plock</span><span class="p">;</span>
</span><span class="line">    <span class="n">rep</span><span class="p">;</span><span class="n">nop</span><span class="p">;</span>
</span><span class="line">    <span class="n">jne</span> <span class="mi">2</span><span class="n">b</span><span class="p">;</span>
</span><span class="line">    <span class="n">jmp</span> <span class="mi">1</span><span class="n">b</span><span class="p">;</span>
</span><span class="line">    <span class="p">.</span><span class="n">previous</span>
</span><span class="line"> <span class="p">}</span>
</span></code></pre></td></tr></table></div></figure></notextile></div>

<h3 id="section-3">总结</h3>

<table>
  <thead>
    <tr>
      <th>Criteria</th>
      <th>Muutex</th>
      <th>Spinlock</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>机制</td>
      <td>尝试获取锁.若可得到就占有.若不能,就进入睡眠等待.</td>
      <td>尝试获取锁.若可得到就占有.若不能,持续尝试直到获取.</td>
    </tr>
    <tr>
      <td>什么时候使用</td>
      <td>当线程进入睡眠没有伤害.或需要等待一段足够长的时间才能获取锁.</td>
      <td>当线程不应该进入睡眠如中断处理等.当只需等待非常短的时间就能获取锁.</td>
    </tr>
    <tr>
      <td>缺点</td>
      <td>引起 context switch 和 scheduling 开销.</td>
      <td>线程不做任何事情在获取到锁前.浪费 CPU 运行.</td>
    </tr>
  </tbody>
</table>

<p><a href="http://en.wikipedia.org/wiki/Spinlock#Alternatives">大多数操作系统(包括 Solaris,Mac OS X 和 FreeBSD)使用混合的机制叫”adaptive mutex”或”hybrid mutex”</a>.一个 hybrid mutex 首先行为和 spinlock 一样,如果不能获取锁,持续尝试获取,但过了一定的时间,它就和 mutex 一样,让线程进入睡眠.<sup id="fnref:f1"><a href="#fn:f1" rel="footnote">1</a></sup>.</p>

<div class="footnotes">
  <ol>
    <li id="fn:f1">
      <p>http://stackoverflow.com/questions/5869825/when-should-one-use-a-spinlock-instead-of-mutex<a href="#fnref:f1" rel="reference">&#8617;</a></p>
    </li>
  </ol>
</div>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[浅谈Memory Reordering]]></title>
    <link href="http://dreamrunner.org/blog/2014/06/28/qian-tan-memory-reordering/"/>
    <updated>2014-06-28T22:55:22+08:00</updated>
    <id>http://dreamrunner.org/blog/2014/06/28/qian-tan-memory-reordering</id>
    <content type="html"><![CDATA[<h2 id="memory-ordering">Memory ordering</h2>
<p>在我们编写的 C/C++代码和它被在 CPU 上运行,按照一些规则,代码的内存交互会被乱序.内存乱序同时由编译器(编译时候)和处理器(运行时)造成,都为了使代码运行的更快.</p>

<p><img src="http://dreamrunner.org/images/blog/2014/multithreading/memory_model.png" title="'memory_ordering'" /></p>

<p>被编译开发者和处理器制造商遵循的中心内存排序准则是:</p>
<blockquote><p>不能改变单线程程序的行为.</p></blockquote>

<p>因为这条规则,在写单线程代码时内存乱序被普遍忽略.即使在多线程程序中,它也被时常忽略,因为有 mutexes,semaphores 等来防止它们调用中的内存乱序.仅当
lock-free 技术被使用时,内存在不受任何互斥保护下被多个线程共享,内存乱序的影响能被看到.</p>

<p>下面先比较 Weak 和 Strong 的内存模型,然后分两部分,实际内存乱序如何在编译和运行时发生,并如何防止它们.</p>

<!-- more -->

<h2 id="weak-vs-strong-memory-models">Weak VS strong Memory Models</h2>
<p><a href="http://preshing.com/about">Jeff Preshing</a> 在
<a href="http://preshing.com/20120930/weak-vs-strong-memory-models/">Weak vs. Strong Memory Models</a>
中很好的总结了从 Weak 到 Strong 的类型:</p>

<table>
  <thead>
    <tr>
      <th>非常弱</th>
      <th>数据依赖性的弱</th>
      <th>强制</th>
      <th>顺序一致</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>DEC Alpha</td>
      <td>ARM</td>
      <td>X86/64</td>
      <td>dual 386</td>
    </tr>
    <tr>
      <td>C/C++11 low-level atomics</td>
      <td>PowerPC</td>
      <td>SPARC TSO</td>
      <td>Java volatile/C/C++11 atomics</td>
    </tr>
  </tbody>
</table>

<h3 id="section">弱内存模型</h3>

<p>在最弱的内存模型中,可能经历所有四种内存乱序
(<a href="http://g.oswego.edu/dl/jmm/cookbook.html">LoadLoad, StoreStore, LoadStore and StoreLoad</a>).任何 load 或 store 的操作能与任何的其他的 load 或 store 操作乱序,只要它不改变一个独立进程的行为.实际中,这样的乱序由于编译器引起的指令乱序或处理器本身处理指令的乱序.</p>

<p>当处理器是弱硬件内存模式,通常称它为 weakly-ordered 或 weak ordering.或说它有 relaxed memory model. <strong>DEC Alpha</strong> 是
<a href="http://www.mjmwired.net/kernel/Documentation/memory-barriers.txt#2277">最具代表</a>
的弱排序的处理器.</p>

<p>C/C++的底层原子操作也呈现弱内存模型,无论代码的平台是如 x86/64 的强序处理器.下面章节
<a href="http://dreamrunner.org/blog/2014/06/28/qian-tan-memory-reordering/#memory-ordering-at-compile-time">Memory ordering at compile time</a>
会演示其弱内存模型,并说明如何强制内存顺序来保护编译器乱序.</p>

<h3 id="section-1">数据依赖性的弱</h3>

<p>ARM 和 PowerPC 系列的处理器内存模型和 Alpha 同样弱,除了它们保持
<a href="http://www.mjmwired.net/kernel/Documentation/memory-barriers.txt#305">data dependency ordering</a>.它意味两个相依赖的<code>load</code>(load A, load B&lt;-A)被保证顺序<code>load B&lt;-A</code>总能在
<code>load A</code>之后.(A data dependency barrier is a partial ordering on interdependent loads only; it is not required to have any effect on stores, independent loads or overlapping loads.)</p>

<h3 id="section-2">强内存模型</h3>

<p>弱和强内存模型区别<a href="http://herbsutter.com/2012/08/02/strong-and-weak-hardware-memory-models/#comment-5903">存在分歧</a>.<a href="http://preshing.com/20120930/weak-vs-strong-memory-models/">Preshing</a>
总结的定义是:</p>

<blockquote><p>一个强硬件内存模型是在这样的硬件上每条机器指令隐性的保证 acquire and release<br />semantics 的执行.因此,当一个 CPU 核进行了一串写操作,每个其他的 CPU 核看到这些值的改变顺序与其顺序一致.</p></blockquote>

<p>所以也就是保证了四种内存乱序
(<a href="http://g.oswego.edu/dl/jmm/cookbook.html">LoadLoad, StoreStore, LoadStore and StoreLoad</a>)
中的 3 种,除了不保证 StoreLoad 的顺序.基于以上的定义,x86/64 系列处理器基本就是强顺序的.之后
<a href="http://dreamrunner.org/blog/2014/06/28/qian-tan-memory-reordering/#memory-ordering-at-processor-time">Memory ordering at processor time</a>
可以看到 StoreLoad 在 X86/64 的乱序实验.</p>

<h3 id="section-3">顺序一致</h3>

<p>在顺序一致
(<a href="http://en.wikipedia.org/wiki/Sequential_consistency">Sequential consistency</a>)
的内存模型中,没有内存乱序存在.</p>

<p>如今,很难找到一个现代多核设备保证在硬件层 Sequential consistency.也就早期的 386 没有强大到能在运行时进行任何内存的乱序.</p>

<p>当用上层语言编程时,Sequential consistency 成为一个重要的软件内存模型.Java5 和之后版本,用<code>volatile</code>声明共享变量.在 C+11 中,可以使用默认的顺序约束<code>memory_order_seq_cst</code>在做原子操作时.当使用这些术语后,编译器会限制编译乱序和插入特定 CPU 的指令来指定合适的 memory barrier 类型.</p>

<h2 id="memory-ordering-at-compile-time">Memory ordering at compile time</h2>
<p>看如下代码:</p>

<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span>test.c</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
<span class="line-number">5</span>
</pre></td><td class="code"><pre><code class="c"><span class="line"><span class="kt">int</span> <span class="n">A</span><span class="p">,</span> <span class="n">B</span><span class="p">;</span>
</span><span class="line"><span class="kt">void</span> <span class="nf">test</span><span class="p">()</span> <span class="p">{</span>
</span><span class="line">  <span class="n">A</span> <span class="o">=</span> <span class="n">B</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
</span><span class="line">  <span class="n">B</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span><span class="line"><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure></notextile></div>

<p>不打开编译器的优化,把它编译成汇编,我们可以看到,<code>B</code>的赋值在<code>A</code>的后面,和原程序的顺序一样.</p>

<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
<span class="line-number">5</span>
<span class="line-number">6</span>
</pre></td><td class="code"><pre><code class="sh"><span class="line"><span class="nv">$ </span>gcc -S -masm<span class="o">=</span>intel test.c
</span><span class="line">
</span><span class="line">	mov	eax, DWORD PTR B
</span><span class="line">	add	eax, 1
</span><span class="line">	mov	DWORD PTR A, eax
</span><span class="line">	mov	DWORD PTR B, 0
</span></code></pre></td></tr></table></div></figure></notextile></div>

<p>用<code>O2</code>打开优化:</p>

<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
<span class="line-number">5</span>
<span class="line-number">6</span>
</pre></td><td class="code"><pre><code class="sh"><span class="line"><span class="nv">$ </span>gcc -S -O2  -masm<span class="o">=</span>intel test.c
</span><span class="line">
</span><span class="line">	mov	eax, DWORD PTR B
</span><span class="line">	mov	DWORD PTR B, 0
</span><span class="line">	add	eax, 1
</span><span class="line">	mov	DWORD PTR A, eax
</span></code></pre></td></tr></table></div></figure></notextile></div>

<p>这次编译器把<code>B</code>的赋值提到<code>A</code>的前面.为什么它可以这么做呢?内存顺序的中心没有破坏.这样的改变并不影响单线程程序,单线程程序不能知道这样的区别.</p>

<p>但是当编写 lock-free 代码时,这样的编译器乱序就会引起问题.看如下例子,一个共享的标识来表明其他共享数据是否更新:</p>

<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
<span class="line-number">5</span>
<span class="line-number">6</span>
</pre></td><td class="code"><pre><code class="c"><span class="line"><span class="kt">int</span> <span class="n">value</span><span class="p">;</span>
</span><span class="line"><span class="kt">int</span> <span class="n">updated</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span><span class="line"><span class="kt">void</span> <span class="nf">UpdateValue</span><span class="p">(</span><span class="kt">int</span> <span class="n">x</span><span class="p">)</span> <span class="p">{</span>
</span><span class="line">    <span class="n">value</span> <span class="o">=</span> <span class="n">x</span><span class="p">;</span>
</span><span class="line">    <span class="n">update</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
</span><span class="line"><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure></notextile></div>

<p>如果编译器把<code>update</code>的赋值提到<code>value</code>赋值的前面.即使在单核处理器系统中,会有问题:在两个参数赋值的中间这个线程被中断,使得另外的程序通过<code>update</code>判断以为<code>value</code>的值已经得到更新,实际上却没有.</p>

<h3 id="compiler-barriers">显性的 Compiler Barriers</h3>
<p>一种方法是用一个特殊的被称为 Compiler Barrier 的指令来防止编译器优化的乱序.以下
<a href="http://en.wikipedia.org/wiki/Memory_ordering#Compiler_memory_barrier"><code>asm volative</code></a>
是 GCC 中的方法.</p>

<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span>test_barrier.c</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
<span class="line-number">5</span>
<span class="line-number">6</span>
</pre></td><td class="code"><pre><code class="c"><span class="line"><span class="kt">int</span> <span class="n">A</span><span class="p">,</span> <span class="n">B</span><span class="p">;</span>
</span><span class="line"><span class="kt">void</span> <span class="nf">test</span><span class="p">()</span> <span class="p">{</span>
</span><span class="line">  <span class="n">A</span> <span class="o">=</span> <span class="n">B</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
</span><span class="line">  <span class="n">asm</span> <span class="k">volatile</span><span class="p">(</span><span class="s">&quot;&quot;</span> <span class="o">:::</span> <span class="s">&quot;memory&quot;</span><span class="p">);</span>
</span><span class="line">  <span class="n">B</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span><span class="line"><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure></notextile></div>

<p>经过这样的修改,打开优化,<code>B</code>的存储将保持在要求的顺序上.</p>

<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
<span class="line-number">5</span>
<span class="line-number">6</span>
</pre></td><td class="code"><pre><code class="sh"><span class="line"><span class="nv">$ </span>gcc -S -O2  -masm<span class="o">=</span>intel test.c
</span><span class="line">
</span><span class="line">	mov	eax, DWORD PTR B
</span><span class="line">	add	eax, 1
</span><span class="line">	mov	DWORD PTR A, eax
</span><span class="line">	mov	DWORD PTR B, 0
</span></code></pre></td></tr></table></div></figure></notextile></div>

<h3 id="compiler-barriers-1">隐性的 Compiler Barriers</h3>
<p>在 C++11 中原子库中,每个不是 relaxed 的原子操作同时是一个 compiler barrier.</p>

<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
<span class="line-number">5</span>
<span class="line-number">6</span>
<span class="line-number">7</span>
</pre></td><td class="code"><pre><code class="c++"><span class="line"><span class="kt">int</span> <span class="n">value</span><span class="p">;</span>
</span><span class="line"><span class="n">std</span><span class="o">::</span><span class="n">atomic</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">updated</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
</span><span class="line"><span class="kt">void</span> <span class="n">UpdateValue</span><span class="p">(</span><span class="kt">int</span> <span class="n">x</span><span class="p">)</span> <span class="p">{</span>
</span><span class="line">    <span class="n">value</span> <span class="o">=</span> <span class="n">x</span><span class="p">;</span>
</span><span class="line">    <span class="c1">// reordering is prevented here</span>
</span><span class="line">    <span class="n">update</span><span class="p">.</span><span class="n">store</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">memory_order_release</span><span class="p">);</span>
</span><span class="line"><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure></notextile></div>

<p>每一个拥有 compiler barrier 的函数本身也是一个 compiler barrier,即使它是
inline 的.</p>

<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
<span class="line-number">5</span>
<span class="line-number">6</span>
<span class="line-number">7</span>
</pre></td><td class="code"><pre><code class="c++"><span class="line"><span class="kt">int</span> <span class="n">a</span><span class="p">;</span>
</span><span class="line"><span class="kt">int</span> <span class="n">b</span><span class="p">;</span>
</span><span class="line"><span class="kt">void</span> <span class="n">DoSomething</span><span class="p">()</span> <span class="p">{</span>
</span><span class="line">    <span class="n">a</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
</span><span class="line">    <span class="n">UpdateValue</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
</span><span class="line">    <span class="n">b</span> <span class="o">=</span> <span class="n">a</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
</span><span class="line"><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure></notextile></div>

<p>进一步推知,大多数被调用的函数是一个 compiler barrier.无论它们是否包含
memory barrier.排除 inline 函数,被声明为<a href="http://lwn.net/Articles/285332/"><code>pure attribution</code></a>
或当
<a href="http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0474c/CHDHIEGF.html">link-time code generation</a>
使用时.因为编译器在编译时,并不知道<code>UpdateValue</code>的运行是否依赖于<code>a</code>或会改变<code>a</code>的值从而影响<code>b</code>,所以编译器不会乱序它们之间的顺序.</p>

<p>可以看到,有许多隐藏的规则禁止编译指令的乱序,也防止了编译器多进一步的代码优化,所以在某些场景
<a href="https://www.kernel.org/doc/Documentation/volatile-considered-harmful.txt">Why the “volatile” type class should not be used</a>,
来让编译器进一步优化.</p>

<h3 id="section-4">无缘由的存储</h3>

<p>有隐形的 Compiler Barriers,同样 GCC 编译器也有无缘由的存储.来自<a href="https://gcc.gnu.org/ml/gcc/2007-10/msg00266.html">这里的实例</a>:</p>

<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
<span class="line-number">5</span>
<span class="line-number">6</span>
<span class="line-number">7</span>
<span class="line-number">8</span>
</pre></td><td class="code"><pre><code class="c"><span class="line"><span class="k">extern</span> <span class="kt">int</span> <span class="n">v</span><span class="p">;</span>
</span><span class="line">
</span><span class="line">    <span class="kt">void</span>
</span><span class="line">    <span class="nf">f</span><span class="p">(</span><span class="kt">int</span> <span class="n">set_v</span><span class="p">)</span>
</span><span class="line">    <span class="p">{</span>
</span><span class="line">      <span class="k">if</span> <span class="p">(</span><span class="n">set_v</span><span class="p">)</span>
</span><span class="line">        <span class="n">v</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
</span><span class="line">    <span class="p">}</span>
</span></code></pre></td></tr></table></div></figure></notextile></div>

<p>在 i686,GCC 3.3.4–4.3.0 用<code>O1</code>编译得到:</p>

<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
<span class="line-number">5</span>
<span class="line-number">6</span>
<span class="line-number">7</span>
<span class="line-number">8</span>
</pre></td><td class="code"><pre><code class="sh"><span class="line">        pushl   %ebp
</span><span class="line">        movl    %esp, %ebp
</span><span class="line">        cmpl    <span class="nv">$0</span>, 8<span class="o">(</span>%ebp<span class="o">)</span>
</span><span class="line">        movl    <span class="nv">$1</span>, %eax
</span><span class="line">        cmove   v, %eax        ; load <span class="o">(</span>maybe<span class="o">)</span>
</span><span class="line">        movl    %eax, v        ; store <span class="o">(</span>always<span class="o">)</span>
</span><span class="line">        popl    %ebp
</span><span class="line">        ret
</span></code></pre></td></tr></table></div></figure></notextile></div>

<p>在单线程中,没有问题,但多线程中调用<code>f(0)</code>仅仅只是读取 v 的值,但中断后回去覆盖其他线程修改的值.引起
<a href="http://www.devx.com/cplus/Article/42725">data rate</a>.在新的 C++11 标准中明确禁止了这样的行为,看<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf">最近 C+11 标准进行的 draft</a>§1.10.22 节:</p>

<blockquote><p>Compiler transformations that introduce assignments to a potentially shared memory location that would not be modified by the abstract machine are generally precluded by this standard.</p></blockquote>

<h2 id="memory-ordering-at-processor-time">Memory ordering at processor time</h2>

<p>看一个简单的 CPU 乱序的简单例子,即使在强内存模型的 X86/64 也能看到.有两个整数<code>X</code>和<code>Y</code>初始是 0,另外两个变量 r1 和 r2 读取它们的值,两个线程并行运行,执行如下的机器代码:</p>

<p><img class="center" src="http://dreamrunner.org/images/blog/2014/multithreading/ordering-example.png" width="370" height="100" title="'ordering-example'" /></p>

<p>每个线程存储 1 到一个共享变量,然后把对方变量读取到一个变量或一个寄存器中.无论哪个线程先写 1 到内存,另外个线程读回那个值,意味着最后 r1=1 或 r2=1 或两者都是.但是 X86/64 是强内存模型,它还是允许<strong>乱序</strong>机器指令.特别,每个线程允许延迟存储到读回之后.以致最后 r1 和 r2 能同时等于 0–违反直觉的一个结果.因为指令可能如下顺序执行:</p>

<p><img class="center" src="http://dreamrunner.org/images/blog/2014/multithreading/reordering-example.png" width="190" height="100" title="'reordering-example'" /></p>

<p>写一个实例程序,实际看一下 CPU 的确乱序了指令.源码可以
<a href="https://github.com/shishougang/blog_multithreading/tree/master/memory_reordering">Github 下载</a>.两个读写的线程代码如下:</p>

<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
<span class="line-number">5</span>
<span class="line-number">6</span>
<span class="line-number">7</span>
<span class="line-number">8</span>
<span class="line-number">9</span>
<span class="line-number">10</span>
<span class="line-number">11</span>
<span class="line-number">12</span>
<span class="line-number">13</span>
<span class="line-number">14</span>
<span class="line-number">15</span>
<span class="line-number">16</span>
<span class="line-number">17</span>
<span class="line-number">18</span>
<span class="line-number">19</span>
<span class="line-number">20</span>
<span class="line-number">21</span>
<span class="line-number">22</span>
<span class="line-number">23</span>
<span class="line-number">24</span>
<span class="line-number">25</span>
<span class="line-number">26</span>
<span class="line-number">27</span>
<span class="line-number">28</span>
<span class="line-number">29</span>
<span class="line-number">30</span>
<span class="line-number">31</span>
<span class="line-number">32</span>
<span class="line-number">33</span>
<span class="line-number">34</span>
<span class="line-number">35</span>
<span class="line-number">36</span>
</pre></td><td class="code"><pre><code class="c++"><span class="line"><span class="n">sem_t</span> <span class="n">begin_sem1</span><span class="p">;</span>
</span><span class="line"><span class="n">sem_t</span> <span class="n">begin_sem2</span><span class="p">;</span>
</span><span class="line"><span class="n">sem_t</span> <span class="n">end_sem</span><span class="p">;</span>
</span><span class="line">
</span><span class="line"><span class="kt">int</span> <span class="n">X</span><span class="p">,</span> <span class="n">Y</span><span class="p">;</span>
</span><span class="line"><span class="kt">int</span> <span class="n">r1</span><span class="p">,</span> <span class="n">r2</span><span class="p">;</span>
</span><span class="line">
</span><span class="line"><span class="kt">void</span> <span class="o">*</span><span class="n">ThreadFunc1</span><span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">param</span><span class="p">)</span> <span class="p">{</span>
</span><span class="line">  <span class="n">MersenneTwister</span> <span class="n">random</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
</span><span class="line">  <span class="k">for</span> <span class="p">(;;)</span> <span class="p">{</span>
</span><span class="line">    <span class="n">sem_wait</span><span class="p">(</span><span class="o">&amp;</span><span class="n">begin_sem1</span><span class="p">);</span>
</span><span class="line">    <span class="c1">// random delay</span>
</span><span class="line">    <span class="k">while</span> <span class="p">(</span><span class="n">random</span><span class="p">.</span><span class="n">Integer</span><span class="p">()</span> <span class="o">%</span> <span class="mi">8</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span><span class="line">    <span class="p">}</span>
</span><span class="line">    <span class="n">X</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
</span><span class="line">    <span class="k">asm</span> <span class="k">volatile</span><span class="p">(</span><span class="s">&quot;&quot;</span> <span class="o">:::</span> <span class="s">&quot;memory&quot;</span><span class="p">);</span>  <span class="c1">// prevent compiler ordering</span>
</span><span class="line">    <span class="n">r1</span> <span class="o">=</span> <span class="n">Y</span><span class="p">;</span>
</span><span class="line">    <span class="n">sem_post</span><span class="p">(</span><span class="o">&amp;</span><span class="n">end_sem</span><span class="p">);</span>
</span><span class="line">  <span class="p">}</span>
</span><span class="line">  <span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span>
</span><span class="line"><span class="p">}</span>
</span><span class="line">
</span><span class="line"><span class="kt">void</span> <span class="o">*</span><span class="n">ThreadFunc2</span><span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">param</span><span class="p">)</span> <span class="p">{</span>
</span><span class="line">  <span class="n">MersenneTwister</span> <span class="n">random</span><span class="p">(</span><span class="mi">2</span><span class="p">);</span>
</span><span class="line">  <span class="k">for</span> <span class="p">(;;)</span> <span class="p">{</span>
</span><span class="line">    <span class="n">sem_wait</span><span class="p">(</span><span class="o">&amp;</span><span class="n">begin_sem2</span><span class="p">);</span>
</span><span class="line">    <span class="c1">// random delay</span>
</span><span class="line">    <span class="k">while</span> <span class="p">(</span><span class="n">random</span><span class="p">.</span><span class="n">Integer</span><span class="p">()</span> <span class="o">%</span> <span class="mi">8</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span><span class="line">    <span class="p">}</span>
</span><span class="line">    <span class="n">Y</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
</span><span class="line">    <span class="k">asm</span> <span class="k">volatile</span><span class="p">(</span><span class="s">&quot;&quot;</span> <span class="o">:::</span> <span class="s">&quot;memory&quot;</span><span class="p">);</span>  <span class="c1">// prevent compiler ordering</span>
</span><span class="line">    <span class="n">r2</span> <span class="o">=</span> <span class="n">X</span><span class="p">;</span>
</span><span class="line">    <span class="n">sem_post</span><span class="p">(</span><span class="o">&amp;</span><span class="n">end_sem</span><span class="p">);</span>
</span><span class="line">  <span class="p">}</span>
</span><span class="line">  <span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span>
</span><span class="line"><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure></notextile></div>

<p>随机的延迟被插入在存储的开始处,为了交错线程的开始时间,以来达到重叠两个线程的指令的目的.随机延迟使用线程安全的<code>MersenneTwister</code>类.汇编代码<code>asm
volatile("" ::: "memory");</code>如上节所述只是用来
<a href="http://dreamrunner.org/blog/2014/06/28/qian-tan-memory-reordering/#memory-ordering-at-compile-time">防止编译器的乱序</a>,
因为这里是要看 CPU 的乱序,排除编译器的乱序影响.</p>

<p>主线程如下,利用
<a href="http://pubs.opengroup.org/onlinepubs/7908799/xsh/sem_init.html">POSIX 的 semaphore</a>
同步它与两个子线程的同步.先让两个子线程等待,直到主线程初始化<code>X=0</code>和
<code>Y=0</code>.然后主线程等待,直到两个子线程完成操作,然后主线程检查<code>r1</code>和<code>r2</code>的值.所以 semaphore 防止线程见的不同步引起的内存乱序,主线程代码如下:</p>

<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
<span class="line-number">5</span>
<span class="line-number">6</span>
<span class="line-number">7</span>
<span class="line-number">8</span>
<span class="line-number">9</span>
<span class="line-number">10</span>
<span class="line-number">11</span>
<span class="line-number">12</span>
<span class="line-number">13</span>
<span class="line-number">14</span>
<span class="line-number">15</span>
<span class="line-number">16</span>
<span class="line-number">17</span>
<span class="line-number">18</span>
<span class="line-number">19</span>
<span class="line-number">20</span>
<span class="line-number">21</span>
<span class="line-number">22</span>
<span class="line-number">23</span>
<span class="line-number">24</span>
</pre></td><td class="code"><pre><code class="c++"><span class="line"><span class="kt">int</span> <span class="n">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> <span class="p">{</span>
</span><span class="line">  <span class="n">sem_init</span><span class="p">(</span><span class="o">&amp;</span><span class="n">begin_sem1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
</span><span class="line">  <span class="n">sem_init</span><span class="p">(</span><span class="o">&amp;</span><span class="n">begin_sem2</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
</span><span class="line">  <span class="n">sem_init</span><span class="p">(</span><span class="o">&amp;</span><span class="n">end_sem</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
</span><span class="line">
</span><span class="line">  <span class="n">pthread_t</span> <span class="kr">thread</span><span class="p">[</span><span class="mi">2</span><span class="p">];</span>
</span><span class="line">  <span class="n">pthread_create</span><span class="p">(</span><span class="o">&amp;</span><span class="kr">thread</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="nb">NULL</span><span class="p">,</span> <span class="n">ThreadFunc1</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">);</span>
</span><span class="line">  <span class="n">pthread_create</span><span class="p">(</span><span class="o">&amp;</span><span class="kr">thread</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="nb">NULL</span><span class="p">,</span> <span class="n">ThreadFunc2</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">);</span>
</span><span class="line">
</span><span class="line">  <span class="kt">int</span> <span class="n">detected</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span><span class="line">  <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
</span><span class="line">    <span class="n">X</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span><span class="line">    <span class="n">Y</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span><span class="line">    <span class="n">sem_post</span><span class="p">(</span><span class="o">&amp;</span><span class="n">begin_sem1</span><span class="p">);</span>
</span><span class="line">    <span class="n">sem_post</span><span class="p">(</span><span class="o">&amp;</span><span class="n">begin_sem2</span><span class="p">);</span>
</span><span class="line">    <span class="n">sem_wait</span><span class="p">(</span><span class="o">&amp;</span><span class="n">end_sem</span><span class="p">);</span>
</span><span class="line">    <span class="n">sem_wait</span><span class="p">(</span><span class="o">&amp;</span><span class="n">end_sem</span><span class="p">);</span>
</span><span class="line">    <span class="k">if</span> <span class="p">(</span><span class="n">r1</span> <span class="o">==</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="n">r2</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span><span class="line">      <span class="n">detected</span><span class="o">++</span><span class="p">;</span>
</span><span class="line">      <span class="n">printf</span><span class="p">(</span><span class="s">&quot;%d reorders detected after %d iterations</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">,</span> <span class="n">detected</span><span class="p">,</span> <span class="n">i</span><span class="p">);</span>
</span><span class="line">    <span class="p">}</span>
</span><span class="line">  <span class="p">}</span>
</span><span class="line">  <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span><span class="line"><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure></notextile></div>

<p>在 Intel i5-2435M X64 的 ubuntu 下运行一下程序:</p>

<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
<span class="line-number">5</span>
<span class="line-number">6</span>
<span class="line-number">7</span>
<span class="line-number">8</span>
<span class="line-number">9</span>
<span class="line-number">10</span>
<span class="line-number">11</span>
<span class="line-number">12</span>
<span class="line-number">13</span>
<span class="line-number">14</span>
<span class="line-number">15</span>
<span class="line-number">16</span>
<span class="line-number">17</span>
<span class="line-number">18</span>
<span class="line-number">19</span>
</pre></td><td class="code"><pre><code class="sh"><span class="line">1 reorders detected after 2181 iterations
</span><span class="line">2 reorders detected after 4575 iterations
</span><span class="line">3 reorders detected after 7689 iterations
</span><span class="line">4 reorders detected after 22215 iterations
</span><span class="line">5 reorders detected after 60023 iterations
</span><span class="line">6 reorders detected after 60499 iterations
</span><span class="line">7 reorders detected after 61639 iterations
</span><span class="line">8 reorders detected after 62243 iterations
</span><span class="line">9 reorders detected after 67998 iterations
</span><span class="line">10 reorders detected after 68098 iterations
</span><span class="line">11 reorders detected after 71179 iterations
</span><span class="line">12 reorders detected after 71668 iterations
</span><span class="line">13 reorders detected after 72417 iterations
</span><span class="line">14 reorders detected after 73970 iterations
</span><span class="line">15 reorders detected after 78227 iterations
</span><span class="line">16 reorders detected after 81897 iterations
</span><span class="line">17 reorders detected after 82722 iterations
</span><span class="line">18 reorders detected after 85377 iterations
</span><span class="line">...
</span></code></pre></td></tr></table></div></figure></notextile></div>

<p>差不多每 <strong>4000</strong> 次的迭代才发现一次 CPU 内存乱序.所以多线程的 bug 是多么难发现.那么如何消除这些乱序.至少有如下两种方法:</p>

<ol>
  <li>让两个子线程在同一个 CPU 核下运行.(没有可移植性方法,如下是 linux 平台的).</li>
  <li>使用 CPU 的 memory barrier 防止它的乱序.</li>
</ol>

<h3 id="lock-to-one-processor">Lock to one processor</h3>
<p>让两个子线程在同一个 CPU 核下运行,代码如下:</p>

<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
<span class="line-number">5</span>
</pre></td><td class="code"><pre><code class="c++"><span class="line">  <span class="n">cpu_set_t</span> <span class="n">cpus</span><span class="p">;</span>
</span><span class="line">  <span class="n">CPU_ZERO</span><span class="p">(</span><span class="o">&amp;</span><span class="n">cpus</span><span class="p">);</span>
</span><span class="line">  <span class="n">CPU_SET</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">cpus</span><span class="p">);</span>
</span><span class="line">  <span class="n">pthread_setaffinity_np</span><span class="p">(</span><span class="kr">thread</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">cpu_set_t</span><span class="p">),</span> <span class="o">&amp;</span><span class="n">cpus</span><span class="p">);</span>
</span><span class="line">  <span class="n">pthread_setaffinity_np</span><span class="p">(</span><span class="kr">thread</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">cpu_set_t</span><span class="p">),</span> <span class="o">&amp;</span><span class="n">cpus</span><span class="p">);</span>
</span></code></pre></td></tr></table></div></figure></notextile></div>

<h3 id="place-a-memory-barrier">Place a memory barrier</h3>

<p>防止一个 Store 在 Load 之后的乱序,需要一个 StoreLoad 的 barrier.这里使用
<code>mfence</code>的一个全部 memory barrier,防止任何类型的内存乱序.代码如下:</p>

<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
<span class="line-number">5</span>
<span class="line-number">6</span>
<span class="line-number">7</span>
<span class="line-number">8</span>
<span class="line-number">9</span>
<span class="line-number">10</span>
<span class="line-number">11</span>
<span class="line-number">12</span>
<span class="line-number">13</span>
<span class="line-number">14</span>
</pre></td><td class="code"><pre><code class="c++"><span class="line"><span class="kt">void</span> <span class="o">*</span><span class="n">ThreadFunc1</span><span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="n">param</span><span class="p">)</span> <span class="p">{</span>
</span><span class="line">  <span class="n">MersenneTwister</span> <span class="n">random</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
</span><span class="line">  <span class="k">for</span> <span class="p">(;;)</span> <span class="p">{</span>
</span><span class="line">    <span class="n">sem_wait</span><span class="p">(</span><span class="o">&amp;</span><span class="n">begin_sem1</span><span class="p">);</span>
</span><span class="line">    <span class="c1">// random delay</span>
</span><span class="line">    <span class="k">while</span> <span class="p">(</span><span class="n">random</span><span class="p">.</span><span class="n">Integer</span><span class="p">()</span> <span class="o">%</span> <span class="mi">8</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span><span class="line">    <span class="p">}</span>
</span><span class="line">    <span class="n">X</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
</span><span class="line">    <span class="k">asm</span> <span class="k">volatile</span><span class="p">(</span><span class="s">&quot;mfence&quot;</span> <span class="o">:::</span> <span class="s">&quot;memory&quot;</span><span class="p">);</span>  <span class="c1">// prevent CPU ordering</span>
</span><span class="line">    <span class="n">r1</span> <span class="o">=</span> <span class="n">Y</span><span class="p">;</span>
</span><span class="line">    <span class="n">sem_post</span><span class="p">(</span><span class="o">&amp;</span><span class="n">end_sem</span><span class="p">);</span>
</span><span class="line">  <span class="p">}</span>
</span><span class="line">  <span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span>
</span><span class="line">  <span class="p">}</span>
</span></code></pre></td></tr></table></div></figure></notextile></div>

<h2 id="more">More</h2>

<ol>
  <li><a href="http://www.cl.cam.ac.uk/~pes20/weakmemory/">University of Cambridge 整理的文档和论文</a></li>
  <li><a href="http://lwn.net/Articles/470681/">Paul McKenney 概括他们做的一些工作和工具</a></li>
  <li><a href="http://www.amazon.com/gp/product/0123973376/ref=as_li_ss_tl?ie=UTF8&amp;tag=preshonprogr-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0123973376">The Art of Multiprocessor Programming</a></li>
  <li><a href="http://www.amazon.com/C-Concurrency-Action-Practical-Multithreading/dp/1933988770/ref=pd_sim_b_2?ie=UTF8&amp;refRID=1QTX99XZAM6HKVG7X0G2">C++ Concurrency in Action: Practical Multithreading</a></li>
  <li><a href="https://www.kernel.org/pub/linux/kernel/people/paulmck/perfbook/perfbook.2011.01.02a.pdf">Is Parallel Programming Hard, And, If So, What Can You Do About It?</a></li>
  <li><a href="https://gcc.gnu.org/wiki/Atomic/GCCMM">The C++11 Memory Model and GCC</a></li>
</ol>

<h2 id="summarization">Summarization</h2>
<ol>
  <li>有两种内存乱序存在:编译器乱序和 CPU 乱序.</li>
  <li>如何防止编译器乱序.</li>
  <li>如何防止 CPU 乱序.</li>
</ol>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[High Resolution Time]]></title>
    <link href="http://dreamrunner.org/blog/2014/06/24/high-resolution-time/"/>
    <updated>2014-06-24T20:19:36+08:00</updated>
    <id>http://dreamrunner.org/blog/2014/06/24/high-resolution-time</id>
    <content type="html"><![CDATA[<p>在不同的平台有繁多的 Time API，如何选用精准的高精度 Time 函数来做
performance benchmarking 呢？</p>

<h2 id="wall-clock-time-vs-cpu-time">Wall-clock time VS CPU time</h2>
<p>先理解一些时间的概念。明白不同时间 API 测量的是什么时间。</p>

<p><a href="http://en.wikipedia.org/wiki/Wall-clock_time">Wall-clock time</a>,顾名思义，墙上的钟，代表一个任务从开始到完成所经历的时间。它包含 3 部分：CPU 的时间，I/O 的时间和通信延迟的时间。但 wall-clock 很少是正确的时钟来使用，因为它随着时区，和 daylightsaving 改变，或与 NTP 同步。而这些特性没有一个是有益的，如果你用它来调度任务或做 performance benchmarking。它仅仅如名字所言，墙上的一个时钟。</p>

<p><a href="http://en.wikipedia.org/wiki/CPU_time">CPU time</a> 仅仅统计一个任务从开始到完成在 CPU 上所花的时间。CPU time 主要包括 User time（在 user space 所花时间）和 System time（在 kernel space 所花时间）。</p>

<p>以并行程序为例，CPU time 就是所有 CPU 在这个程序所花的时间总和，
Wall-clock time 在这种情况可能时间相对短，它只统计任务开始到结束所花时间。</p>

<!-- more -->

<h2 id="api-f1">不同时钟 API 对比<sup id="fnref:f1"><a href="#fn:f1" rel="footnote">1</a></sup></h2>
<p>对于不同的时钟 API,主要分析如下特性：</p>

<ol>
  <li>API 测试的是什么时间？（real, user, system，CPU or wall-clock)</li>
  <li>API 的精度？(s, ms, µs, or faster?)</li>
  <li>多久时间这个时钟数字会返转？或有什么策略避免它？</li>
  <li>时钟是 monotonic 的，还是它会随着系统时间改变（比如 NTP，time zone，
daylight saving time, by the user, etc)?</li>
</ol>

<p>Linux 和 OS X 的主要时钟 API：</p>

<ul>
  <li><a href="http://linux.die.net/man/2/time">time()</a>返回系统的 wall-clock，精度到秒。</li>
  <li><a href="http://linux.die.net/man/3/clock">clock()</a>返回 user 和 systime 总共的时间.现在标准要求<code>CLOCKS_PER_SEC</code>是<code>1000000</code>,使精度最多达到
1µs.<code>clock_t</code>类型平台相关(The range and precision of times
representable in clock_t and time_t are implementation-defined.) 它
wrap around 一旦达到最大值.(通常是 32 位的类型,那么~2^32 ticks 后,还是比较长的时间.)</li>
  <li><a href="http://linux.die.net/man/3/clock_gettime">clock_gettime(CLOCK_MONOTONIC,..)</a>
提供纳秒级的精确度并且是单调的.它的秒和纳秒是分开存储的,所以,任何的
wrap around 将很多年才发生一次.它是个不错的时钟,但 OS X 平台上没有.</li>
  <li><a href="http://linux.die.net/man/2/getrusage">getrusage</a> 返回独立的 user 和
system 时间,并且不会 wrap around.精确达到 1 µs,</li>
  <li><a href="http://linux.die.net/man/2/gettimeofday">gettimeofday</a> 返回一个
wall-clock 时间并达到µs 精度.但是精度不能保证,因为<a href="http://www.lehman.cuny.edu/cgi-bin/man-cgi?gettimeofday+3">依赖于硬件</a>.</li>
  <li><a href="https://developer.apple.com/library/mac/qa/qa1398/_index.html">mach_absolute_time()</a>
是 OS X 平台的高精度(ns)计时的一个选择.ns 以 64 位 unsigned integer 存储,实际使用 wrap around 不是大问题,移植性是问题.</li>
</ul>

<p>Window 的高精度时钟：</p>

<p><a href="http://msdn.microsoft.com/en-us/library/ms644905(VS.85).aspx">QueryPerformanceFrequency()</a>
和
<a href="http://msdn.microsoft.com/en-us/library/ms644904(v=VS.85).aspx">QueryPerformanceCounter()</a>.
QueryPerformanceFrequency() 返回计数的频率,QueryPerformanceCounter()返回当前计数值.和 Linux 中 CLOCK_MONOTONIC 一样,它是一个稳定并单调递增计数器,精准达到纳秒级,并且不会 wrap around.</p>

<p>更多参考:</p>

<ul>
  <li><a href="https://blog.habets.se/2010/09/gettimeofday-should-never-be-used-to-measure-time">gettimeofday() should never be used to measure time</a></li>
  <li><a href="http://tdistler.com/2010/06/27/high-performance-timing-on-linux-windows">High-performance Timing on Linux / Windows</a></li>
</ul>

<h2 id="high-resolution-time">不同平台 High Resolution Time</h2>

<h3 id="linux">Linux</h3>
<p>使用
<a href="http://linux.die.net/man/3/clock_gettime">clock_gettime(CLOCK_MONOTONIC,..)</a>
作为 High Resolution Time,编译需加上参数<code>-lrt</code>,实例代码如下:</p>

<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span>clock_gettime.c</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
<span class="line-number">5</span>
<span class="line-number">6</span>
<span class="line-number">7</span>
<span class="line-number">8</span>
<span class="line-number">9</span>
<span class="line-number">10</span>
<span class="line-number">11</span>
<span class="line-number">12</span>
<span class="line-number">13</span>
<span class="line-number">14</span>
<span class="line-number">15</span>
<span class="line-number">16</span>
<span class="line-number">17</span>
<span class="line-number">18</span>
<span class="line-number">19</span>
<span class="line-number">20</span>
<span class="line-number">21</span>
<span class="line-number">22</span>
<span class="line-number">23</span>
<span class="line-number">24</span>
<span class="line-number">25</span>
</pre></td><td class="code"><pre><code class="c"><span class="line"><span class="cp">#include &lt;time.h&gt;</span>
</span><span class="line"><span class="cp">#include &lt;stdio.h&gt;</span>
</span><span class="line">
</span><span class="line"><span class="kt">void</span> <span class="nf">GetMonotonicTime</span><span class="p">(</span><span class="k">struct</span> <span class="n">timespec</span> <span class="o">*</span><span class="n">ts</span><span class="p">)</span> <span class="p">{</span>
</span><span class="line">  <span class="n">clock_gettime</span><span class="p">(</span><span class="n">CLOCK_MONOTONIC</span><span class="p">,</span> <span class="n">ts</span><span class="p">);</span>
</span><span class="line"><span class="p">}</span>
</span><span class="line">
</span><span class="line"><span class="kt">double</span> <span class="nf">GetElapsedTime</span><span class="p">(</span><span class="k">struct</span> <span class="n">timespec</span> <span class="o">*</span><span class="n">before</span><span class="p">,</span> <span class="k">struct</span> <span class="n">timespec</span> <span class="o">*</span><span class="n">after</span><span class="p">)</span> <span class="p">{</span>
</span><span class="line">  <span class="kt">double</span> <span class="n">delta_s</span> <span class="o">=</span> <span class="n">after</span><span class="o">-&gt;</span><span class="n">tv_sec</span> <span class="o">-</span> <span class="n">before</span><span class="o">-&gt;</span><span class="n">tv_sec</span><span class="p">;</span>
</span><span class="line">  <span class="kt">double</span> <span class="n">delta_ns</span> <span class="o">=</span> <span class="n">after</span><span class="o">-&gt;</span><span class="n">tv_nsec</span> <span class="o">-</span> <span class="n">before</span><span class="o">-&gt;</span><span class="n">tv_nsec</span><span class="p">;</span>
</span><span class="line">  <span class="k">return</span> <span class="n">delta_s</span> <span class="o">*</span> <span class="mf">1e9</span> <span class="o">+</span> <span class="n">delta_ns</span><span class="p">;</span>
</span><span class="line"><span class="p">}</span>
</span><span class="line">
</span><span class="line"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> <span class="p">{</span>
</span><span class="line">  <span class="k">struct</span> <span class="n">timespec</span> <span class="n">before</span><span class="p">,</span> <span class="n">after</span><span class="p">;</span>
</span><span class="line">  <span class="n">GetMonotonicTime</span><span class="p">(</span><span class="o">&amp;</span><span class="n">before</span><span class="p">);</span>
</span><span class="line">  <span class="kt">double</span> <span class="n">sum</span> <span class="o">=</span> <span class="mf">0.0</span><span class="p">;</span>
</span><span class="line">  <span class="kt">unsigned</span> <span class="kt">int</span> <span class="n">i</span><span class="p">;</span>
</span><span class="line">  <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">100</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
</span><span class="line">    <span class="n">sum</span> <span class="o">+=</span> <span class="mf">1.0</span> <span class="o">/</span> <span class="n">i</span><span class="p">;</span>
</span><span class="line">  <span class="p">}</span>
</span><span class="line">  <span class="n">GetMonotonicTime</span><span class="p">(</span><span class="o">&amp;</span><span class="n">after</span><span class="p">);</span>
</span><span class="line">  <span class="n">printf</span><span class="p">(</span><span class="s">&quot;the elapsed time=%e ns</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">,</span> <span class="n">GetElapsedTime</span><span class="p">(</span><span class="o">&amp;</span><span class="n">before</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">after</span><span class="p">));</span>
</span><span class="line">  <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span><span class="line"><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure></notextile></div>

<p>除了<code>clock_gettime()</code>高精度时钟外,还有相对应的高精度的睡眠函数
<a href="http://pubs.opengroup.org/onlinepubs/000095399/functions/clock_nanosleep.html">clock_nanosleep</a>,
实例代码如下:</p>

<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span>clock_nanosleep.c</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
<span class="line-number">5</span>
<span class="line-number">6</span>
<span class="line-number">7</span>
<span class="line-number">8</span>
<span class="line-number">9</span>
<span class="line-number">10</span>
</pre></td><td class="code"><pre><code class="c"><span class="line"><span class="cp">#include &lt;time.h&gt;</span>
</span><span class="line">
</span><span class="line"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span>
</span><span class="line"><span class="p">{</span>
</span><span class="line">  <span class="k">struct</span> <span class="n">timespec</span> <span class="n">sleep_time</span><span class="p">;</span>
</span><span class="line">  <span class="n">sleep_time</span><span class="p">.</span><span class="n">tv_sec</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span><span class="line">  <span class="n">sleep_time</span><span class="p">.</span><span class="n">tv_nsec</span> <span class="o">=</span> <span class="mi">100</span><span class="p">;</span>
</span><span class="line">  <span class="n">clock_nanosleep</span><span class="p">(</span><span class="n">CLOCK_REALTIME</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">sleep_time</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">);</span>
</span><span class="line">  <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span><span class="line"><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure></notextile></div>

<h3 id="os-x">OS X</h3>

<h3 id="clockgettime">使用<code>clock_get_time</code></h3>
<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span>clock_get_time.c</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
<span class="line-number">5</span>
<span class="line-number">6</span>
<span class="line-number">7</span>
<span class="line-number">8</span>
<span class="line-number">9</span>
<span class="line-number">10</span>
<span class="line-number">11</span>
<span class="line-number">12</span>
<span class="line-number">13</span>
<span class="line-number">14</span>
<span class="line-number">15</span>
<span class="line-number">16</span>
<span class="line-number">17</span>
<span class="line-number">18</span>
<span class="line-number">19</span>
<span class="line-number">20</span>
<span class="line-number">21</span>
<span class="line-number">22</span>
<span class="line-number">23</span>
<span class="line-number">24</span>
<span class="line-number">25</span>
<span class="line-number">26</span>
<span class="line-number">27</span>
<span class="line-number">28</span>
<span class="line-number">29</span>
<span class="line-number">30</span>
<span class="line-number">31</span>
<span class="line-number">32</span>
<span class="line-number">33</span>
</pre></td><td class="code"><pre><code class="c"><span class="line"><span class="cp">#include &lt;time.h&gt;</span>
</span><span class="line"><span class="cp">#include &lt;stdio.h&gt;</span>
</span><span class="line"><span class="cp">#include &lt;mach/clock.h&gt;</span>
</span><span class="line"><span class="cp">#include &lt;mach/mach.h&gt;</span>
</span><span class="line">
</span><span class="line"><span class="kt">void</span> <span class="nf">GetMonotonicTime</span><span class="p">(</span><span class="k">struct</span> <span class="n">timespec</span> <span class="o">*</span><span class="n">ts</span><span class="p">)</span> <span class="p">{</span>
</span><span class="line">  <span class="n">clock_serv_t</span> <span class="n">cclock</span><span class="p">;</span>
</span><span class="line">  <span class="n">mach_timespec_t</span> <span class="n">mts</span><span class="p">;</span>
</span><span class="line">  <span class="n">host_get_clock_service</span><span class="p">(</span><span class="n">mach_host_self</span><span class="p">(),</span> <span class="n">SYSTEM_CLOCK</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">cclock</span><span class="p">);</span>
</span><span class="line">  <span class="n">clock_get_time</span><span class="p">(</span><span class="n">cclock</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">mts</span><span class="p">);</span>
</span><span class="line">  <span class="n">mach_port_deallocate</span><span class="p">(</span><span class="n">mach_task_self</span><span class="p">(),</span> <span class="n">cclock</span><span class="p">);</span>
</span><span class="line">  <span class="n">ts</span><span class="o">-&gt;</span><span class="n">tv_sec</span> <span class="o">=</span> <span class="n">mts</span><span class="p">.</span><span class="n">tv_sec</span><span class="p">;</span>
</span><span class="line">  <span class="n">ts</span><span class="o">-&gt;</span><span class="n">tv_nsec</span> <span class="o">=</span> <span class="n">mts</span><span class="p">.</span><span class="n">tv_nsec</span><span class="p">;</span>
</span><span class="line"><span class="p">}</span>
</span><span class="line">
</span><span class="line"><span class="kt">double</span> <span class="nf">GetElapsedTime</span><span class="p">(</span><span class="k">struct</span> <span class="n">timespec</span> <span class="o">*</span><span class="n">before</span><span class="p">,</span> <span class="k">struct</span> <span class="n">timespec</span> <span class="o">*</span><span class="n">after</span><span class="p">)</span> <span class="p">{</span>
</span><span class="line">  <span class="kt">double</span> <span class="n">delta_s</span> <span class="o">=</span> <span class="n">after</span><span class="o">-&gt;</span><span class="n">tv_sec</span> <span class="o">-</span> <span class="n">before</span><span class="o">-&gt;</span><span class="n">tv_sec</span><span class="p">;</span>
</span><span class="line">  <span class="kt">double</span> <span class="n">delta_ns</span> <span class="o">=</span> <span class="n">after</span><span class="o">-&gt;</span><span class="n">tv_nsec</span> <span class="o">-</span> <span class="n">before</span><span class="o">-&gt;</span><span class="n">tv_nsec</span><span class="p">;</span>
</span><span class="line">  <span class="k">return</span> <span class="n">delta_s</span> <span class="o">*</span> <span class="mf">1e9</span> <span class="o">+</span> <span class="n">delta_ns</span><span class="p">;</span>
</span><span class="line"><span class="p">}</span>
</span><span class="line">
</span><span class="line"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> <span class="p">{</span>
</span><span class="line">  <span class="k">struct</span> <span class="n">timespec</span> <span class="n">before</span><span class="p">,</span> <span class="n">after</span><span class="p">;</span>
</span><span class="line">  <span class="n">GetMonotonicTime</span><span class="p">(</span><span class="o">&amp;</span><span class="n">before</span><span class="p">);</span>
</span><span class="line">  <span class="kt">double</span> <span class="n">sum</span> <span class="o">=</span> <span class="mf">0.0</span><span class="p">;</span>
</span><span class="line">  <span class="kt">unsigned</span> <span class="kt">int</span> <span class="n">i</span><span class="p">;</span>
</span><span class="line">  <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">100</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
</span><span class="line">    <span class="n">sum</span> <span class="o">+=</span> <span class="mf">1.0</span> <span class="o">/</span> <span class="n">i</span><span class="p">;</span>
</span><span class="line">  <span class="p">}</span>
</span><span class="line">  <span class="n">GetMonotonicTime</span><span class="p">(</span><span class="o">&amp;</span><span class="n">after</span><span class="p">);</span>
</span><span class="line">  <span class="n">printf</span><span class="p">(</span><span class="s">&quot;the elapsed time=%e ns</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">,</span> <span class="n">GetElapsedTime</span><span class="p">(</span><span class="o">&amp;</span><span class="n">before</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">after</span><span class="p">));</span>
</span><span class="line">  <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span><span class="line"><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure></notextile></div>

<h3 id="machabsolutetime">使用<code>mach_absolute_time</code></h3>
<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span>mach_absolute_time.c</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
<span class="line-number">5</span>
<span class="line-number">6</span>
<span class="line-number">7</span>
<span class="line-number">8</span>
<span class="line-number">9</span>
<span class="line-number">10</span>
<span class="line-number">11</span>
<span class="line-number">12</span>
<span class="line-number">13</span>
<span class="line-number">14</span>
<span class="line-number">15</span>
<span class="line-number">16</span>
</pre></td><td class="code"><pre><code class="c"><span class="line"><span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="kt">char</span> <span class="o">*</span><span class="n">argv</span><span class="p">[])</span> <span class="p">{</span>
</span><span class="line">    <span class="kt">uint64_t</span>        <span class="n">start</span><span class="p">;</span>
</span><span class="line">    <span class="kt">uint64_t</span>        <span class="n">end</span><span class="p">;</span>
</span><span class="line">    <span class="kt">uint64_t</span>        <span class="n">elapsed</span><span class="p">;</span>
</span><span class="line">    <span class="n">Nanoseconds</span>     <span class="n">elapsedNano</span><span class="p">;</span>
</span><span class="line">    <span class="n">start</span> <span class="o">=</span> <span class="n">mach_absolute_time</span><span class="p">();</span>
</span><span class="line">    <span class="kt">double</span> <span class="n">sum</span> <span class="o">=</span> <span class="mf">0.0</span><span class="p">;</span>
</span><span class="line">    <span class="kt">unsigned</span> <span class="kt">int</span> <span class="n">i</span><span class="p">;</span>
</span><span class="line">    <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">100</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
</span><span class="line">        <span class="n">sum</span> <span class="o">+=</span> <span class="mf">1.0</span> <span class="o">/</span> <span class="n">i</span><span class="p">;</span>
</span><span class="line">    <span class="p">}</span>
</span><span class="line">    <span class="n">end</span> <span class="o">=</span> <span class="n">mach_absolute_time</span><span class="p">();</span>
</span><span class="line">    <span class="n">elapsed</span> <span class="o">=</span> <span class="n">end</span> <span class="o">-</span> <span class="n">start</span><span class="p">;</span>
</span><span class="line">    <span class="c1">// Convert to nanoseconds</span>
</span><span class="line">    <span class="n">elapsedNano</span> <span class="o">=</span> <span class="n">AbsoluteToNanoseconds</span><span class="p">(</span> <span class="o">*</span><span class="p">(</span><span class="n">AbsoluteTime</span> <span class="o">*</span><span class="p">)</span> <span class="o">&amp;</span><span class="n">elapsed</span> <span class="p">);</span>
</span><span class="line"><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure></notextile></div>

<h3 id="windows">Windows</h3>
<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span>query_performance.cc</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
<span class="line-number">5</span>
<span class="line-number">6</span>
<span class="line-number">7</span>
<span class="line-number">8</span>
<span class="line-number">9</span>
<span class="line-number">10</span>
<span class="line-number">11</span>
<span class="line-number">12</span>
<span class="line-number">13</span>
<span class="line-number">14</span>
<span class="line-number">15</span>
<span class="line-number">16</span>
<span class="line-number">17</span>
<span class="line-number">18</span>
<span class="line-number">19</span>
<span class="line-number">20</span>
<span class="line-number">21</span>
<span class="line-number">22</span>
<span class="line-number">23</span>
<span class="line-number">24</span>
<span class="line-number">25</span>
<span class="line-number">26</span>
<span class="line-number">27</span>
<span class="line-number">28</span>
<span class="line-number">29</span>
</pre></td><td class="code"><pre><code class="c++"><span class="line"><span class="cp">#include &lt;iostream&gt;</span>
</span><span class="line"><span class="cp">#include &lt;windows.h&gt; </span>
</span><span class="line"><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span>
</span><span class="line">
</span><span class="line"><span class="kt">int</span> <span class="n">main</span><span class="p">()</span>
</span><span class="line"><span class="p">{</span>
</span><span class="line">    <span class="n">LARGE_INTEGER</span> <span class="n">frequency</span><span class="p">;</span>
</span><span class="line">    <span class="n">LARGE_INTEGER</span> <span class="n">start</span><span class="p">,</span> <span class="n">end</span><span class="p">;</span>
</span><span class="line">    <span class="kt">double</span> <span class="n">elapsedTime</span><span class="p">;</span>
</span><span class="line">
</span><span class="line">    <span class="c1">// get ticks per second</span>
</span><span class="line">    <span class="n">QueryPerformanceFrequency</span><span class="p">(</span><span class="o">&amp;</span><span class="n">frequency</span><span class="p">);</span>
</span><span class="line">
</span><span class="line">    <span class="n">QueryPerformanceCounter</span><span class="p">(</span><span class="o">&amp;</span><span class="n">start</span><span class="p">);</span>
</span><span class="line">
</span><span class="line">    <span class="c1">//do someting</span>
</span><span class="line">    <span class="kt">double</span> <span class="n">sum</span> <span class="o">=</span> <span class="mf">0.0</span><span class="p">;</span>
</span><span class="line">    <span class="kt">unsigned</span> <span class="kt">int</span> <span class="n">i</span><span class="p">;</span>
</span><span class="line">    <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">100</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
</span><span class="line">        <span class="n">sum</span> <span class="o">+=</span> <span class="mf">1.0</span> <span class="o">/</span> <span class="n">i</span><span class="p">;</span>
</span><span class="line">    <span class="p">}</span>
</span><span class="line">
</span><span class="line">    <span class="n">QueryPerformanceCounter</span><span class="p">(</span><span class="o">&amp;</span><span class="n">end</span><span class="p">);</span>
</span><span class="line">
</span><span class="line">    <span class="c1">// compute and print the elapsed time in millisec</span>
</span><span class="line">    <span class="n">elapsedTime</span> <span class="o">=</span> <span class="p">(</span><span class="n">end</span><span class="p">.</span><span class="n">QuadPart</span> <span class="o">-</span> <span class="n">start</span><span class="p">.</span><span class="n">QuadPart</span><span class="p">)</span> <span class="o">*</span> <span class="mf">1000.0</span> <span class="o">/</span> <span class="n">frequency</span><span class="p">.</span><span class="n">QuadPart</span><span class="p">;</span>
</span><span class="line">    <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">elapsedTime</span> <span class="o">&lt;&lt;</span> <span class="s">&quot; ms.</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">;</span>
</span><span class="line">    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span><span class="line"><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure></notextile></div>

<div class="footnotes">
  <ol>
    <li id="fn:f1">
      <p>http://stackoverflow.com/questions/12392278/measure-time-in-linux-getrusage-vs-clock-gettime-vs-clock-vs-gettimeofday<a href="#fnref:f1" rel="reference">&#8617;</a></p>
    </li>
  </ol>
</div>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Double-Checked Locking Works in C++11]]></title>
    <link href="http://dreamrunner.org/blog/2014/06/22/double-checked-locking-works-in-c-plus-plus-11/"/>
    <updated>2014-06-22T14:07:01+08:00</updated>
    <id>http://dreamrunner.org/blog/2014/06/22/double-checked-locking-works-in-c-plus-plus-11</id>
    <content type="html"><![CDATA[<p>在
<a href="http://dreamrunner.org/blog/2014/05/03/%E6%B5%85%E8%B0%88%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F6/">浅谈设计模式六: 单例模式(Singleton)</a>
中提到 double-checked locking pattern(DCLP)来实现 Singleton 设计模式，但是在 C++11 之前，没有安全方法在可移植的 C++中去实现它．具体原因可见
<a href="http://dreamrunner.org/blog/2014/05/03/%E6%B5%85%E8%B0%88%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F6/">单例模式(Singleton)</a>
或 Scott Meyers 和 Andrei Alexandrescu 发布的原文
<a href="http://www.aristeia.com/Papers/DDJ_Jul_Aug_2004_revised.pdf">“C++ and the Perils of Double-Checked Locking”</a>
．</p>

<p>C++11 引入了新的内存模型和线程库，使得能在 C++中实现可移植的 DCLP．本文说明如何实现它．</p>

<!-- more -->

<h2 id="double-checked-locking">什么是 Double-Checked Locking</h2>
<p>在
<a href="http://dreamrunner.org/blog/2014/05/03/%E6%B5%85%E8%B0%88%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F6/">单例模式(Singleton)</a>
很好的介绍什么是 DCLP,这里稍作回顾.</p>

<p>线程安全的方式实现 Signleton 模式如下:</p>

<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span>singleton.cc</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
<span class="line-number">5</span>
<span class="line-number">6</span>
<span class="line-number">7</span>
</pre></td><td class="code"><pre><code class="c++"><span class="line"><span class="n">Singleton</span><span class="o">*</span> <span class="n">Singleton</span><span class="o">::</span><span class="n">instance</span><span class="p">()</span> <span class="p">{</span>
</span><span class="line">  <span class="n">Lock</span> <span class="n">lock</span><span class="p">;</span>    <span class="c1">// acquire lock (params omitted for simplicity)</span>
</span><span class="line">  <span class="k">if</span><span class="p">(</span><span class="n">pInstance</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span> <span class="p">{</span>
</span><span class="line">    <span class="n">pInstance</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Singleton</span><span class="p">();</span>
</span><span class="line">  <span class="p">}</span>
</span><span class="line">  <span class="k">return</span> <span class="n">pInstance</span><span class="p">;</span>
</span><span class="line">  <span class="p">}</span>  <span class="c1">// release lock (via Lock destructor)</span>
</span></code></pre></td></tr></table></div></figure></notextile></div>

<p>每次获取 Singleton 都要获取一个锁，但是实际上，我们只有当初始化 pInstance 时才需要一个锁。也就是只发生在第一次调用 instance 时。如果在一个程序运行时， instance 被调用了 n 次，我们只需要锁在第一次调用时。当我们知道那 n-1 次锁是没必要的.</p>

<p>DCLP 的关键点是发现，大多数 instance 的调用将看到 pInstance 是非空的，因此根本没必要去尝试初始化它。因此，DCLP 判断 pInstance 是否为空在尝试获取锁前。只有当判断成功（ pInstance 还没有被初始化）才去获取锁，然后之后这个判断在此进行一次确保 pInstance 是仍然空的。（所以名字叫双重检查锁）。第二个检查是有必要的，因为从上可以看到，另外的线程可能碰巧初始化了 pInstance 在 pInstance 被第一次判断和获取锁之间。</p>

<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span>singleton-dclp.cc</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
<span class="line-number">5</span>
<span class="line-number">6</span>
<span class="line-number">7</span>
<span class="line-number">8</span>
<span class="line-number">9</span>
<span class="line-number">10</span>
<span class="line-number">11</span>
<span class="line-number">12</span>
<span class="line-number">13</span>
<span class="line-number">14</span>
</pre></td><td class="code"><pre><code class="c++"><span class="line"><span class="n">Singleton</span><span class="o">*</span> <span class="n">Singleton</span><span class="o">::</span><span class="n">instance</span><span class="p">()</span> <span class="p">{</span>
</span><span class="line">  <span class="n">Singleton</span> <span class="o">*</span><span class="n">tmp</span> <span class="o">=</span> <span class="n">pInstance</span><span class="p">;</span>
</span><span class="line">  <span class="p">...</span>  <span class="c1">// need memory barrier</span>
</span><span class="line">  <span class="k">if</span><span class="p">(</span><span class="n">tmp</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 1st test</span>
</span><span class="line">  <span class="n">Lock</span> <span class="n">lock</span><span class="p">;</span>
</span><span class="line">  <span class="n">tmp</span> <span class="o">=</span> <span class="n">pInstance</span><span class="p">;</span>
</span><span class="line">  <span class="k">if</span><span class="p">(</span><span class="n">tmp</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 2nd test</span>
</span><span class="line">    <span class="n">tmp</span>  <span class="o">=</span> <span class="k">new</span> <span class="n">Singleton</span><span class="p">;</span>
</span><span class="line">  <span class="p">...</span>  <span class="c1">// need memory barrier</span>
</span><span class="line">    <span class="n">pInstance</span> <span class="o">=</span> <span class="n">tmp</span><span class="p">;</span>
</span><span class="line">  <span class="p">}</span>
</span><span class="line">  <span class="p">}</span>
</span><span class="line"><span class="k">return</span> <span class="n">pInstance</span><span class="p">;</span>
</span><span class="line"><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure></notextile></div>

<p><a href="http://dreamrunner.org/blog/2014/05/03/%E6%B5%85%E8%B0%88%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F6/">单例模式(Singleton)</a>
说明了各种不安全实现的缺陷,主要原因是 1) 编译器的乱序编译 和 2) CPU 的乱序执行指令.所以安全的实现依靠 memory barrier,防止它们的乱序,使得在多线程中得到同步,C++11 之前没有可移植的 C/C++函数,但现在,C++11 有了.</p>

<h2 id="c11--acqure--release-fence">使用 C++11 的 Acqure 和 Release Fence</h2>
<p>使用 Acqure 和 Release Fence 来实现它,并且保证对实例<code>pInstance</code>进行原子操作,把它定义为<code>atomic</code>类型,并用<code>memory_order_relaxed</code>操作.(Relaxed
ordering: there are no synchronization or ordering constraints, only
atomicity is required of this operation.)如下实现代码.</p>

<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
<span class="line-number">5</span>
<span class="line-number">6</span>
<span class="line-number">7</span>
<span class="line-number">8</span>
<span class="line-number">9</span>
<span class="line-number">10</span>
<span class="line-number">11</span>
<span class="line-number">12</span>
<span class="line-number">13</span>
<span class="line-number">14</span>
<span class="line-number">15</span>
<span class="line-number">16</span>
<span class="line-number">17</span>
</pre></td><td class="code"><pre><code class="c++"><span class="line"><span class="n">std</span><span class="o">::</span><span class="n">atomic</span><span class="o">&lt;</span><span class="n">Singleton</span> <span class="o">*&gt;</span> <span class="n">Singleton</span><span class="o">::</span><span class="n">m_pInstance</span><span class="p">;</span>
</span><span class="line"><span class="n">std</span><span class="o">::</span><span class="n">mutex</span> <span class="n">Singleton</span><span class="o">::</span><span class="n">m_mutex</span><span class="p">;</span>
</span><span class="line">
</span><span class="line"><span class="n">Singleton</span><span class="o">*</span> <span class="n">Singleton</span><span class="o">::</span><span class="n">instance</span><span class="p">()</span> <span class="p">{</span>
</span><span class="line">  <span class="n">Singleton</span> <span class="o">*</span><span class="n">tmp</span> <span class="o">=</span> <span class="n">m_pInstance</span><span class="p">.</span><span class="n">load</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">memory_order_relaxed</span><span class="p">);</span>
</span><span class="line">  <span class="n">std</span><span class="o">::</span><span class="n">atomic_thread_fence</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">memory_order_acquire</span><span class="p">);</span>
</span><span class="line">  <span class="k">if</span><span class="p">(</span><span class="n">tmp</span> <span class="o">==</span> <span class="n">nullptr</span><span class="p">)</span> <span class="p">{</span>
</span><span class="line">    <span class="n">std</span><span class="o">::</span><span class="n">lock_guard</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">mutex</span><span class="o">&gt;</span> <span class="n">lock</span><span class="p">(</span><span class="n">m_mutex</span><span class="p">);</span>
</span><span class="line">    <span class="n">tmp</span> <span class="o">=</span> <span class="n">m_pInstance</span><span class="p">.</span><span class="n">load</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">memory_order_relaxed</span><span class="p">);</span>
</span><span class="line">    <span class="k">if</span><span class="p">(</span><span class="n">tmp</span> <span class="o">==</span> <span class="n">nullptr</span><span class="p">)</span> <span class="p">{</span>
</span><span class="line">      <span class="n">tmp</span>  <span class="o">=</span> <span class="k">new</span> <span class="n">Singleton</span><span class="p">;</span>
</span><span class="line">      <span class="n">std</span><span class="o">::</span><span class="n">atomic_thread_fence</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">memory_order_release</span><span class="p">);</span>
</span><span class="line">      <span class="n">m_pInstance</span><span class="p">.</span><span class="n">store</span><span class="p">(</span><span class="n">tmp</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">memory_order_relaxed</span><span class="p">);</span>
</span><span class="line">    <span class="p">}</span>
</span><span class="line">  <span class="p">}</span>
</span><span class="line">  <span class="k">return</span> <span class="n">m_pInstance</span><span class="p">;</span>
</span><span class="line"><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure></notextile></div>

<p>在多核系统中,这整个代码也是稳健的,因为 memory fences 在多个线程间建立了同步的关系.<code>Singleton::m_pInstance</code>作为 guard variable,singleton 变量自身成为 payload.</p>

<p>如果没有这层同步关系的话,就不能保证第一个线程的所有写操作(这里就是
singleton 实力的创建)被第二个线程读取到,即使<code>m_pInstance</code>已经被第二个线程能看到.</p>

<h2 id="c11--c11-">使用 C++11 的底层的内存顺序约束在 C++11 中也可以在单元操作时附加底层的内存顺序约束来达到同样的目的.一个</h2>
<p>write-release 能同步于一个 read-release.</p>

<ol>
  <li>
    <p><code>memory_order_acquire</code>: A load operation with this memory order performs the acquire operation on the affected memory location: prior writes made to other memory locations by the thread that did the release become visible in this thread.</p>
  </li>
  <li>
    <p><code>memory_order_release</code>: A store operation with this memory order performs the release operation: prior writes to other memory locations become visible to the threads that do a consume or an acquire on the same location.</p>
  </li>
</ol>

<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
<span class="line-number">5</span>
<span class="line-number">6</span>
<span class="line-number">7</span>
<span class="line-number">8</span>
<span class="line-number">9</span>
<span class="line-number">10</span>
<span class="line-number">11</span>
<span class="line-number">12</span>
<span class="line-number">13</span>
<span class="line-number">14</span>
<span class="line-number">15</span>
</pre></td><td class="code"><pre><code class="c++"><span class="line"><span class="n">std</span><span class="o">::</span><span class="n">atomic</span><span class="o">&lt;</span><span class="n">Singleton</span> <span class="o">*&gt;</span> <span class="n">Singleton</span><span class="o">::</span><span class="n">m_pInstance</span><span class="p">;</span>
</span><span class="line"><span class="n">std</span><span class="o">::</span><span class="n">mutex</span> <span class="n">Singleton</span><span class="o">::</span><span class="n">m_mutex</span><span class="p">;</span>
</span><span class="line">
</span><span class="line"><span class="n">Singleton</span><span class="o">*</span> <span class="n">Singleton</span><span class="o">::</span><span class="n">instance</span><span class="p">()</span> <span class="p">{</span>
</span><span class="line">  <span class="n">Singleton</span> <span class="o">*</span><span class="n">tmp</span> <span class="o">=</span> <span class="n">m_pInstance</span><span class="p">.</span><span class="n">load</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">memory_order_acquire</span><span class="p">);</span>
</span><span class="line">  <span class="k">if</span><span class="p">(</span><span class="n">tmp</span> <span class="o">==</span> <span class="n">nullptr</span><span class="p">)</span> <span class="p">{</span>
</span><span class="line">    <span class="n">std</span><span class="o">::</span><span class="n">lock_guard</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">mutex</span><span class="o">&gt;</span> <span class="n">lock</span><span class="p">(</span><span class="n">m_mutex</span><span class="p">);</span>
</span><span class="line">    <span class="n">tmp</span> <span class="o">=</span> <span class="n">m_pInstance</span><span class="p">.</span><span class="n">load</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">memory_order_relaxed</span><span class="p">);</span>
</span><span class="line">    <span class="k">if</span><span class="p">(</span><span class="n">tmp</span> <span class="o">==</span> <span class="n">nullptr</span><span class="p">)</span> <span class="p">{</span>
</span><span class="line">      <span class="n">tmp</span>  <span class="o">=</span> <span class="k">new</span> <span class="n">Singleton</span><span class="p">;</span>
</span><span class="line">      <span class="n">m_pInstance</span><span class="p">.</span><span class="n">store</span><span class="p">(</span><span class="n">tmp</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">memory_order_release</span><span class="p">);</span>
</span><span class="line">    <span class="p">}</span>
</span><span class="line">  <span class="p">}</span>
</span><span class="line">  <span class="k">return</span> <span class="n">m_pInstance</span><span class="p">;</span>
</span><span class="line"><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure></notextile></div>

<p>从深层分析来看,这种形式的免锁机制的同步比上面单独 memory fences 来的约束更小.这种形式的操作只意味在这个操作周围防止内存乱序,而 memory fences 意味着在一块区域内防止内存乱序.更多细节参考 preshing 的
<a href="http://preshing.com/20131125/acquire-and-release-fences-dont-work-the-way-youd-expect/">Acquire and Release Fences Don’t Work the Way You’d Expect</a>
的分析.
## 使用 C++11 的 Sequentially-consistent ordering
C++11 还提供了其他的方法来写 lock-free 的代码.当在 atomic 操作函数中忽略
<code>std::memory_order</code>参数项,那么默认值是<code>std::memory_order_seq_cst</code>,使得所有原子参数成为
<a href="http://en.wikipedia.org/wiki/Sequential_consistency">sequentically consistent(SC)</a>
原子.通过 SC 原子性,整个算法保证 sequentically consistent 只要没有 <a href="http://www.devx.com/cplus/Article/42725">data races</a>.</p>

<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
<span class="line-number">5</span>
<span class="line-number">6</span>
<span class="line-number">7</span>
<span class="line-number">8</span>
<span class="line-number">9</span>
<span class="line-number">10</span>
<span class="line-number">11</span>
<span class="line-number">12</span>
<span class="line-number">13</span>
<span class="line-number">14</span>
<span class="line-number">15</span>
<span class="line-number">16</span>
<span class="line-number">17</span>
</pre></td><td class="code"><pre><code class="c++"><span class="line"><span class="n">std</span><span class="o">::</span><span class="n">atomic</span><span class="o">&lt;</span><span class="n">Singleton</span> <span class="o">*&gt;</span> <span class="n">Singleton</span><span class="o">::</span><span class="n">m_pInstance</span><span class="p">;</span>
</span><span class="line"><span class="n">std</span><span class="o">::</span><span class="n">mutex</span> <span class="n">Singleton</span><span class="o">::</span><span class="n">m_mutex</span><span class="p">;</span>
</span><span class="line">
</span><span class="line"><span class="n">Singleton</span><span class="o">*</span> <span class="n">Singleton</span><span class="o">::</span><span class="n">instance</span><span class="p">()</span> <span class="p">{</span>
</span><span class="line">  <span class="n">Singleton</span> <span class="o">*</span><span class="n">tmp</span> <span class="o">=</span> <span class="n">m_pInstance</span><span class="p">.</span><span class="n">load</span><span class="p">();</span>
</span><span class="line">  <span class="n">std</span><span class="o">::</span><span class="n">atomic_thread_fence</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">memory_order_acquire</span><span class="p">);</span>
</span><span class="line">  <span class="k">if</span><span class="p">(</span><span class="n">tmp</span> <span class="o">==</span> <span class="n">nullptr</span><span class="p">)</span> <span class="p">{</span>
</span><span class="line">    <span class="n">std</span><span class="o">::</span><span class="n">lock_guard</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">mutex</span><span class="o">&gt;</span> <span class="n">lock</span><span class="p">(</span><span class="n">m_mutex</span><span class="p">);</span>
</span><span class="line">    <span class="n">tmp</span> <span class="o">=</span> <span class="n">m_pInstance</span><span class="p">.</span><span class="n">load</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">memory_order_relaxed</span><span class="p">);</span>
</span><span class="line">    <span class="k">if</span><span class="p">(</span><span class="n">tmp</span> <span class="o">==</span> <span class="n">nullptr</span><span class="p">)</span> <span class="p">{</span>
</span><span class="line">      <span class="n">tmp</span>  <span class="o">=</span> <span class="k">new</span> <span class="n">Singleton</span><span class="p">;</span>
</span><span class="line">      <span class="n">std</span><span class="o">::</span><span class="n">atomic_thread_fence</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">memory_order_release</span><span class="p">);</span>
</span><span class="line">      <span class="n">m_pInstance</span><span class="p">.</span><span class="n">store</span><span class="p">(</span><span class="n">tmp</span><span class="p">);</span>
</span><span class="line">    <span class="p">}</span>
</span><span class="line">  <span class="p">}</span>
</span><span class="line">  <span class="k">return</span> <span class="n">m_pInstance</span><span class="p">;</span>
</span><span class="line"><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure></notextile></div>

<p>SC 的原子性可能更容易理解.权衡点就是它产生的机器代码没有之前做法的高效.比如如下是 Gcc 4.8.2 intle X64 对上面代码产生的机器代码,通过<code>g++ -O2 -std=c++11 -S</code>.
<img src="http://dreamrunner.org/images/blog/2014/multithreading/sc.png" title="sc'" /></p>

<p>因为使用了 SC 原子性,对<code>m_pInstance</code>的存储实现使用了<code>mfence</code>指令,起到一个在 X64 上的 full memory fence.这是个更严格的指令想对于 DCLP 在 X64 上的实际需求.一个普通的<code>mov</code>足以胜任.但也无关紧要,因为<code>mfence</code>指令也仅仅执行一次而已,就在创建 singleton 的实例的代码路径上.</p>

<h2 id="more">More</h2>
<p>使用 <a href="http://preshing.com">Preshing</a> 的小型可移植的 lock-free 库,在没有 C++11
的支持下,使用它的 <a href="http://preshing.com/20130930/double-checked-locking-is-fixed-in-cpp11/#using-mintomic-fences">Mintomic Fences 实现 DCLP</a>.</p>

<p>更多关于 C++11 的 multithreading 库的详解见之后的文章.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Algorithm Design Manual Chapter 6]]></title>
    <link href="http://dreamrunner.org/blog/2014/06/15/The-Algorithm-Design-Manual6/"/>
    <updated>2014-06-15T00:00:00+08:00</updated>
    <id>http://dreamrunner.org/blog/2014/06/15/The-Algorithm-Design-Manual6</id>
    <content type="html"><![CDATA[<div id="outline-container-sec-1" class="outline-2">
<h2 id="sec-1">Book Notes</h2>
<div class="outline-text-2" id="text-1">
</div><div id="outline-container-sec-1-1" class="outline-3">
<h3 id="sec-1-1">6.1 Minimum Spanning Trees</h3>
<div class="outline-text-3" id="text-1-1">
</div><div id="outline-container-sec-1-1-1" class="outline-4">
<h4 id="sec-1-1-1">6.1.1 Prim’s Algorithm</h4>
<div class="outline-text-4" id="text-1-1-1">
<p>
A greedy algorithm suffices for correctness: we always add the
lowest-weight edge linking a vertex in the tree to a vertex on the
outside. （选取相邻最近的不在树内的点。）
</p>

<!-- more -->

<div class="org-src-container">

<pre class="src src-c++"><span style="color: #87cefa;">prim</span>(<span style="color: #98fb98;">graph</span> *<span style="color: #eedd82;">g</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">start</span>)
{
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span>; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">counter */</span>
  <span style="color: #98fb98;">edgenode</span> *<span style="color: #eedd82;">p</span>; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">temporary pointer */</span>
  <span style="color: #98fb98;">bool</span> <span style="color: #eedd82;">intree</span>[MAXV+1]; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">is the vertex in the tree yet? */</span>
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">distance</span>[MAXV+1]; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">cost of adding to tree */</span>
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">v</span>; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">current vertex to process */</span>
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">w</span>; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">candidate next vertex */</span>
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">weight</span>; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">edge weight */</span>
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">dist</span>; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">best current distance from start */</span>
  <span style="color: #00ffff;">for</span> (i=1; i&lt;=g-&gt;nvertices; i++) {
    intree[i] = FALSE;
    distance[i] = MAXINT;
    parent[i] = -1;
  }
  distance[start] = 0;
  v = start;
  <span style="color: #00ffff;">while</span> (intree[v] == FALSE) {
    intree[v] = TRUE;
    p = g-&gt;edges[v];
    <span style="color: #00ffff;">while</span> (p != <span style="color: #7fffd4;">NULL</span>) {
      w = p-&gt;y;
      weight = p-&gt;weight;
      <span style="color: #00ffff;">if</span> ((distance[w] &gt; weight) &amp;&amp; (intree[w] == FALSE)) {
        distance[w] = weight;
        parent[w] = v;
      }
      p = p-&gt;next;
    }
    v = 1;
    dist = MAXINT;
    <span style="color: #00ffff;">for</span> (i=1; i&lt;=g-&gt;nvertices; i++)
      <span style="color: #00ffff;">if</span> ((intree[i] == FALSE) &amp;&amp; (dist &gt; distance[i])) {
        dist = distance[i];
        v=i;
      }
  }
}
</pre>
</div>
</div>
</div>

<div id="outline-container-sec-1-1-2" class="outline-4">
<h4 id="sec-1-1-2">6.1.2 Kruskal’s Algorithm</h4>
<div class="outline-text-4" id="text-1-1-2">
<p>
The algorithm repeatedly considers the lightest remaining edge and
tests whether its two endpoints lie within the same connected
component. (最短边）
</p>

<p>
a clever data structure calledunion-find,can support such queries
in O(lgn) time. With this data structure, Kruskal’s algorithm runs in
O(mlgm) time.
</p>

<p>
<b>Implementation</b>
</p>
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #87cefa;">kruskal</span>(<span style="color: #98fb98;">graph</span> *<span style="color: #eedd82;">g</span>)
{
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span>; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">counter */</span>
  <span style="color: #98fb98;">set_union</span> <span style="color: #eedd82;">s</span>; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">set union data structure */</span>
  <span style="color: #98fb98;">edge_pair</span> <span style="color: #eedd82;">e</span>[MAXV+1]; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">array of edges data structure */</span>
  <span style="color: #98fb98;">bool</span> <span style="color: #eedd82;">weight_compare</span>();
  set_union_init(&amp;s, g-&gt;nvertices);
  to_edge_array(g, e); <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">sort edges by increasing cost */</span>
  qsort(&amp;e,g-&gt;nedges,<span style="color: #00ffff;">sizeof</span>(edge_pair),weight_compare);
  <span style="color: #00ffff;">for</span> (i=0; i&lt;(g-&gt;nedges); i++) {
    <span style="color: #00ffff;">if</span> (!same_component(s,e[i].x,e[i].y)) {
      printf(<span style="color: #ffa07a;">"edge (%d,%d) in MST\n"</span>,e[i].x,e[i].y);
      union_sets(&amp;s,e[i].x,e[i].y);
    }
  }
}
</pre>
</div>
</div>
</div>

<div id="outline-container-sec-1-1-3" class="outline-4">
<h4 id="sec-1-1-3">6.1.3 The Union-Find Data Structure</h4>
<div class="outline-text-4" id="text-1-1-3">
<ul class="org-ul">
<li>Find(i)– Find the root of tree containing elementi, by walking up
the parent pointers until there is nowhere to go. Return the label
of the root.
</li>

<li>Union(i,j)– Link the root of one of the trees (say
containingi)to the root of the tree containing the other
(say j) so <code>find(i)</code> now equals <code>find(j)</code>.
</li>
</ul>

<p>
We must double the number of nodes in the tree to get an
extra unit of height. How many doublings can we do before we use up allnnodes?
At most, lg2ndoublings can be performed. Thus, we can do both unions and finds
in O(logn), good enough for Kruskal’s algorithm. In fact, union-find
can be done even faster, as discussed in Section 12.5.
</p>

<p>
<b>Implementation</b>
</p>
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #00ffff;">typedef</span> <span style="color: #00ffff;">struct</span> {
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">p</span>[SET_SIZE+1]; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">parent element */</span>
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">size</span>[SET_SIZE+1]; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">number of elements in subtree i */</span>
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">n</span>; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">number of elements in set */</span>
} <span style="color: #98fb98;">set_union</span>;

<span style="color: #87cefa;">set_union_init</span>(<span style="color: #98fb98;">set_union</span> *<span style="color: #eedd82;">s</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">n</span>)
{
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span>; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">counter */</span>
  <span style="color: #00ffff;">for</span> (i=1; i&lt;=n; i++) {
    s-&gt;p[i] = i;
    s-&gt;size[i] = 1;
  }
  s-&gt;n = n;
}
<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">find</span>(<span style="color: #98fb98;">set_union</span> *<span style="color: #eedd82;">s</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">x</span>)
{
  <span style="color: #00ffff;">if</span> (s-&gt;p[x] == x)
    <span style="color: #00ffff;">return</span>(x);
  <span style="color: #00ffff;">else</span>
    <span style="color: #00ffff;">return</span>( find(s,s-&gt;p[x]) );
}
<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">union_sets</span>(<span style="color: #98fb98;">set_union</span> *<span style="color: #eedd82;">s</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">s1</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">s2</span>)
{
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">r1</span>, <span style="color: #eedd82;">r2</span>; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">roots of sets */</span>
  r1 = find(s,s1);
  r2 = find(s,s2);
  <span style="color: #00ffff;">if</span> (r1 == r2) <span style="color: #00ffff;">return</span>; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">already in same set */</span>
  <span style="color: #00ffff;">if</span> (s-&gt;size[r1] &gt;= s-&gt;size[r2]) {
    s-&gt;size[r1] = s-&gt;size[r1] + s-&gt;size[r2];
    s-&gt;p[ r2 ] = r1;
  }
  <span style="color: #00ffff;">else</span> {
    s-&gt;size[r2] = s-&gt;size[r1] + s-&gt;size[r2];
    s-&gt;p[ r1 ] = r2;
  }
}
<span style="color: #98fb98;">bool</span> <span style="color: #87cefa;">same_component</span>(<span style="color: #98fb98;">set_union</span> *<span style="color: #eedd82;">s</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">s1</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">s2</span>)
{
  <span style="color: #00ffff;">return</span> ( find(s,s1) == find(s,s2) );
}
</pre>
</div>
</div>
</div>

<div id="outline-container-sec-1-1-4" class="outline-4">
<h4 id="sec-1-1-4">More MST</h4>
<div class="outline-text-4" id="text-1-1-4">
<p>
<a href="http://www.seas.gwu.edu/~simhaweb/champalg/mst/mst.html">http://www.seas.gwu.edu/~simhaweb/champalg/mst/mst.html</a>
</p>
</div>
</div>
</div>

<div id="outline-container-sec-1-2" class="outline-3">
<h3 id="sec-1-2">6.3 Shortest Paths</h3>
<div class="outline-text-3" id="text-1-2">
</div><div id="outline-container-sec-1-2-1" class="outline-4">
<h4 id="sec-1-2-1">6.3.1 Dijkstra’s Algorithm</h4>
<div class="outline-text-4" id="text-1-2-1">
<p>
Given a particular start vertexs, it finds the shortest path from s to
every other vertex in the graph, including your desired destination t.
</p>

<p>
<b>Implementation</b>
</p>
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #87cefa;">dijkstra</span>(<span style="color: #98fb98;">graph</span> *<span style="color: #eedd82;">g</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">start</span>) <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">WAS prim(g,start) */</span>
{
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span>; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">counter */</span>
  <span style="color: #98fb98;">edgenode</span> *<span style="color: #eedd82;">p</span>; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">temporary pointer */</span>
  <span style="color: #98fb98;">bool</span> <span style="color: #eedd82;">intree</span>[MAXV+1]; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">is the vertex in the tree yet? */</span>
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">distance</span>[MAXV+1]; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">distance vertex is from start */</span>
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">v</span>; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">current vertex to process */</span>
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">w</span>; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">candidate next vertex */</span>
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">weight</span>; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">edge weight */</span>
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">dist</span>; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">best current distance from start */</span>
  <span style="color: #00ffff;">for</span> (i=1; i&lt;=g-&gt;nvertices; i++) {
    intree[i] = FALSE;
    distance[i] = MAXINT;
    parent[i] = -1;
  }
  distance[start] = 0;
  v = start;
  <span style="color: #00ffff;">while</span> (intree[v] == FALSE) {
    intree[v] = TRUE;
    p = g-&gt;edges[v];
    <span style="color: #00ffff;">while</span> (p != <span style="color: #7fffd4;">NULL</span>) {
      w = p-&gt;y;
      weight = p-&gt;weight;
      <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">CHANGED */</span> <span style="color: #00ffff;">if</span> (distance[w] &gt; (distance[v]+weight)) {
        <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">CHANGED */</span> distance[w] = distance[v]+weight;
        <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">CHANGED */</span> parent[w] = v;
      }
      p = p-&gt;next;
    }
    v=1;
    dist = MAXINT;
    <span style="color: #00ffff;">for</span> (i=1; i&lt;=g-&gt;nvertices; i++)
      <span style="color: #00ffff;">if</span> ((intree[i] == FALSE) &amp;&amp; (dist &gt; distance[i])) {
        dist = distance[i];
        v=i;
      }
  }
}
</pre>
</div>
<p>
As implemented here, the complexity is O(n<sup>2</sup>). 
</p>

<p>
Dijkstra works correctly only on graphs without negative-cost edges. The reason
is that midway through the execution we may encounter an edge with weight so
negative that it changes the cheapest way to get froms to some other vertex
already in the tree.
</p>
</div>
</div>

<div id="outline-container-sec-1-2-2" class="outline-4">
<h4 id="sec-1-2-2">6.3.2 All-Pairs Shortest Path</h4>
<div class="outline-text-4" id="text-1-2-2">
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #00ffff;">typedef</span> <span style="color: #00ffff;">struct</span> {
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">weight</span>[MAXV+1][MAXV+1]; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">adjacency/weight info */</span>
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">nvertices</span>; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">number of vertices in graph */</span>
} <span style="color: #98fb98;">adjacency_matrix</span>;
</pre>
</div>

<p>
The critical issue in an adjacency matrix implementation is how we denote the
edges absent from the graph. A common convention for unweighted graphs denotes
graph edges by 1 and non-edges by 0. This gives exactly the wrong interpretation
if the numbers denote edge weights, for the non-edges get interpreted
as a free ride between vertices. Instead, we should initialize each
non-edge to MAXINT. 
</p>

<div class="org-src-container">

<pre class="src src-c++"><span style="color: #87cefa;">floyd</span>(<span style="color: #98fb98;">adjacency_matrix</span> *<span style="color: #eedd82;">g</span>)
{
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span>,<span style="color: #eedd82;">j</span>; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">dimension counters */</span>
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">k</span>; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">intermediate vertex counter */</span>
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">through_k</span>; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">distance through vertex k */</span>
  <span style="color: #00ffff;">for</span> (k=1; k&lt;=g-&gt;nvertices; k++)
    <span style="color: #00ffff;">for</span> (i=1; i&lt;=g-&gt;nvertices; i++)
      <span style="color: #00ffff;">for</span> (j=1; j&lt;=g-&gt;nvertices; j++) {
        through_k = g-&gt;weight[i][k]+g-&gt;weight[k][j];
        <span style="color: #00ffff;">if</span> (through_k &lt; g-&gt;weight[i][j])
          g-&gt;weight[i][j] = through_k;
      }
}
</pre>
</div>

<p>
The Floyd-Warshall all-pairs shortest path runs in O(n<sup>3</sup>) time, which
is asymptotically no better thanncalls to Dijkstra’s algorithm.
However, the loops are so tight and the program so short that it runs
better in practice.
</p>
</div>
</div>
</div>

<div id="outline-container-sec-1-3" class="outline-3">
<h3 id="sec-1-3">6.4 War Story: Dialing for Documents</h3>
<div class="outline-text-3" id="text-1-3">
<p>
“We can get good word-use frequencies and grammatical information
from a big text database called the Brown Corpus. It contains
thousands of typical English sentences, each parsed according to parts
of speech. But how do we factor it all in?” Harald asked.
</p>

<p>
Each possible sentence interpretation can be thought of as a path in a
graph. The vertices of this graph are the complete set of possible
word choices. There will be an edge from each possible choice for the
ith word to each possible choice for the (i + 1)st word. The cheapest
path across this graph defines the best interpretation of the
sentence.
</p>

<p>
Perhaps we can count how often that pair of words occurred together in
previous texts. Or we can weigh them by the part of speech of each
word. Maybe nouns don’t like to be next to nouns as much as they like
being next to verbs.
</p>

<p>
We can pay a cost for walking through a particular vertex that depends
upon the frequency of the word. Our best sentence will be given by the
shortest path across the graph.
</p>

<p>
The constraints for many pattern recognition problems can be naturally
formulated as shortest path problems in graphs. In fact, there is a
particularly convenient dynamic programming solution for these
problems (the Viterbi algorithm). Despite the fancy name, the Viterbi
algorithm is basically solving a shortest path problem on a DAG.
</p>
</div>
</div>

<div id="outline-container-sec-1-4" class="outline-3">
<h3 id="sec-1-4">6.5 Network Flows and Bipartite Matching</h3>
<div class="outline-text-3" id="text-1-4">
<p>
The <i>network flow problem</i> asks for the maximum amount of flow which can
be sent from vertices s to t in a given weighted graph G while
respecting the maximum capacities of each pipe.
</p>
</div>
<div id="outline-container-sec-1-4-1" class="outline-4">
<h4 id="sec-1-4-1">6.5.1 Bipartite Matching</h4>
<div class="outline-text-4" id="text-1-4-1">
<p>
The largest bipartite matching can be readily found using network
flow. Create a source nodes that is connected to every vertex in L by
an edge of weight 1. Create a sink node t and connect it to every
vertex in R by an edge of weight 1. Finally, assign each edge in the
bipartite graph G a weight of 1. Now, the maximum possible flow
fromstotdefines the largest matching in G.
</p>
</div>
</div>

<div id="outline-container-sec-1-4-2" class="outline-4">
<h4 id="sec-1-4-2">6.5.2 Computing Network Flows</h4>
<div class="outline-text-4" id="text-1-4-2">
<p>
The key structure is the residual flow graph, denoted as R(G, f), where Gis
the input graph andfis the current flow through G. 
</p>

<p>
The maximum flow fromstotalways equals the weight of the minimums-t
cut. Thus, flow algorithms can be used to solve general edge and
vertex connectivity problems in graphs.
</p>

<p>
<b>Implementation</b>
</p>
<div class="org-src-container">

<pre class="src src-c++">        <span style="color: #00ffff;">typedef</span> <span style="color: #00ffff;">struct</span> {
          <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">v</span>; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">neighboring vertex */</span>
          <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">capacity</span>; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">capacity of edge */</span>
          <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">flow</span>; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">flow through edge */</span>
          <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">residual</span>; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">residual capacity of edge */</span>
          <span style="color: #00ffff;">struct</span> <span style="color: #98fb98;">edgenode</span> *<span style="color: #eedd82;">next</span>; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">next edge in list */</span>
        } <span style="color: #98fb98;">edgenode</span>;

      <span style="color: #87cefa;">netflow</span>(<span style="color: #98fb98;">flow_graph</span> *<span style="color: #eedd82;">g</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">source</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">sink</span>)
      {
        <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">volume</span>; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">weight of the augmenting path */</span>
        add_residual_edges(g);
        initialize_search(g);
        bfs(g,source);
        volume = path_volume(g, source, sink, parent);
        <span style="color: #00ffff;">while</span> (volume &gt; 0) {
          augment_path(g,source,sink,parent,volume);
          initialize_search(g);
          bfs(g,source);
          volume = path_volume(g, source, sink, parent);
        }
      }

    <span style="color: #98fb98;">bool</span> <span style="color: #87cefa;">valid_edge</span>(<span style="color: #98fb98;">edgenode</span> *<span style="color: #eedd82;">e</span>)
    {
      <span style="color: #00ffff;">if</span> (e-&gt;residual &gt; 0) <span style="color: #00ffff;">return</span> (TRUE);
      <span style="color: #00ffff;">else</span> <span style="color: #00ffff;">return</span>(FALSE);
    }

  <span style="color: #98fb98;">int</span> <span style="color: #87cefa;">path_volume</span>(<span style="color: #98fb98;">flow_graph</span> *<span style="color: #eedd82;">g</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">start</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">end</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">parents</span>[])
  {
    <span style="color: #98fb98;">edgenode</span> *<span style="color: #eedd82;">e</span>; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">edge in question */</span>
    <span style="color: #98fb98;">edgenode</span> *<span style="color: #eedd82;">find_edge</span>();
    <span style="color: #00ffff;">if</span> (parents[end] == -1) <span style="color: #00ffff;">return</span>(0);
    e = find_edge(g,parents[end],end);
    <span style="color: #00ffff;">if</span> (start == parents[end])
      <span style="color: #00ffff;">return</span>(e-&gt;residual);
    <span style="color: #00ffff;">else</span>
      <span style="color: #00ffff;">return</span>( min(path_volume(g,start,parents[end],parents),
                  e-&gt;residual) );
  }
  <span style="color: #98fb98;">edgenode</span> *<span style="color: #87cefa;">find_edge</span>(<span style="color: #98fb98;">flow_graph</span> *<span style="color: #eedd82;">g</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">x</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">y</span>)
  {
    <span style="color: #98fb98;">edgenode</span> *<span style="color: #eedd82;">p</span>; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">temporary pointer */</span>
    p = g-&gt;edges[x];
    <span style="color: #00ffff;">while</span> (p != <span style="color: #7fffd4;">NULL</span>) {
      <span style="color: #00ffff;">if</span> (p-&gt;v == y) <span style="color: #00ffff;">return</span>(p);
      p = p-&gt;next;
    }
    <span style="color: #00ffff;">return</span>(<span style="color: #7fffd4;">NULL</span>);
  }

<span style="color: #87cefa;">augment_path</span>(<span style="color: #98fb98;">flow_graph</span>*<span style="color: #eedd82;">g</span>,intstart,intend,<span style="color: #98fb98;">intparents</span>[],intvolume)
{
  <span style="color: #98fb98;">edgenode</span> *<span style="color: #eedd82;">e</span>; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">edge in question */</span>
  <span style="color: #98fb98;">edgenode</span> *<span style="color: #eedd82;">find_edge</span>();
  <span style="color: #00ffff;">if</span> (start == end) <span style="color: #00ffff;">return</span>;
  e = find_edge(g,parents[end],end);
  e-&gt;flow += volume;
  e-&gt;residual -= volume;
  e = find_edge(g,end,parents[end]);
  e-&gt;residual += volume;
  augment_path(g,start,parents[end],parents,volume);
}
</pre>
</div>

<p>
Edmonds and Karp [EK72] proved that always selecting ashortest
unweighted augmenting path guarantees that O(n<sup>3</sup>) augmentations
suffice for optimization.
</p>
</div>
</div>
</div>

<div id="outline-container-sec-1-5" class="outline-3">
<h3 id="sec-1-5">6.6 Design Graphs, Not Algorithms</h3>
<div class="outline-text-3" id="text-1-5">
<p>
The secret is learning to design graphs, not algorithms. We have
already seen a few instances of this idea:
</p>

<ul class="org-ul">
<li>The maximum spanning tree can be found by negating the edge weights
of the input graph G and using aminimumspanning tree algorithm on
the result. The most negative weight spanning tree will define the
maximum weight tree in G.
</li>
<li>To solve bipartite matching, we constructed a special network flow
graph such that the maximum flow corresponds to a maximum
cardinality matching.
</li>
</ul>
</div>

<div id="outline-container-sec-1-5-1" class="outline-4">
<h4 id="sec-1-5-1">Bucketing Rectangles</h4>
<div class="outline-text-4" id="text-1-5-1">
<p>
Problem: “In my graphics work I need to solve the following problem.
Given an arbitrary set of rectangles in the plane, how can I
distribute them into a minimum number of buckets such that no subset
of rectangles in any given bucket intersects another? In other words,
there can not be any overlapping area between two rectangles in the same bucket.”
</p>

<p>
Solution: We formulate a graph where each vertex is a rectangle, and
there is an edge if two rectangles intersect. Each bucket corresponds
to anindependent set of rectangles, so there is no overlap between any
two. Avertex coloringof a graph is a partition of the vertices into
independent sets, so minimizing the number of colors is exactly what
you want.
</p>
</div>
</div>

<div id="outline-container-sec-1-5-2" class="outline-4">
<h4 id="sec-1-5-2">Names in Collision</h4>
<div class="outline-text-4" id="text-1-5-2">
<p>
Problem:“In porting code from UNIX to DOS, I have to shorten several
hundred file names down to at most 8 characters each. I can’t just
use the first eight characters from each name, because “filename1”
and “filename2” would be assigned the exact same name. How can I
meaningfully shorten the names while ensuring that they do not
collide?”
</p>

<p>
Solution: Construct a bipartite graph with vertices corresponding to
each original file namefi for 1≤i≤n, as well as a collection of
acceptable shortenings for each name f<sub>i1</sub>,&#x2026;,f<sub>ik</sub>. Add an edge
between each original and shortened name. We now seek a set of n edges
that have no vertices in common, so each file name is mapped to a
distinct acceptable substitute. Bipartite matching, discussed in
Section 15.6 (page 498), is exactly this problem of finding an
independent set of edges in a graph.
</p>
</div>
</div>

<div id="outline-container-sec-1-5-3" class="outline-4">
<h4 id="sec-1-5-3">Separate the Text</h4>
<div class="outline-text-4" id="text-1-5-3">
<p>
Problem: “We need a way to separate the lines of text in the optical
characterrecognition system that we are building. Although there is
some white space between the lines, problems like noise and the tilt
of the page makes it hard to find. How can we do line segmentation?
</p>

<p>
Solution: Consider the following graph formulation. Treat each pixel
in the image as a vertex in the graph, with an edge between two
neighboring pixels. The weight of this edge should be proportional to
how dark the pixels are. A segmentation between two lines is a path in
this graph from the left to right side of the page. We seek a
relatively straight path that avoids as much blackness as possible.
This suggests that theshortest pathin the pixel graph will likely find
a good line segmentation.
</p>
</div>
</div>
</div>
</div>

<div id="outline-container-sec-2" class="outline-2">
<h2 id="sec-2">Exercises</h2>
<div class="outline-text-2" id="text-2">
</div><div id="outline-container-sec-2-1" class="outline-3">
<h3 id="sec-2-1">2-3</h3>
<div class="outline-text-3" id="text-2-1">
<p>
Is the path between two vertices in a minimum spanning tree necessarily a
shortest path between the two vertices in the full graph? Give a proof
or a counterexample.
</p>

<p>
Assume that all edges in the graph have distinct edge weights (i.e. ,
no pair of edges have the same weight). Is the path between a pair of
vertices in a minimum spanning tree necessarily a shortest path
between the two vertices in the full graph? Give a proof or a
counterexample.
</p>

<p>
不必要. 如下图,若 a 是 6 的话,minimum spanning tree 不会选择 a,但 A 和 C 间的最短路径会选择 a.
</p>

<img src="http://dreamrunner.org/images/blog/2014/AlgorithmDesignManual/6_4.jpg" />
</div>
</div>

<div id="outline-container-sec-2-2" class="outline-3">
<h3 id="sec-2-2">4</h3>
<div class="outline-text-3" id="text-2-2">
<p>
Can Prim’s and Kruskal’s algorithm yield different minimum spanning
trees? Explain why or why not.
</p>

<p>
能.当有相同 weight 的边.
</p>

<p>
当所有边的 weight 不同时,图存在唯一的 minimum spanning trees,两者生成同样的树.
</p>
</div>
</div>

<div id="outline-container-sec-2-3" class="outline-3">
<h3 id="sec-2-3">5</h3>
<div class="outline-text-3" id="text-2-3">
<p>
Does either Prim&#8217;s and Kruskal&#8217;s algorithm work if there are negative
edge weights? Explain why or why not. 
</p>

<p>
可以.Prim 每次选相邻最近的不在树内的点,有负 weight 的边并不影响它. 而
Kruskal 每次选最短的边,同样不受影响.
</p>
</div>
</div>

<div id="outline-container-sec-2-4" class="outline-3">
<h3 id="sec-2-4">6</h3>
<div class="outline-text-3" id="text-2-4">
<p>
Suppose we are given the minimum spanning tree T of a given graph G
(with n vertices and m edges) and a new edge e = (u,v) of weight w
that we will add to G. Give an efficient algorithm to find the
minimum spanning tree of the graph G + e. Your algorithm should run
in O(n) time to receive full credit.
</p>

<p>
新添加的 e 在顶点 u 和 v 中间,原本的 MST 中 u 和 v 通过 u-&gt;a1-&gt;ai-&gt;v,把此路径的边与
e 比较,用 Prim 算法选最临近点.
</p>
</div>
</div>

<div id="outline-container-sec-2-5" class="outline-3">
<h3 id="sec-2-5">7</h3>
<div class="outline-text-3" id="text-2-5">
<p>
(a) Let T be a minimum spanning tree of a weighted graph G. Construct
a new graph G′ by adding a weight of k to every edge of G. Do the
edges of T form a minimum spanning tree of G′? Prove the statement or
give a counterexample.
</p>

<p>
(b) Let P = {s, &#8230; , t} describe a shortest weighted path between
vertices s and t of a weighted graph G. Construct a new graph G′ by
adding a weight of k to every edge of G. Does P describe a shortest
path from s to t in G′? Prove the statement or give a counterexample.
</p>

<p>
(a)和(b)都对,并没有改变边之间的比较关系.
</p>
</div>
</div>

<div id="outline-container-sec-2-6" class="outline-3">
<h3 id="sec-2-6">8</h3>
<div class="outline-text-3" id="text-2-6">
<p>
Devise and analyze an algorithm that takes a weighted graph G and
finds the smallest change in the cost to a non-MST edge that would
cause a change in the minimum spanning tree of G. Your algorithm must
be correct and run in polynomial time. 
</p>

<ol class="org-ol">
<li>遍历图的边,掠过 MST 中的边,当遇到 non-MST 的边 E(i,j).
</li>
<li>利用 MST 中的 parent 遍历出顶点 i 到 j 的所有 MST 边,并得到其中最大 weight 的边
mst<sub>e</sub><sub>max</sub>.
</li>
<li>计算 E(i,j)与 mst<sub>e</sub><sub>max 的差值</sub>.
</li>
<li>遍历所有的 non-MST 的边,得到最小差值就是改变的最小值.
</li>
</ol>

<p>
总共边数 m,算法复杂度 O(m<sup>2</sup>).
</p>
</div>
</div>

<div id="outline-container-sec-2-7" class="outline-3">
<h3 id="sec-2-7">9</h3>
<div class="outline-text-3" id="text-2-7">
<p>
Consider the problem of finding a minimum weight connected subset T of
edges from a weighted connected graph G. The weight of T is the sum of
all the edge weights in T.
</p>

<ol class="org-ol">
<li>Why is this problem not just the minimum spanning tree problem?
Hint: think negative weight edges.
</li>
<li>Give an efficient algorithm to compute the minimum weight connected
subset T. 
</li>
</ol>

<p>
MST 不能有环路,minimum weight connected subset T 可以有环路,所以如果一条负数 weight 的边,不在 MST 中,但却包含在 T 中,因为它能使 T 的总权值减小.
</p>

<ol class="org-ol">
<li>把所有负数 weight 的边加入 T 中,若剩下 1 个连通图,结束.
</li>
<li>若剩下 C(&gt;1)个连通图,对 C 个连通图使用 Kruskal,直到剩下一个连通图 T.
</li>
</ol>

<div class="org-src-container">

<pre class="src src-sh"><span style="color: #87cefa;">sort</span>(edges);
c := n;
<span style="color: #00ffff;">for</span> edge<span style="color: #00ffff;"> in</span> edges:
    <span style="color: #00ffff;">if</span> edge.weight &lt; 0:
        <span style="color: #00ffff;">if</span> find(edge.firstEnd) != find(edge.secondEnd):
            --c;
        unite(edge.firstEnd, edge.secondEnd);
    <span style="color: #00ffff;">else</span>:
        <span style="color: #00ffff;">if</span> <span style="color: #eedd82;">c</span> == 1: break;
        <span style="color: #00ffff;">if</span> find(edge.firstEnd) != find(edge.secondEnd):
            unite(edge.firstEnd, edge.secondEnd);
            --c;
</pre>
</div>
</div>
</div>

<div id="outline-container-sec-2-8" class="outline-3">
<h3 id="sec-2-8">10</h3>
<div class="outline-text-3" id="text-2-8">
<p>
Let G=(V,E) be an undirected graph. A set F⊆E of edges is called a
feedback-edge set if every cycle of G has at least one edge in F.
</p>

<ol class="org-ol">
<li>Suppose that Gis unweighted. Design an efficient algorithm to find
a minimum-size feedback-edge set.
</li>

<li>Suppose that Gis a weighted undirected graph with positive edge
weights. Design an efficient algorithm to find a minimum-weight
feedback-edge set.
</li>

<li><b>Minimum size feedback edge set:</b> 使用 DFS,从任意点开始,遇到回归边,
把它加入结果 set 中,当 DFS 完成,结果 set 就是答案.
</li>
<li><b>minimum-weight feedback-edge set:</b> 对所有 weight 值取反,用 Kruskal 算法,当遇到边 E 的顶点在同一个集合中,把 E 加入到结果 set 中,当 Kruskal 遍历完所有边后,结果 set 就是答案.
</li>
</ol>
</div>
</div>

<div id="outline-container-sec-2-9" class="outline-3">
<h3 id="sec-2-9">11</h3>
<div class="outline-text-3" id="text-2-9">
<p>
Modify Prim&#8217;s algorithm so that it runs in time O(nlogk) on a
graph that has only k different edges costs. 
</p>

<ul class="org-ul">
<li>k 个不同的边值,使用一个 k 个元素的 min-heap,heap 的节点是相同距离的顶点链表.
</li>
<li>Prim 每次选择和更新顶点的距离在 min-heap 完成,做到 O(nlogk).
</li>
</ul>
</div>
</div>
<div id="outline-container-sec-2-10" class="outline-3">
<h3 id="sec-2-10">12</h3>
<div class="outline-text-3" id="text-2-10">
<p>
Devise an efficient data structure to handle the following operations
on a weighted directed graph:
</p>

<ol class="org-ol">
<li>Merge two given components.
</li>
<li>Locate which component contains a given vertex v.
</li>
<li>Retrieve a minimum edge from a given component. 
</li>
</ol>

<p>
使用 Union-Find 并添加 minimum edge.
</p>
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #00ffff;">typedef</span> <span style="color: #00ffff;">struct</span> {
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">p</span>[SET_SIZE+1]; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">parent element */</span>
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">size</span>[SET_SIZE+1]; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">number of elements in subtree i */</span>
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">minedge</span>[SET_SIZE+1];
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">n</span>; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">number of elements in set */</span>
} <span style="color: #98fb98;">set_union</span>;
</pre>
</div>
</div>
</div>

<div id="outline-container-sec-2-11" class="outline-3">
<h3 id="sec-2-11">14</h3>
<div class="outline-text-3" id="text-2-11">
<p>
The single-destination shortest path problem for a directed graph
seeks the shortest path from every vertex to a specified vertex v. Give
an efficient algorithm to solve the single-destination shortest paths
problem.
</p>

<p>
用 Floyd-Warshall 对于顶点 v 反向更新距离值.得到最终 shortest paths.
</p>
</div>
</div>

<div id="outline-container-sec-2-12" class="outline-3">
<h3 id="sec-2-12">19</h3>
<div class="outline-text-3" id="text-2-12">
<p>
Let G be a weighted directed graph with n vertices and m edges, where
all edges have positive weight. A directed cycle is a directed path
that starts and ends at the same vertex and contains at least one
edge. Give an O(n<sup>3</sup>) algorithm to find a directed cycle in G of minimum
total weight. Partial credit will be given for an O(n<sup>2</sup>m) algorithm. 
</p>

<div class="org-src-container">

<pre class="src src-c++">run Floyd Warshall on the <span style="color: #98fb98;">graph</span>
<span style="color: #eedd82;">min</span> &lt;- MAX_INT
vertex &lt;- None
<span style="color: #00ffff;">for</span> each pair of vertices u,<span style="color: #87cefa;">v</span>
    <span style="color: #00ffff;">if</span> (dist(u,v) + dist(v,u) &lt; min):
           min &lt;- dist(u,v) + dist(v,u)
           pair &lt;- (u,v)
<span style="color: #00ffff;">return</span> path(u,v) + path(v,u)
</pre>
</div>
</div>
</div>

<div id="outline-container-sec-2-13" class="outline-3">
<h3 id="sec-2-13">20</h3>
<div class="outline-text-3" id="text-2-13">
<p>
Can we modify Dijkstra’s algorithm to solve the single-source longest
path problem by changing minimum to maximum? If so, then prove your
algorithm correct. If not, then provide a counterexample.
</p>

<p>
没有负 weight 的边,可以.
</p>
</div>
</div>

<div id="outline-container-sec-2-14" class="outline-3">
<h3 id="sec-2-14">21</h3>
<div class="outline-text-3" id="text-2-14">
<p>
LetG=(V,E) be a weighted acyclic directed graph with possibly negative
edge weights. Design a linear-time algorithm to solve the
single-source shortest-path problem from a given source v.
</p>

<div class="org-src-container">

<pre class="src src-sh"><span style="color: #00ffff;">for</span> each vertex y<span style="color: #00ffff;"> in</span> a topological ordering of G
    choose edge (x,y) minimizing d(s,x)+length(x,y)
    path(s,y) = path(s,x) + edge (x,y)
    d(s,y) = d(s,x) + length(x,y)
</pre>
</div>
</div>
</div>

<div id="outline-container-sec-2-15" class="outline-3">
<h3 id="sec-2-15">22</h3>
<div class="outline-text-3" id="text-2-15">
<p>
Let G=(V,E) be a directed weighted graph such that all the weights are
positive. Let v and w be two vertices in G and k≤|V| be an integer. Design
an algorithm to find the shortest path from v to w that contains
exactly k edges. Note that the path need not be simple.
</p>

<div class="org-src-container">

<pre class="src src-sh">create the table D[V,k];
<span style="color: #eedd82;">D</span>[v,1] = 0;
<span style="color: #00ffff;">for</span> i<span style="color: #00ffff;"> in</span> other vertex except v:
         <span style="color: #eedd82;">D</span>[i,1] = MAX_INT;
<span style="color: #00ffff;">for</span> <span style="color: #eedd82;">m</span>=2 to k:
    <span style="color: #00ffff;">for</span> every edge(i,j):
        <span style="color: #eedd82;">D</span>[j,m] = D[i,m-1] + D[i,j]
        <span style="color: #eedd82;">P</span>[i,m] = i
<span style="color: #eedd82;">Path</span> = emtpy list
<span style="color: #eedd82;">i</span> = w
<span style="color: #00ffff;">for</span> <span style="color: #eedd82;">m</span>=k down to 1:
    Path.append(m);
    <span style="color: #eedd82;">i</span> = P[m,k]
 Path.append(V);
 Path.reverse();
</pre>
</div>
</div>
</div>

<div id="outline-container-sec-2-16" class="outline-3">
<h3 id="sec-2-16">23</h3>
<div class="outline-text-3" id="text-2-16">
<p>
Arbitrage is the use of discrepancies in currency-exchange rates to
make a profit. For example, there may be a small window of time during
which 1 U.S. dollar buys 0.75 British pounds, 1 British pound buys 2
Australian dollars, and 1 Australian dollar buys 0.70 U.S. dollars. At
such a time, a smart trader can trade one U.S. dollar and end up with
0.75 × 2 × 0.7 = 1.05 U.S. dollars—a profit of 5%. Suppose that
there are n currencies c1 , …, cn and an n × n table R of exchange
rates, such that one unit of currency ci buys R[i,j] units of currency
cj. Devise and analyze an algorithm to determine the maximum value of
R[c1, ci1] · R[ci1, ci2] · · · R[cik−1, cik] · R[cik, c1]
</p>

<p>
log(a*b*c) = loga + lgob + log.所以求最长路径.
</p>

<ol class="org-ol">
<li>用 Floyd-Warshall 算法算出 i,j 的最长路径;
</li>
<li>计算所有 C<sub>(1i)</sub>*C<sub>(i1)</sub>的值,得出最大值.
</li>
</ol>
</div>
</div>
</div>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Algorithm Design Manual Chapter 5]]></title>
    <link href="http://dreamrunner.org/blog/2014/06/12/The-Algorithm-Design-Manual5/"/>
    <updated>2014-06-12T00:00:00+08:00</updated>
    <id>http://dreamrunner.org/blog/2014/06/12/The-Algorithm-Design-Manual5</id>
    <content type="html"><![CDATA[<div id="outline-container-sec-1" class="outline-2">
<h2 id="sec-1">Book Notes</h2>
<div class="outline-text-2" id="text-1">
</div><div id="outline-container-sec-1-1" class="outline-3">
<h3 id="sec-1-1">5.1 Flavors of Graphs</h3>
<div class="outline-text-3" id="text-1-1">
<ul class="org-ul">
<li>Undirected vs. Directed
</li>
<li>Weighted vs. Unweighted
</li>
<li>Simple vs. Non-simple
</li>
<li>Sparse vs. Dense
</li>
<li>Cyclic vs. Acyclic
</li>
<li>Embedded vs. Topological
</li>
<li>Implicit vs. Explicit
</li>
<li>Labeled vs. Unlabeled
</li>
</ul>

<!-- more -->
</div>
</div>
<div id="outline-container-sec-1-2" class="outline-3">
<h3 id="sec-1-2">5.2 Data Structures for Graphs</h3>
<div class="outline-text-3" id="text-1-2">
<ul class="org-ul">
<li>Adjacency Matrix: We can represent G using an n×n matrix M, where
element M[i, j] = 1 if(i, j) is an edge of G, and 0 if it isn’t.
</li>
<li>Adjacency Lists: We can more efficiently represent sparse graphs by
using linked lists to store the neighbors adjacent to each vertex.
</li>
</ul>

<p>
Adjacency lists are the right data structure for most applications of
graphs.
</p>

<p>
<b>Adjacency Lists</b>
</p>

<div class="org-src-container">

<pre class="src src-c++"><span style="color: #b0c4de;">#define</span> <span style="color: #eedd82;">MAXV</span> 1000  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">maximum number of vertices</span>

<span style="color: #00ffff;">typedef</span> <span style="color: #00ffff;">struct</span> {
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">y</span>;  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">adjacency info</span>
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">weight</span>;  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">edge weight, if any</span>
  <span style="color: #00ffff;">struct</span> <span style="color: #98fb98;">edgenode</span> *<span style="color: #eedd82;">next</span>;  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">next edge in list</span>
} <span style="color: #98fb98;">edgenode</span>;

<span style="color: #00ffff;">typedef</span> <span style="color: #00ffff;">struct</span> {
  <span style="color: #98fb98;">edgenode</span> *<span style="color: #eedd82;">edges</span>[MAXV + 1];   <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">adjacency info</span>
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">degree</span>[MAXV + 1];  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">outdegree of each vertex</span>
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">nvertices</span>;  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">number of vertices in graph</span>
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">nedges</span>;  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">number of edges in graph</span>
  <span style="color: #98fb98;">bool</span> <span style="color: #eedd82;">directed</span>;  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">is the graph directed</span>
} <span style="color: #98fb98;">graph</span>;

<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">initialize_graph</span>(<span style="color: #98fb98;">graph</span> *<span style="color: #eedd82;">g</span>, <span style="color: #98fb98;">bool</span> <span style="color: #eedd82;">directed</span>) {
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span>;
  g-&gt;nvertices = 0;
  g-&gt;nedges = 0;
  g-&gt;directed = directed;
  <span style="color: #00ffff;">for</span> (i = 1; i &lt;= NMAX; ++i) {
    g-&gt;degree[i] = 0;
    g-&gt;edges[i] = <span style="color: #7fffd4;">NULL</span>;
  }
}

<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">insert_edge</span>(<span style="color: #98fb98;">graph</span> *<span style="color: #eedd82;">g</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">x</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">y</span>, <span style="color: #98fb98;">bool</span> <span style="color: #eedd82;">directed</span>) {
  <span style="color: #98fb98;">edgenode</span> *<span style="color: #eedd82;">p</span>;
  p = <span style="color: #00ffff;">new</span> <span style="color: #98fb98;">edgenode</span>;
  p-&gt; weight = 0;
  p-&gt;y = y;
  p-&gt;next = g-&gt;edges[x];
  g-&gt;edges[x] = p;
  g-&gt;degree[x]++;
  <span style="color: #00ffff;">if</span> (directed == <span style="color: #7fffd4;">false</span>) {
    insert_edge(g, y, x, <span style="color: #7fffd4;">true</span>);
  } <span style="color: #00ffff;">else</span> {
    g-&gt;nedges++;
  }
}

<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">read_graph</span>(<span style="color: #98fb98;">graph</span> *<span style="color: #eedd82;">g</span>, <span style="color: #98fb98;">bool</span> <span style="color: #eedd82;">directed</span>) {
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span>;
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">m</span>;
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">x</span>, <span style="color: #eedd82;">y</span>;
  initialize_graph(g, directed);
  scanf(<span style="color: #ffa07a;">"%d %d"</span>, &amp;(g-&gt;nvertices), &amp;m);
  <span style="color: #00ffff;">for</span> (i = 1; i &lt;= m; ++i) {
    scanf(<span style="color: #ffa07a;">"$d %d"</span>, &amp;x, &amp;y);
    insert_edge(g, x, y, directed);
  }
}

<span style="color: #87cefa;">print_graph</span>(<span style="color: #98fb98;">graph</span> *<span style="color: #eedd82;">g</span>) {
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span>;
  <span style="color: #98fb98;">edgenode</span> *<span style="color: #eedd82;">p</span>;
  <span style="color: #00ffff;">for</span> (i = 1; i &lt;= g-&gt;nvertices; ++i) {
    printf(<span style="color: #ffa07a;">"%d: "</span>, i);
    p = g-&gt;edges[i];
    <span style="color: #00ffff;">while</span> (p != <span style="color: #7fffd4;">NULL</span>) {
      printf(<span style="color: #ffa07a;">"%d "</span>, p-&gt;y);
      p = p-&gt;next;
    }
    printf(<span style="color: #ffa07a;">"\n"</span>);
  }
}
</pre>
</div>
</div>
</div>
<div id="outline-container-sec-1-3" class="outline-3">
<h3 id="sec-1-3">5.5 Traversing a Graph</h3>
<div class="outline-text-3" id="text-1-3">
<p>
The key idea behind graph traversal is to mark each vertex when we
first visit it and keep track of what we have not yet completely
explored. Although bread crumbs or unraveled threads have been used to
mark visited places in fairy-tale mazes, we will rely on Boolean flags
or enumerated types.
</p>

<p>
Each vertex will exist in one of three states:
</p>
<ul class="org-ul">
<li>undiscovered– the vertex is in its initial, virgin state.
</li>
<li>discovered– the vertex has been found, but we have not yet checked
out all its incident edges.
</li>
<li>processed– the vertex after we have visited all its incident edges.
</li>
</ul>
</div>
</div>
<div id="outline-container-sec-1-4" class="outline-3">
<h3 id="sec-1-4">5.6 Breadth-First Search</h3>
<div class="outline-text-3" id="text-1-4">
<p>
先遍历完一个点的所有相邻点。
</p>

<div class="org-src-container">

<pre class="src src-c++">    <span style="color: #98fb98;">bool</span> <span style="color: #eedd82;">processed</span>[MAXV+1]; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">which vertices have been processed */</span>
    <span style="color: #98fb98;">bool</span> <span style="color: #eedd82;">discovered</span>[MAXV+1]; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">which vertices have been found */</span>
    <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">parent</span>[MAXV+1]; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">discovery relation */</span>

    <span style="color: #87cefa;">initialize_search</span>(<span style="color: #98fb98;">graph</span> *<span style="color: #eedd82;">g</span>)
    {
      <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span>; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">counter */</span>
      <span style="color: #00ffff;">for</span> (i=1; i&lt;=g-&gt;nvertices; i++) {
        processed[i] = discovered[i] = FALSE;
        parent[i] = -1;
      }
    }

  <span style="color: #87cefa;">bfs</span>(<span style="color: #98fb98;">graph</span> *<span style="color: #eedd82;">g</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">start</span>)
  {
    <span style="color: #98fb98;">queue</span> <span style="color: #eedd82;">q</span>; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">queue of vertices to visit */</span>
    <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">v</span>; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">current vertex */</span>
    <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">y</span>; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">successor vertex */</span>
    <span style="color: #98fb98;">edgenode</span> *<span style="color: #eedd82;">p</span>; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">temporary pointer */</span>
    init_queue(&amp;q);
    enqueue(&amp;q,start);
    discovered[start] = TRUE;
    <span style="color: #00ffff;">while</span> (empty_queue(&amp;q) == FALSE) {
      v = dequeue(&amp;q);
      process_vertex_early(v);
      processed[v] = TRUE;
      p = g-&gt;edges[v];
      <span style="color: #00ffff;">while</span> (p != <span style="color: #7fffd4;">NULL</span>) {
        y = p-&gt;y;
        <span style="color: #00ffff;">if</span> ((processed[y] == FALSE) || g-&gt;directed)
          process_edge(v,y);
        <span style="color: #00ffff;">if</span> (discovered[y] == FALSE) {
          enqueue(&amp;q,y);
          discovered[y] = TRUE;
          parent[y] = v;
        }
        p = p-&gt;next;
      }
      process_vertex_late(v);
    }
  }

<span style="color: #87cefa;">find_path</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">start</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">end</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">parents</span>[])
{
  <span style="color: #00ffff;">if</span> ((start == end) || (end == -1))
    printf(<span style="color: #ffa07a;">"\n%d"</span>,start);
  <span style="color: #00ffff;">else</span> {
    find_path(start,parents[end],parents);
    printf(<span style="color: #ffa07a;">" %d"</span>,end);
  }
}
</pre>
</div>

<p>
Because vertices are discovered in order of increasing distance from the root,
this tree has a very important property. The unique tree path from the root to
each node x∈V uses the smallest number of edges (or equivalently, intermediate
nodes) possible on any root-to-xpath in the graph.
</p>

<p>
There are <b>two points</b> to remember when using breadth-first search to find a
shortest path fromxtoy: First, the shortest path tree is only useful if BFS was
performed with x as the root of the search. Second, BFS gives the shortest path
only if the graph is unweighted.
</p>
</div>
</div>
<div id="outline-container-sec-1-5" class="outline-3">
<h3 id="sec-1-5">5.7 Applications of Breadth-First Search</h3>
<div class="outline-text-3" id="text-1-5">
<p>
Properly implemented using adjacency lists, any such algorithm is
destined to be linear, since BFS runs in O(n+m) time on both directed
and undirected graphs. This is optimal, since it is as fast as one can
hope to read any n-vertex, m-edge graph.
</p>
</div>
</div>

<div id="outline-container-sec-1-6" class="outline-3">
<h3 id="sec-1-6">5.8 Depth-First Search</h3>
<div class="outline-text-3" id="text-1-6">
<p>
The difference between BFS and DFS results is in the order in which they
explore vertices. This order depends completely upon the container
data structure used to store the discovered but not processed
vertices.
</p>

<ul class="org-ul">
<li>Queue– By storing the vertices in a first-in, first-out (FIFO)
queue, we explore the oldest unexplored vertices first. Thus our
explorations radiate out slowly from the starting vertex, defining a
breadth-first search.
</li>

<li>Stack– By storing the vertices in a last-in, first-out (LIFO) stack,
we explore the vertices by lurching along a path, visiting a new
neighbor if one is available, and backing up only when we are
surrounded by previously discovered vertices. Thus, our explorations
quickly wanderaway from our starting point, defining a depth-first
search.
</li>
</ul>

<p>
DFS organizes vertices by entry/exit times, and edges into tree and
back edges. This organization is what gives DFS its real power.
</p>

<p>
<b>Implementation</b>
</p>

<p>
The beauty of implementingdfsrecursively is that recursion eliminates
the need to keep an explicit stack:
</p>

<div class="org-src-container">

<pre class="src src-c++"><span style="color: #87cefa;">dfs</span>(<span style="color: #98fb98;">graph</span> *<span style="color: #eedd82;">g</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">v</span>)
{
  <span style="color: #98fb98;">edgenode</span> *<span style="color: #eedd82;">p</span>; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">temporary pointer */</span>
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">y</span>; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">successor vertex */</span>
  <span style="color: #00ffff;">if</span> (finished) <span style="color: #00ffff;">return</span>; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">allow for search termination */</span>
  discovered[v] = TRUE;
  time = time + 1;
  entry_time[v] = time;
  process_vertex_early(v);
  p = g-&gt;edges[v];
  <span style="color: #00ffff;">while</span> (p != <span style="color: #7fffd4;">NULL</span>) {
    y = p-&gt;y;
    <span style="color: #00ffff;">if</span> (discovered[y] == FALSE) {
      parent[y] = v;
      process_edge(v,y);
      dfs(g,y);
    }
    <span style="color: #00ffff;">else</span> <span style="color: #00ffff;">if</span> ((!processed[y]) || (g-&gt;directed))
      process_edge(v,y);
    <span style="color: #00ffff;">if</span> (finished) <span style="color: #00ffff;">return</span>;
    p = p-&gt;next;
  }
  process_vertex_late(v);
  time = time + 1;
  exit_time[v] = time;
  processed[v] = TRUE;
}
</pre>
</div>
</div>
</div>
<div id="outline-container-sec-1-7" class="outline-3">
<h3 id="sec-1-7">5.9 Applications of Depth-First Search</h3>
<div class="outline-text-3" id="text-1-7">
</div><div id="outline-container-sec-1-7-1" class="outline-4">
<h4 id="sec-1-7-1">Finding Cycles</h4>
<div class="outline-text-4" id="text-1-7-1">
<p>
But any back edge going from x to an ancestorycreates a cycle with the
tree path fromytox. Such a cycle is easy to find using dfs:
</p>

<div class="org-src-container">

<pre class="src src-c++"><span style="color: #87cefa;">process_edge</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">x</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">y</span>)
{
  <span style="color: #00ffff;">if</span> (parent[x] != y) { <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">found back edge! */</span>
    printf(<span style="color: #ffa07a;">"Cycle from %d to %d:"</span>,y,x);
    find_path(y,x,parent);
    printf(<span style="color: #ffa07a;">"\n\n"</span>);
    finished = TRUE;
  }
}
</pre>
</div>
</div>
</div>

<div id="outline-container-sec-1-7-2" class="outline-4">
<h4 id="sec-1-7-2">Articulation Vertices</h4>
<div class="outline-text-4" id="text-1-7-2">
<p>
Observe that there is a single point of failure—a single vertex whose
deletion disconnects a connected component of the graph. Such a vertex
is called an articulation vertex or cut-node.
</p>

<p>
More robust graphs without such a vertex are said to be biconnected.
</p>

<p>
Temporarily delete each vertex v, and then do a BFS or DFS traversal
of the remaining graph to establish whether it is still connected. The
total time fornsuch traversals is O(n(m+n)). There is a clever
linear-time algorithm, however, that tests all the vertices of a
connected graph using a single depth-first search.
</p>

<p>
Let <code>reachable_ancestor[v]</code> denote the earliest reachable ancestor of
vertex v, meaning the oldest ancestor ofvthat we can reach by a
combination of tree edges and back edges. Initially,
<code>reachable_ancestor[v] = v</code>:
</p>

<div class="org-src-container">

<pre class="src src-c++"><span style="color: #98fb98;">int</span> <span style="color: #eedd82;">reachable_ancestor</span>[MAXV+1]; <span style="color: #ff7f24;">/*</span><span style="color: #ff7f24;">earliestreachableancestorofv*/</span>
<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">tree_out_degree</span>[MAXV+1];  <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">DFStree outdegree ofv*/</span>
<span style="color: #87cefa;">process_vertex_early</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">v</span>)
{
  reachable_ancestor[v] = v;
}
</pre>
</div>

<p>
We update <code>reachable_ancestor[v]</code> whenever we encounter a back edge
that takes us to an earlier ancestor than we have previously seen. The
relative age/rank of our ancestors can be determined from
their <code>entry_time’s</code>:
</p>

<div class="org-src-container">

<pre class="src src-c++"><span style="color: #87cefa;">process_edge</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">x</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">y</span>)
{
  <span style="color: #98fb98;">int</span> <span style="color: #00ffff;">class</span>; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">edge class */</span>
  <span style="color: #00ffff;">class</span> = edge_classification(x,y);
  <span style="color: #00ffff;">if</span> (<span style="color: #00ffff;">class</span> == TREE)
    tree_out_degree[x] = tree_out_degree[x] + 1;
  <span style="color: #00ffff;">if</span> ((<span style="color: #00ffff;">class</span> == BACK) &amp;&amp; (parent[x] != y)) {
    <span style="color: #00ffff;">if</span> (entry_time[y] &lt; entry_time[ reachable_ancestor[x] ] )
      reachable_ancestor[x] = y;
  }
}
</pre>
</div>

<p>
The key issue is determining how the reachability relation impacts
whether vertexv is an articulation vertex. There are three cases:
</p>
<ul class="org-ul">
<li>Root cut-nodes– If the root of the DFS tree has two or more
children, it must be an articulation vertex. No edges from the
subtree of the second child can possibly connect to the subtree of
the first child.
</li>

<li>Bridge cut-nodes– If the earliest reachable vertex fromvis v, then
deleting the single edge (parent[v],v) disconnects the graph.
Clearlyparent[v] must be an articulation vertex, since it cuts v from
the graph. Vertex vis also an articulation vertex unless it is a
leaf of the DFS tree. For any leaf, nothing falls off when you cut it.
</li>
<li>Parent cut-nodes– If the earliest reachable vertex fromvis the
parent of v, then deleting the parent must severvfrom the tree
unless the parent is the root.
</li>
</ul>

<img src="http://dreamrunner.org/images/blog/2014/AlgorithmDesignManual/articulation_vertices.jpg" />

<p>
The routine below systematically evaluates each of the three
conditions as we back up from the vertex after traversing all outgoing
edges. We use <code>entry_time[v]</code> to represent the age of vertex v. The
reachability time <code>time_v</code> calculated below denotes the oldest vertex that
can be reached using back edges.
</p>

<div class="org-src-container">

<pre class="src src-c++"><span style="color: #87cefa;">process_vertex_late</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">v</span>)
{
  <span style="color: #98fb98;">bool</span> <span style="color: #eedd82;">root</span>; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">is the vertex the root of the DFS tree? */</span>
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">time_v</span>; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">earliest reachable time for v */</span>
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">time_parent</span>; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">earliest reachable time for parent[v] */</span>
  <span style="color: #00ffff;">if</span> (parent[v] &lt; 1) { <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">test if v is the root */</span>
    <span style="color: #00ffff;">if</span> (tree_out_degree[v] &gt; 1)
      printf(<span style="color: #ffa07a;">"root articulation vertex: %d \n"</span>,v);
    <span style="color: #00ffff;">return</span>;
  }
  root = (parent[parent[v]] &lt; 1); <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">is parent[v] the root? */</span>
  <span style="color: #00ffff;">if</span> ((reachable_ancestor[v] == parent[v]) &amp;&amp; (!root))
    printf(<span style="color: #ffa07a;">"parent articulation vertex: %d \n"</span>,parent[v]);
  <span style="color: #00ffff;">if</span> (reachable_ancestor[v] == v) {
    printf(<span style="color: #ffa07a;">"bridge articulation vertex: %d \n"</span>,parent[v]);
    <span style="color: #00ffff;">if</span> (tree_out_degree[v] &gt; 0) <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">test if v is not a leaf */</span>
      printf(<span style="color: #ffa07a;">"bridge articulation vertex: %d \n"</span>,v);
  }
  time_v = entry_time[reachable_ancestor[v]];
  time_parent = entry_time[ reachable_ancestor[parent[v]] ];
  <span style="color: #00ffff;">if</span> (time_v &lt; time_parent)
    reachable_ancestor[parent[v]] = reachable_ancestor[v];
}
</pre>
</div>

<p>
We can alternately talk about reliability in terms of edge failures
instead of vertex failures. 
</p>

<p>
In fact
all bridges can be identified in the same O(n+m) time. Edge (x, y) is a
bridge if (1) it is a tree edge, and (2) no back edge connects from
yor below toxor above. This can be computed with a minor modification
of the <code>reachable_ancestor</code> function.
</p>
</div>
</div>
</div>
<div id="outline-container-sec-1-8" class="outline-3">
<h3 id="sec-1-8">5.10 Depth-First Search on Directed Graphs</h3>
<div class="outline-text-3" id="text-1-8">
<p>
For directed graphs, depth-first search labelings can take on a wider
range of possibilities. Indeed, all four of the edge cases in Figure
below can occur in traversing directed graphs.
</p>

<img src="http://dreamrunner.org/images/blog/2014/AlgorithmDesignManual/edge_cases_for_traversl.jpg" />

<p>
The correct labeling of each edge can be readily determined from the
state, discovery time, and parent of each vertex, as encoded in the
following function:
</p>

<div class="org-src-container">

<pre class="src src-c++"><span style="color: #98fb98;">int</span> <span style="color: #87cefa;">edge_classification</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">x</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">y</span>)
{
  <span style="color: #00ffff;">if</span> (parent[y] == x) <span style="color: #00ffff;">return</span>(TREE);
  <span style="color: #00ffff;">if</span> (discovered[y] &amp;&amp; !processed[y]) <span style="color: #00ffff;">return</span>(BACK);
  <span style="color: #00ffff;">if</span> (processed[y] &amp;&amp; (entry_time[y]&gt;entry_time[x])) <span style="color: #00ffff;">return</span>(FORWARD);
  <span style="color: #00ffff;">if</span> (processed[y] &amp;&amp; (entry_time[y]&lt;entry_time[x])) <span style="color: #00ffff;">return</span>(CROSS);
  printf(<span style="color: #ffa07a;">"Warning: unclassified edge (%d,%d)\n"</span>,x,y);
}
</pre>
</div>
</div>

<div id="outline-container-sec-1-8-1" class="outline-4">
<h4 id="sec-1-8-1">Strongly Connected Components</h4>
<div class="outline-text-4" id="text-1-8-1">
<p>
A directed graph isstrongly connectedif there is a directed path
between any two vertices.
</p>

<img src="http://dreamrunner.org/images/blog/2014/AlgorithmDesignManual/strongly_connected_components.jpg" />

<p>
The algorithm is based on the observation that it is easy to find a
directed cycle using a depth-first search, since any back edge plus
the down path in the DFS tree gives such a cycle. All vertices in this
cycle must be in the same strongly connected component. Thus, we can
shrink (contract) the vertices on this cycle down to a single vertex
representing the component, and then repeat. This process terminates
when no directed cycle remains, and each vertex represents a different
strongly connected component.
</p>

<p>
We update our notion of the oldest reachable vertex in response to (1)
nontree edges and (2) backing up from a vertex.
</p>

<div class="org-src-container">

<pre class="src src-c++"><span style="color: #87cefa;">strong_components</span>(<span style="color: #98fb98;">graph</span> *<span style="color: #eedd82;">g</span>)
{
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span>; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">counter */</span>
  <span style="color: #00ffff;">for</span> (i=1; i&lt;=(g-&gt;nvertices); i++) {
    low[i] = i;
    scc[i] = -1;
  }
  components_found = 0;
  init_stack(&amp;active);
  initialize_search(&amp;g);
  <span style="color: #00ffff;">for</span> (i=1; i&lt;=(g-&gt;nvertices); i++)
    <span style="color: #00ffff;">if</span> (discovered[i] == FALSE) {
      dfs(g,i);
    }
}
</pre>
</div>

<p>
Define low[v]to be the oldest vertex known to be in the same strongly
connected component asv. This vertex is not necessarily an ancestor,
but may also be a distant cousin of v because of cross edges. Cross
edges that point vertices from previous strongly connected components
of the graph cannot help us, because there can be no way back from
them tov, but otherwise cross edges are fair game. Forward edges have
no impact on reachability over the depth-first tree edges, and hence
can be disregarded:
</p>

<div class="org-src-container">

<pre class="src src-c++"><span style="color: #98fb98;">int</span> <span style="color: #eedd82;">low</span>[MAXV+1]; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">oldest vertex surely in component of v */</span>
<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">scc</span>[MAXV+1]; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">strong component number for each vertex */</span>
<span style="color: #87cefa;">process_edge</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">x</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">y</span>)
{
  <span style="color: #98fb98;">int</span> <span style="color: #00ffff;">class</span>; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">edge class */</span>
  <span style="color: #00ffff;">class</span> = edge_classification(x,y);
  <span style="color: #00ffff;">if</span> (<span style="color: #00ffff;">class</span> == BACK) {
    <span style="color: #00ffff;">if</span> (entry_time[y] &lt; entry_time[ low[x] ] )
      low[x] = y;
  }
  <span style="color: #00ffff;">if</span> (<span style="color: #00ffff;">class</span> == CROSS) {
    <span style="color: #00ffff;">if</span> (scc[y] == -1) <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">component not yet assigned */</span>
      <span style="color: #00ffff;">if</span> (entry_time[y] &lt; entry_time[ low[x] ] )
        low[x] = y;
  }
}
</pre>
</div>

<p>
A new strongly connected component is found whenever the lowest reachable
vertex fromvis v. If so, we can clear the stack of this component.
Otherwise, we give our parent the benefit of the oldest ancestor we
can reach and backtrack:
</p>

<div class="org-src-container">

<pre class="src src-c++">  <span style="color: #87cefa;">process_vertex_early</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">v</span>)
  {
    push(&amp;active,v);
  }

<span style="color: #87cefa;">process_vertex_late</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">v</span>)
{
  <span style="color: #00ffff;">if</span> (low[v] == v) { <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">edge (parent[v],v) cuts off scc */</span>
    pop_component(v);
  }
  <span style="color: #00ffff;">if</span> (entry_time[low[v]] &lt; entry_time[low[parent[v]]])
    low[parent[v]] = low[v];
}

<span style="color: #87cefa;">pop_component</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">v</span>)
{
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">t</span>; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">vertex placeholder */</span>
  components_found = components_found + 1;
  scc[ v ] = components_found;
  <span style="color: #00ffff;">while</span> ((t = pop(&amp;active)) != v) {
    scc[ t ] = components_found;
  }
}
</pre>
</div>
</div>
</div>
</div>
</div>
<div id="outline-container-sec-2" class="outline-2">
<h2 id="sec-2">Exercises</h2>
<div class="outline-text-2" id="text-2">
</div><div id="outline-container-sec-2-1" class="outline-3">
<h3 id="sec-2-1">5</h3>
<div class="outline-text-3" id="text-2-1">
<p>
Give a linear algorithm to compute the chromatic number of graphs
where each vertex has degree at most 2. Must such graphs be bipartite?
</p>

<p>
这样的图不必要是 bipartite 的.反例是:3 个顶点,两两相连.
</p>

<p>
因为每个顶点最多 2 度,使用 DFS 遍历,对子顶点着色与父顶点相反的颜色.当遇到一个回归的边,那么对当前定点着色与父顶点不同,并且与回归边上的祖先定点不同.
</p>

<p>
只有一次遍历,复杂度 O(m+n) (m edges, n vertices).
</p>
</div>
</div>

<div id="outline-container-sec-2-2" class="outline-3">
<h3 id="sec-2-2">7</h3>
<div class="outline-text-3" id="text-2-2">
<p>
Given pre-order and in-order traversals of a binary tree, is it
possible to reconstruct the tree? If so, sketch an algorithm to do it.
If not, give a counterexample. Repeat the problem if you are given the
pre-order and post-order traversals.
</p>

<p>
没有相同元素,给予 pre-order and in-order traversals 能重构 binary search
tree.代码如下.若有相同元素,给予:
</p>

<div class="org-src-container">

<pre class="src src-sh"><span style="color: #eedd82;">preorder</span> = {1,1}
<span style="color: #eedd82;">inorder</span> = {1,1}
</pre>
</div>
<p>
可以重构:
</p>
<div class="org-src-container">

<pre class="src src-sh">  1                     1
 /           or          <span style="color: #ffa07a;">\</span>
1                         1
</pre>
</div>

<p>
每次 preorder 的数都要去搜索在 inoder 所在位置,若书是平衡的,那么 n 个元素每次搜索后总的算法复杂度 O(nlogn),但不是平衡的,一下就变成 O(n<sup>2</sup>).
</p>

<p>
所以利用 hash table,先把 inorder 的元素和位置 hash 起来,那么总的算法时间:O(n).
</p>

<p>
以下假设元素都小于 255,简单的利用数组映射来模拟 hash table.
</p>
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #00ffff;">struct</span> <span style="color: #98fb98;">Node</span> {
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">val</span>;
  <span style="color: #00ffff;">struct</span> <span style="color: #98fb98;">Node</span>* <span style="color: #eedd82;">left</span>;
  <span style="color: #00ffff;">struct</span> <span style="color: #98fb98;">Node</span>* <span style="color: #eedd82;">right</span>;
  <span style="color: #87cefa;">Node</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">val_in</span>) {
    val = val_in;
    left = <span style="color: #7fffd4;">NULL</span>;
    right = <span style="color: #7fffd4;">NULL</span>;
  }
};

<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">kMax</span> = 256;
<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">map_index</span>[kMax];

<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">MapToIndex</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">inorder</span>[], <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">n</span>) {
  <span style="color: #00ffff;">for</span> (<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span> = 0; i &lt; n; ++i) {
    map_index[inorder[i]] = i;
  }
}

<span style="color: #98fb98;">Node</span> *<span style="color: #87cefa;">BuildInorderPreorder</span>(<span style="color: #98fb98;">in</span> <span style="color: #eedd82;">in</span>[], <span style="color: #98fb98;">in</span> <span style="color: #eedd82;">pre</span>[], <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">n</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">offset</span>) {
  <span style="color: #00ffff;">if</span> (n == 0) {
    <span style="color: #00ffff;">return</span> <span style="color: #7fffd4;">NULL</span>:
  }
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">root_val</span> = pre[0];
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span> = map_index[root_val] - offset;
  <span style="color: #98fb98;">Node</span> *<span style="color: #eedd82;">root</span> = <span style="color: #00ffff;">new</span> <span style="color: #98fb98;">Node</span>(root_val);
  root-&gt;left = BuildInorderPreorder(in, pre+1, i, offset);
  root-&gt;right = BuildInorderPreorder(in+i+1, pre+i+1, offset+i+1);
  <span style="color: #00ffff;">return</span> root;
}
</pre>
</div>

<ul class="org-ul">
<li>给予 pre-order and post-order traversals, 不能重构 binary search tree.
</li>
</ul>
</div>
</div>
<div id="outline-container-sec-2-3" class="outline-3">
<h3 id="sec-2-3">12</h3>
<div class="outline-text-3" id="text-2-3">
<p>
The square of a directed graph G = (V,E) is the graph G<sup>2</sup> = (V,E<sup>2</sup>) such
that (u,w)∈E<sup>2</sup> iff there exists v∈V, such that (u,v)∈E  and
(u,w)∈E; i.e., there is a path of exactly two edges from u to w.
square of a graph Give efficient algorithms for both adjacency lists
and matrices.
</p>

<p>
<b>adjacency matrices</b>
算法复杂度：O(n<sup>3</sup>).
</p>
<div class="org-src-container">

<pre class="src src-sh"><span style="color: #87cefa;">MakeSquareGraph</span>(G, n)
<span style="color: #00ffff;">for</span> <span style="color: #eedd82;">i</span>=1 to n
    <span style="color: #00ffff;">for</span> <span style="color: #eedd82;">j</span>=1 to n
        <span style="color: #eedd82;">G2</span>[i][j] = 0
<span style="color: #00ffff;">for</span> <span style="color: #eedd82;">i</span>=1 to n
    <span style="color: #00ffff;">for</span> <span style="color: #eedd82;">j</span>=1 to n
        <span style="color: #00ffff;">if</span> (<span style="color: #eedd82;">G</span>[i][j] == 1)
           <span style="color: #00ffff;">for</span> <span style="color: #eedd82;">k</span>=1 to n
               <span style="color: #00ffff;">if</span> (<span style="color: #eedd82;">G</span>[j][k] == 1)
                  <span style="color: #eedd82;">G2</span>[i][k] = 1
<span style="color: #00ffff;">return</span> G2
</pre>
</div>
</div>
</div>

<div id="outline-container-sec-2-4" class="outline-3">
<h3 id="sec-2-4">18</h3>
<div class="outline-text-3" id="text-2-4">
<p>
Consider a set of movies \(M_1, M_2, \ldots, M_k\). There is a set of
customers, each one of which indicates the two movies they would like
to see this weekend. Movies are shown on Saturday evening and Sunday
evening. Multiple movies may be screened at the same time. You must
decide which movies should be televised on Saturday and which on
Sunday, so that every customer gets to see the two movies they
desire. Is there a schedule where each movie is shown at most once?
Design an efficient algorithm to find such a schedule if one exists.
</p>

<p>
把问题转换成图问题解决。建立无向图，顶点是每部电影，边 E(1,2)表示有个客户想看 M1 和 M2.如下图实例，有电影 M1-M4,3 个客户，1 个客户想看 M1 和 M3,一个客户想看 M1 和 M4，一个客户想看 M2 和 M4.那么把图分成（M1，M2）和（M3,M4），周六日各放一组,满足所有客户要求。
</p>

<img src="http://dreamrunner.org/images/blog/2014/AlgorithmDesignManual/movie1.jpg" />

<p>
若多一个客户想看 M3 和 M4,如下图，无论怎么分图，都有 2 部电影相连，所以不能满足所有客户的要求。可以得出：若原本的图是 bipartite graph，那么能找到满足客户的放映安排。若不是，就不能满足客户要求。
</p>

<img src="http://dreamrunner.org/images/blog/2014/AlgorithmDesignManual/movie2.jpg" />
</div>
</div>

<div id="outline-container-sec-2-5" class="outline-3">
<h3 id="sec-2-5">23</h3>
<div class="outline-text-3" id="text-2-5">
<p>
Your job is to arrange n ill-behaved children in a straight line,
facing front. You are given a list of m statements of the form i hates
j. If i hates j, then you do not want put i somewhere behind j,
because then i is capable of throwing something at j.
</p>

<ol class="org-ol">
<li>Give an algorithm that orders the line, (or says that it is not
possible) in O(m + n) time.
</li>

<li>Suppose instead you want to arrange the children in rows such that
if i hates j, then i must be in a lower numbered row than j. Give
an efficient algorithm to find the minimum number of rows needed,
if it is possible.
</li>

<li>创建一幅有向图,顶点代表孩子,有向边 E(i,j)代表孩子 i hates 孩子 j;
</li>
<li>topological sort 得到队列，或 BFS 时发现环，证明不可能。只 BFS 遍历一次，
O(m + n)。
</li>

<li>如题 1 创建有向图;
</li>
<li>作 DFS 遍历，用遍历的 level 作为行号。
</li>
</ol>
</div>
</div>

<div id="outline-container-sec-2-6" class="outline-3">
<h3 id="sec-2-6">31</h3>
<div class="outline-text-3" id="text-2-6">
<p>
Which data structures are used in depth-first and breath-first search?
</p>
<ol class="org-ol">
<li>BFS:使用 queue
</li>
<li>DFS:使用 stack,通常使用递归代替 stack.
</li>
</ol>
</div>
</div>
<div id="outline-container-sec-2-7" class="outline-3">
<h3 id="sec-2-7">32</h3>
<div class="outline-text-3" id="text-2-7">
<p>
Write a function to traverse binary search tree and return the ith
node in sorted order.
</p>

<div class="org-src-container">

<pre class="src src-c++"><span style="color: #00ffff;">struct</span> <span style="color: #98fb98;">Node</span> {
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">val</span>;
  <span style="color: #00ffff;">struct</span> <span style="color: #98fb98;">Node</span>* <span style="color: #eedd82;">left</span>;
  <span style="color: #00ffff;">struct</span> <span style="color: #98fb98;">Node</span>* <span style="color: #eedd82;">right</span>;
  <span style="color: #87cefa;">Node</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">val_in</span>) {
    val = val_in;
    left = <span style="color: #7fffd4;">NULL</span>;
    right = <span style="color: #7fffd4;">NULL</span>;
  }
};

<span style="color: #98fb98;">bool</span> <span style="color: #87cefa;">FindIthElementCore</span>(<span style="color: #00ffff;">struct</span> <span style="color: #98fb98;">Node</span> *<span style="color: #eedd82;">root</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">ith</span>, <span style="color: #98fb98;">int</span> *<span style="color: #eedd82;">index</span>, <span style="color: #98fb98;">int</span> *<span style="color: #eedd82;">value</span>) {
  <span style="color: #00ffff;">if</span> (root == <span style="color: #7fffd4;">NULL</span>) {
    <span style="color: #00ffff;">return</span> <span style="color: #7fffd4;">false</span>;
  }
  <span style="color: #00ffff;">if</span> (FindIthElementCore(root-&gt;left, ith, index, value)) {
    <span style="color: #00ffff;">return</span> <span style="color: #7fffd4;">true</span>;
  }
  cout &lt;&lt; ith &lt;&lt; <span style="color: #ffa07a;">": "</span> &lt;&lt; *index &lt;&lt; <span style="color: #ffa07a;">": "</span> &lt;&lt; root-&gt;val &lt;&lt; endl;
  <span style="color: #00ffff;">if</span> (ith == *index) {
    *value = root-&gt;val;
    <span style="color: #00ffff;">return</span> <span style="color: #7fffd4;">true</span>;
  }
  (*index)++;
  <span style="color: #00ffff;">if</span> (FindIthElementCore(root-&gt;right, ith, index, value)) {
    <span style="color: #00ffff;">return</span> <span style="color: #7fffd4;">true</span>;
  } <span style="color: #00ffff;">else</span> {
    <span style="color: #00ffff;">return</span> <span style="color: #7fffd4;">false</span>;
  }
}

<span style="color: #98fb98;">bool</span> <span style="color: #87cefa;">FindIthElement</span>(<span style="color: #00ffff;">struct</span> <span style="color: #98fb98;">Node</span> *<span style="color: #eedd82;">root</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">ith</span>, <span style="color: #98fb98;">int</span> *<span style="color: #eedd82;">value</span>) {
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">start</span> = 0;
  <span style="color: #00ffff;">return</span> FindIthElementCore(root, ith, &amp;start, value);
}
</pre>
</div>
</div>
</div>
</div>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Algorithm Design Manual Chapter 4]]></title>
    <link href="http://dreamrunner.org/blog/2014/06/09/The-Algorithm-Design-Manual4/"/>
    <updated>2014-06-09T00:00:00+08:00</updated>
    <id>http://dreamrunner.org/blog/2014/06/09/The-Algorithm-Design-Manual4</id>
    <content type="html"><![CDATA[<div id="outline-container-sec-1" class="outline-2">
<h2 id="sec-1">Book Notes</h2>
<div class="outline-text-2" id="text-1">
</div><div id="outline-container-sec-1-1" class="outline-3">
<h3 id="sec-1-1">4.3 Heapsort: Fast Sorting via Data Structures</h3>
<div class="outline-text-3" id="text-1-1">
</div><div id="outline-container-sec-1-1-1" class="outline-4">
<h4 id="sec-1-1-1">Where in the Heap?</h4>
<div class="outline-text-4" id="text-1-1-1">
<p>
Problem: Given an array-based heap on n elements and a real number x,
efficiently determine whether the kth smallest element in the heap is
greater than or equal to x. Your algorithm should be O(k) in the
worst-case, independent of the size of the heap. Hint: you do not have
to find the kth smallest element; you need only determine its
relationship to x.
</p>

<p>
Solution: There are at least two different ideas that lead to correct
but inefficient algorithms for this problem:
</p>

<ol class="org-ol">
<li>Call extract-minktimes, and test whether all of these are less
thanx. This explicitly sorts the firstkelements and so gives us
more information than the desired answer, but it takes O(klogn) time
to do so.
</li>
<li>The kth smallest element cannot be deeper than the kth level of the
heap, since the path from it to the root must go through elements
of decreasing value. Thus we can look at all the elements on the
first k levels of the heap, and count how many of them are less
thanx, stopping when we either find k of them or run out of
elements. This is correct, but takes O(min(n,2<sup>k</sup>-1)) time, since
the top k elements have 2<sup>k</sup>-1 elements.
</li>
</ol>

<p>
An O(k) solution can look at only k elements smaller than x, plus at
most O(k) elements greater than x. Consider the following recursive
procedure, called at the root with i= 1 with count=k:
</p>

<!-- more -->


<div class="org-src-container">

<pre class="src src-c++"><span style="color: #98fb98;">int</span> <span style="color: #87cefa;">heap_compare</span>(<span style="color: #98fb98;">priority_queue</span> *<span style="color: #eedd82;">q</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">count</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">x</span>)
{
  <span style="color: #00ffff;">if</span> ((count &lt;= 0) || (i &gt; q-&gt;n)) <span style="color: #00ffff;">return</span>(count);
  <span style="color: #00ffff;">if</span> (q-&gt;q[i] &lt; x) {
    count = heap_compare(q, pq_young_child(i), count-1, x);
    count = heap_compare(q, pq_young_child(i)+1, count, x);
  }
  <span style="color: #00ffff;">return</span>(count);
}
</pre>
</div>

<p>
If the root of the min-heap is ≥ x, then no elements in the heap can
be less than x, as by definition the root must be the smallest
element. This procedure searches the children of all nodes of weight
smaller than x until either (a) we have found k of them, when it returns
0, or (b) they are exhausted, when it returns a value greater than
zero. Thus it will find enough small elements if they exist.
</p>

<p>
But how long does it take? The only nodes whose children we look at
are those &lt; x, and at most k of these in total. Each have at most
visited two children, so we visit at most 3k nodes, for a total time
of O(k).
</p>
</div>
</div>
</div>

<div id="outline-container-sec-1-2" class="outline-3">
<h3 id="sec-1-2">4.5 Mergesort: Sorting by Divide-and-Conquer</h3>
<div class="outline-text-3" id="text-1-2">
<p>
Mergesort is a great algorithm for sorting linked lists, because it
does not rely on random access to elements as does heapsort or
quicksort. Its primary disadvantage is the need for an auxilliary
buffer when sorting arrays. It is easy to merge two sorted linked
lists without using any extra space, by just rearranging the pointers.
However, to merge two sorted arrays (or portions of an array), we need
use a third array to store the result of the merge to avoid stepping
on the component arrays
</p>
</div>
</div>
<div id="outline-container-sec-1-3" class="outline-3">
<h3 id="sec-1-3">4.9 Binary Search and Related Algorithms</h3>
<div class="outline-text-3" id="text-1-3">
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #98fb98;">int</span> <span style="color: #87cefa;">binary_search</span>(<span style="color: #98fb98;">item_type</span> <span style="color: #eedd82;">s</span>[], <span style="color: #98fb98;">item_type</span> <span style="color: #eedd82;">key</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">low</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">high</span>)
{
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">middle</span>; <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">index of middle element */</span>
  <span style="color: #00ffff;">if</span> (low &gt; high) <span style="color: #00ffff;">return</span> (-1); <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">key not found */</span>
  middle = (low+high)/2;
  <span style="color: #00ffff;">if</span> (s[middle] == key) <span style="color: #00ffff;">return</span>(middle);
  <span style="color: #00ffff;">if</span> (s[middle] &gt; key)
    <span style="color: #00ffff;">return</span> (binary_search(s,key,low,middle-1));
  <span style="color: #00ffff;">else</span>
    <span style="color: #00ffff;">return</span> (binary_search(s,key,middle+1,high));
}
</pre>
</div>
</div>

<div id="outline-container-sec-1-3-1" class="outline-4">
<h4 id="sec-1-3-1">Counting Occurrences</h4>
<div class="outline-text-4" id="text-1-3-1">
<p>
This algorithm runs inO(lgn+s), wheresis the number of occurrences of
the key. This can be as bad as linear if the entire array consists of
identical keys. A faster algorithm results by modifying binary search
to search for the boundary of the block containing k, instead of
kitself. Suppose we delete the equality test
</p>

<p>
<code>if (s[middle] == key) return(middle);</code>
</p>

<p>
from the implementation above and return the index <code>low</code> instead of
<code>−1</code> on each unsuccessful search. All searches will now be
unsuccessful, since there is no equality test. The search will proceed
to the right half whenever the key is compared to an identical array
element, eventually terminating at the <b>right boundary</b>. Repeating the
search after reversing the direction of the binary comparison will
lead us to the <b>left boundary</b>. Each search takes O(lgn) time, so we can
count the occurrences in logarithmic time regardless of the size of
the block.
</p>
</div>
</div>
<div id="outline-container-sec-1-3-2" class="outline-4">
<h4 id="sec-1-3-2">One-Sided Binary Search</h4>
<div class="outline-text-4" id="text-1-3-2">
<p>
Now suppose we have an array A consisting of a run of 0’s, followed
by an unbounded run of 1’s, and would like to identify the exact
point of transition between them. Binary search on the array would
provide the transition point in lgn tests, if we had a bound non the
number of elements in the array. In the absence of such
a bound, we can test repeatedly at larger intervals (<code>A[1], A[2],
A[4], A[8], A[16],...</code>) until we find a first nonzero value. Now we
have a window containing the target and can proceed with binary
search. This <i>one-sided binary search</i> finds the transition pointpusing at
most 2lgp comparisons, regardless of how large the array actually is.
</p>
</div>
</div>
<div id="outline-container-sec-1-3-3" class="outline-4">
<h4 id="sec-1-3-3">Square and Other Roots</h4>
<div class="outline-text-4" id="text-1-3-3">
<p>
First, observe that the square root ofn≥1 must be at least 1 and at
most n. Let <code>l = 1</code> and <code>r = n</code>. Consider the midpoint of this
interval, <code>m=(l+r)/2</code>. How does m<sup>2</sup> compare to n? If n≥m<sup>2</sup> , then the
square root must be greater than m, so the algorithm repeats with
<code>l=m</code>. If n&lt;m<sup>2</sup> , then the square root must be less than m, so the
algorithm repeats with <code>r=m</code>. 
</p>

<p>
Suppose that we start with values l and r such that f(l)&gt;0 and f(r)&lt;0.
If f is a continuous function, there must exist a root between l and
r. Depending upon the sign of f(m), where <code>m=(l+r)/2</code>, we can cut this
window containing the root in half with each test and stop soon as our
estimate becomes sufficiently accurate.
</p>
</div>
</div>
</div>

<div id="outline-container-sec-1-4" class="outline-3">
<h3 id="sec-1-4">4.10 Divide-and-Conquer</h3>
<div class="outline-text-3" id="text-1-4">
<p>
divide-and-conquer recurrences of the form T(n)=aT(n/b)+f(n)
</p>

1. If $f(n) = O(n^{log_{b}^{a-\epsilon}})$ for some constant $\epsilon
   &gt; 0$, then $T(n) = \Theta(n^{log_{b}^a})$. <br /> 
2. If $f(n) = O(n^{log_{b}^{a}})$, then $T(n) =
   \Theta(n^{log_{b}^a}lgn)$.  <br /> 
3. If $f(n) = O(n^{log_{b}^{a+\epsilon}})$ for some constant $\epsilon
   &gt; 0$ and if $af(n/b) \leq cf(n)$ for some $c&lt;1$, then $T(n) =
   \Theta(f(n))$.  <br /> 
</div>
</div>
</div>
<div id="outline-container-sec-2" class="outline-2">
<h2 id="sec-2">Exercises</h2>
<div class="outline-text-2" id="text-2">
</div><div id="outline-container-sec-2-1" class="outline-3">
<h3 id="sec-2-1">1</h3>
<div class="outline-text-3" id="text-2-1">
<p>
The Grinch is given the job of partitioning 2n players into two teams
of n players each. Each player has a numerical rating that measures
how good he/she is at the game. He seeks to divide the players as
unfairly as possible, so as to create the biggest possible talent
imbalance between team A and team B. Show how the Grinch can do the
job in O(nlogn) time.
</p>

<p>
用个 O(nlogn)的排序算法对 2n 个队根据实力排序，前 n 个作为一队，后 n 个作为一队。
</p>
</div>
</div>

<div id="outline-container-sec-2-2" class="outline-3">
<h3 id="sec-2-2">2</h3>
<div class="outline-text-3" id="text-2-2">
<p>
For each of the following problems, give an algorithm that finds the
desired numbers within the given amount of time. To keep your answers
brief, feel free to use algorithms from the book as subroutines. For
the example,S={6,13,19,3,8}, 19−3 maximizes the difference, while 8−6
minimizes the difference.
</p>


<p>
(a) Let S be an unsorted array of n integers. Give an algorithm that
finds the pair x, y∈S that maximizes|x−y|. Your algorithm must run in
O(n) worst-case time.
</p>

<p>
(b) Let S be a sorted array of n integers. Give an algorithm that finds
the pair x, y∈S that maximizes |x−y|. Your algorithm must run in O(1)
worst-case time.
</p>

<p>
(c) Let S be an unsorted array of n integers. Give an algorithm that finds
the pair x, y∈S that minimizes |x−y|, for x &ne; y. Your algorithm must run
in O(nlogn) worst-case time.
</p>

<p>
(d) Let S be a sorted array of n integers. Give an algorithm that finds the pair
x, y∈S that minimizes |x−y|, for x &ne; y. Your algorithm must run in O(n)
worst-case time.
</p>


<ul class="org-ul">
<li>(a) 扫描 S 一次获得最小和最大值.
</li>
<li>(b) 取首尾数。
</li>
<li>(c) O(nlogn)的算法排序，扫描排序好的 S，获得最小差的相邻元素对。
</li>
<li>(d) 扫描排序好的 S，获得最小差的相邻元素对。
</li>
</ul>
</div>
</div>
<div id="outline-container-sec-2-3" class="outline-3">
<h3 id="sec-2-3">3</h3>
<div class="outline-text-3" id="text-2-3">
<p>
Take a sequence of 2n real numbers as input. Design an O(nlogn)
algorithm that partitions the numbers intonpairs, with the property
that the partition minimizes the maximum sum of a pair. For example,
say we are given the numbers (1,3,5,9). The possible partitions are
((1,3),(5,9)), ((1,5),(3,9)), and ((1,9),(3,5)). The pair sums for
these partitions are (4,14), (6,12), and (10,8). Thus the third
partition has 10 as its maximum sum, which is the minimum over the
three partitions.
</p>

<ol class="org-ol">
<li>O(nlogn)的算法排序
</li>
<li><div class="org-src-container">

<pre class="src src-c++">start = 0;
end = 2n - 1;
<span style="color: #00ffff;">while</span> (start &lt; end) {
  pair(S[star], S[end]);
  start++;
  end--;
</pre>
</div>
</li>
</ol>
</div>
</div>
<div id="outline-container-sec-2-4" class="outline-3">
<h3 id="sec-2-4">4</h3>
<div class="outline-text-3" id="text-2-4">
<p>
Assume that we are given n pairs of items as input, where the first item
is a and the second item is one of three colors (red, blue, or
yellow). Further assume that the items are sorted by number. Give
an O(n) algorithm to sort the items by color (all reds before all blues
before all yellows) such that the numbers for identical colors stay
sorted. For example: (1,blue), (3,red), (4,blue), (6,yellow), (9,red)
should become (3,red), (9,red), (1,blue), (4,blue), (6,yellow).
</p>

<ol class="org-ol">
<li>创建 3 个分别存储 red，blue，yellow 的数组;
</li>
<li>扫描 input，依次按颜色装入不同的数组;
</li>
<li>分别从 red，blue，yellow 的数组中输出结果。
</li>
</ol>
</div>
</div>
<div id="outline-container-sec-2-5" class="outline-3">
<h3 id="sec-2-5">5</h3>
<div class="outline-text-3" id="text-2-5">
<p>
The mode of a set of numbers is the number that occurs most frequently
in the set. The set (4,6,2,4,3,1) has a mode of 4. Give an efficient
and correct algorithm to compute the mode of a set of n numbers.
</p>

<ul class="org-ul">
<li>O(nlogn): O(nlogn)排序，扫描 Set 一遍得到频率最大的数。
</li>
<li>O(n): 使用 hash map 扫描一遍存储数字频率，扫描 hash map 得到频率最大数。
</li>
</ul>
</div>
</div>
<div id="outline-container-sec-2-6" class="outline-3">
<h3 id="sec-2-6">6</h3>
<div class="outline-text-3" id="text-2-6">
<p>
Given two sets S1 and S2 (each of size n), and a number x, describe an
O(nlogn) algorithm for finding whether there exists a pair of
elements, one from S1 and one from S2, that add up to x. (For partial
credit, give a Θ(n<sup>2</sup>) algorithm for this problem.)
</p>

<ol class="org-ol">
<li>从 S1 中减去 n，O(nlogn)排序 S1 和 S2,然后能否找出相同的元素（binary search 或扫描比较）。
</li>
<li>Sort and Scan
<div class="org-src-container">

<pre class="src src-sh">sort S1<span style="color: #00ffff;"> in</span> O(nlogn)
sort S2<span style="color: #00ffff;"> in</span> O(nlogn)
<span style="color: #eedd82;">begin</span> = 0;
<span style="color: #eedd82;">end</span> = n - 1;
<span style="color: #00ffff;">while</span> (begin &lt; n &amp;&amp; end &gt;=0) {
          <span style="color: #00ffff;">if</span> ((S1[begin] + S2[end]) &lt; X) {
                 begin++;
          }
          <span style="color: #00ffff;">else if</span> ((S1[begin] + S2[end]) &gt; X) {
                 end--;
          } <span style="color: #00ffff;">else</span> {
              <span style="color: #00ffff;">return </span><span style="color: #b0c4de;">true</span>;
          }
}
<span style="color: #00ffff;">return </span><span style="color: #b0c4de;">false</span>;
</pre>
</div>
</li>
<li>Binary Search
<ul class="org-ul">
<li>O(nlogn)排序 S1
</li>
<li>X-S2[i]去 binary search 排序好的 S1，是否找到元素。
</li>
</ul>
</li>
</ol>
</div>
</div>
<div id="outline-container-sec-2-7" class="outline-3">
<h3 id="sec-2-7">7</h3>
<div class="outline-text-3" id="text-2-7">
<p>
Outline a reasonable method of solving each of the following problems.
Give the order of the worst-case complexity of your methods.
</p>

<ol class="org-ol">
<li>You are given a pile of thousands of telephone bills and thousands
of checks sent in to pay the bills. Find out who did not pay.
</li>

<li>You are given a list containing the title, author, call number and
publisher of all the books in a school library and another list of
30 publishers. Find out how many of the books in the library were
published by each company.
</li>

<li>You are given all the book checkout cards used in the campus
library during the past year, each of which contains the name of
the person who took out the book. Determine how many distinct
people checked out at least one book.
</li>
</ol>

<p>
都使用 Hash Table，O(n)
</p>
</div>
</div>
<div id="outline-container-sec-2-8" class="outline-3">
<h3 id="sec-2-8">8</h3>
<div class="outline-text-3" id="text-2-8">
<p>
Given a set of S containing n real numbers, and a real number x. We
seek an algorithm to determine whether two elements of S exist whose
sum is exactly x.
</p>

<ul class="org-ul">
<li>Assume that S is unsorted. Give an O(nlogn) algorithm for the problem.
</li>
<li>Assume that S is sorted. Give an O(n) algorithm for the problem.
</li>
</ul>

<p>
(1):
Binary search
</p>
<div class="org-src-container">

<pre class="src src-sh">sort S<span style="color: #00ffff;"> in</span> O(nlogn);
<span style="color: #00ffff;">for</span> (int <span style="color: #eedd82;">i</span> = 0; i &lt; n; ++i) {
        binarysearch S[i]<span style="color: #00ffff;"> in</span> S[i+1,n]
}
</pre>
</div>

<p>
Scan
</p>
<div class="org-src-container">

<pre class="src src-sh">sort S<span style="color: #00ffff;"> in</span> O(nlogn);
<span style="color: #eedd82;">i</span> = 0;
<span style="color: #eedd82;">j</span> = n - 1;
<span style="color: #00ffff;">while</span> (i &lt; j) {
  <span style="color: #00ffff;">if</span> (s[i] + s[j] &lt; X) {
    i++;
  } <span style="color: #00ffff;">else if</span> (s[i] + s[j] &gt; X) {
    j--;
  } <span style="color: #00ffff;">else</span> {
    <span style="color: #00ffff;">break</span>;
  }
}
</pre>
</div>

<p>
(2)
</p>
<div class="org-src-container">

<pre class="src src-c++">i = 0;
j = n - 1;
<span style="color: #00ffff;">while</span> (i &lt; j) {
  <span style="color: #00ffff;">if</span> (s[i] + s[j] &lt; X) {
    i++;
  } <span style="color: #00ffff;">else</span> <span style="color: #00ffff;">if</span> (s[i] + s[j] &gt; X) {
    j--;
  } <span style="color: #00ffff;">else</span> {
    <span style="color: #00ffff;">break</span>;
  }
}
</pre>
</div>
</div>
</div>

<div id="outline-container-sec-2-9" class="outline-3">
<h3 id="sec-2-9">9</h3>
<div class="outline-text-3" id="text-2-9">
<p>
Give an efficient algorithm to compute the union of sets A and B,
where n = max( | A | , | B | ). The output should be an array of
distinct elements that form the union of the sets, such that they
appear more than once in the union.
</p>

<ul class="org-ul">
<li>Assume that A and B are unsorted. Give an O(nlogn) algorithm for the
problem.
</li>

<li>Assume that A and B are sorted. Give an O(n) algorithm for the problem.
</li>

<li>O(nlogn)对Ａ和Ｂ排序，然后用 2 的 O(n)的方法。
</li>
<li>若Ａ和Ｂ以升序排序
<div class="org-src-container">

<pre class="src src-sh"><span style="color: #b0c4de;">set</span> U to empty;
int <span style="color: #eedd82;">i</span> = 0;
int <span style="color: #eedd82;">j</span> = 0;
<span style="color: #00ffff;">while</span> (i &lt; na &amp;&amp; j &lt; na) {
  <span style="color: #00ffff;">if</span> (A[i] &lt; B[j]) {
    add A[i] into U;
    i++;
  } <span style="color: #00ffff;">else</span> (A[i] &gt; B[j]) {
      add B[j] into U;
      j++;
    }
  <span style="color: #00ffff;">else</span> {
     add A[i] into U;
    i++;
    j++;
  }
}
<span style="color: #00ffff;">if</span> (i &lt; na) {
  <span style="color: #00ffff;">while</span> (i &lt; na) {
    add A[i] into U;
    i++;
  }
<span style="color: #00ffff;">if</span> (j &lt; nb) {
  <span style="color: #00ffff;">while</span> (j &lt; nb) {
   add B[j] into U;
      j++;
    }
}
</pre>
</div>
</li>
</ul>
</div>
</div>
<div id="outline-container-sec-2-10" class="outline-3">
<h3 id="sec-2-10">10</h3>
<div class="outline-text-3" id="text-2-10">
<p>
Given a set S of n integers and an integer T, give an O(n<sup>k − 1</sup>logn)
algorithm to test whether k of the integers in S add up to T.
</p>

<ol class="org-ol">
<li>O(nlogn）对数组排序
</li>
<li>(k-1)个数的组合有 n<sup>k-1</sup>，并计算 k-1 个数的和 sum
</li>
<li>用 binary search 在数组中搜索 T-sum
</li>
</ol>
</div>
</div>

<div id="outline-container-sec-2-11" class="outline-3">
<h3 id="sec-2-11">11</h3>
<div class="outline-text-3" id="text-2-11">
<p>
Design an O(n) algorithm that, given a list of n elements, finds all
the elements that appear more than n / 2 times in the list. Then,
design an O(n) algorithm that, given a list of n elements, finds all
the elements that appear more than n / 4 times.
</p>

<p>
Hash Table 可以解决。或
</p>
</div>

<div id="outline-container-sec-2-11-1" class="outline-4">
<h4 id="sec-2-11-1">Find the elements that appear more than n / 2 times</h4>
<div class="outline-text-4" id="text-2-11-1">
<p>
数组中最多有一个数超过重复 n/2 次，并且排序后的第 ceiling(n/2)个数必定是这个数。
</p>
<ol class="org-ol">
<li>method1
<ul class="org-ul">
<li>利用<a href="http://wiki.dreamrunner.org/public_html/Algorithms/Theory%20of%20Algorithms/Median%20Problem.html#sec-5">BFPRT</a> 以 O(n)的复杂度找到第 ceiling(n/2)个小数;
</li>
<li>扫描数组，计数这个数的重复数是否大于 n/2.
</li>
</ul>
</li>
<li>method2
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;stack&gt;</span>
<span style="color: #00ffff;">using</span> <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">stack</span>;

<span style="color: #98fb98;">bool</span> <span style="color: #87cefa;">FindMoreThanHalf</span>(<span style="color: #98fb98;">int</span> *<span style="color: #eedd82;">array</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">n</span>, <span style="color: #98fb98;">int</span> *<span style="color: #eedd82;">res</span>) {
  <span style="color: #98fb98;">stack</span>&lt;<span style="color: #98fb98;">int</span>&gt; <span style="color: #eedd82;">stk</span>;
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span>;
  <span style="color: #00ffff;">for</span> (i = 0; i &lt; n; ++i) {
    <span style="color: #00ffff;">if</span> (stk.empty()) {
      stk.push(array[i]);
    } <span style="color: #00ffff;">else</span> {
      <span style="color: #00ffff;">if</span> (stk.top() == array[i]) {
        stk.push(array[i]);
      } <span style="color: #00ffff;">else</span> {
        stk.pop();
      }
    }
  }
  <span style="color: #00ffff;">if</span> (stk.empty()) {
    <span style="color: #00ffff;">return</span> <span style="color: #7fffd4;">false</span>;
  }
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">candidate</span> = stk.top();
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">times</span> = 0;
  <span style="color: #00ffff;">for</span> (i = 0; i &lt; n; ++i) {
    <span style="color: #00ffff;">if</span> (array[i] == candidate) {
      times++;
    }
  }
  <span style="color: #00ffff;">if</span> (times &gt; n / 2) {
    *res = candidate;
    <span style="color: #00ffff;">return</span> <span style="color: #7fffd4;">true</span>;
  }
  <span style="color: #00ffff;">return</span> <span style="color: #7fffd4;">false</span>;
}
</pre>
</div>
</li>
</ol>
</div>
</div>

<div id="outline-container-sec-2-11-2" class="outline-4">
<h4 id="sec-2-11-2">Find the elements that appear more than n / 4 times</h4>
<div class="outline-text-4" id="text-2-11-2">
<ul class="org-ul">
<li>method1
<ol class="org-ol">
<li>利用<a href="http://wiki.dreamrunner.org/public_html/Algorithms/Theory%20of%20Algorithms/Median%20Problem.html#sec-5">BFPRT</a> 以 O(n)的复杂度找到中间数，验证中中间数是否重复
n/4(O(n));
</li>
<li>以中间元素划分数组为两部分(O(n));
</li>
<li>在上下半部分 n/2 中重复 n/4 次数的元素，同第一个问题一样找(O(n));
</li>
</ol>
</li>
<li>method2
<ol class="org-ol">
<li>初始 3 个空的槽，想对应的槽的 3 个计数为 0;
</li>
<li>对于数组中每个元素：
<ul class="org-ul">
<li>若等于其中任何一个槽中数，增加计数;
</li>
<li>若有槽空，放入这个槽，并计数为 1;
</li>
<li>否则，对所有槽内数的计数减 1
</li>
</ul>
</li>
<li>对槽内剩下的数，扫描一遍数组，计算它们重复次数是否符合要求。
</li>
</ol>
</li>
</ul>
</div>
</div>
</div>
<div id="outline-container-sec-2-12" class="outline-3">
<h3 id="sec-2-12">12</h3>
<div class="outline-text-3" id="text-2-12">
<p>
Devise an algorithm for finding the k smallest elements of an unsorted
set of n integers in O(n + klogn).
</p>

<ol class="org-ol">
<li>O(n)的复杂度建立一个最小堆;
</li>
<li>连续 k 次取出最小值，最后得到第 k 个最小值。
</li>
</ol>
</div>
</div>
<div id="outline-container-sec-2-13" class="outline-3">
<h3 id="sec-2-13">13</h3>
<div class="outline-text-3" id="text-2-13">
<p>
You wish to store a set of n numbers in either a max-heap or a sorted
array. For each application below, state which data structure is
better, or if it does not matter. Explain your answers.
</p>

<ol class="org-ol">
<li>Want to find the maximum element quickly.
</li>
<li>Want to be able to delete an element quickly.
</li>
<li>Want to be able to form the structure quickly.
</li>
<li>Want to find the minimum element quickly.
</li>

<li>都开销 O(1)。
</li>
<li>若知道删除的地方，max-heap 花费 O(logn)，sorted array 花费 O(n)。若不知道删除的地方，max-heap 花费 O(n)查找，删除花费 O(logn); sorted
array binary search 花费 O(logn)，删除花费 O(n)。
</li>
<li>max-heap 花费 O(n);sorted array 花费 O(logn)。
</li>
<li>max-heap 花费 O(n);sorted array 花费 O(1)。
</li>
</ol>
</div>
</div>
<div id="outline-container-sec-2-14" class="outline-3">
<h3 id="sec-2-14">14</h3>
<div class="outline-text-3" id="text-2-14">
<p>
Give an O(nlogk)-time algorithm that merges k sorted lists with a
total of n elements into one sorted list. (Hint: use a heap to speed
up the elementary O(kn)-time algorithm).
</p>

<ol class="org-ol">
<li>扫描 k 组 sorted lists 组成一个大小 k 的 min-heap;
</li>
<li>从 min-heap 中取出最小值放入结果 list。
</li>
</ol>
</div>
</div>

<div id="outline-container-sec-2-15" class="outline-3">
<h3 id="sec-2-15">15</h3>
<div class="outline-text-3" id="text-2-15">
<p>
(a) Give an efficient algorithm to find the second-largest key among n
keys. You can do better than 2n − 3 comparisons. (b) Then, give an
efficient algorithm to find the third-largest key among n keys. How
many key comparisons does your algorithm do in the worst case? Must
your algorithm determine which key is largest and second-largest in
the process?
</p>

<ul class="org-ul">
<li>找第二大元素：大小为 2 个的数组初始化为第一二个元素，之后每个元素与这数组对比，剔除最小的，最后数组内 2 个元组对比得到最大和第二大元素，一共比较 2(n-2)+1=2n-3，找出第二大元素。
</li>
<li>找第三大元素：同样已大小为 3 的数组，最后比较数 3(n-3)+2=3n-7。
</li>
</ul>

<p>
<a href="http://wiki.dreamrunner.org/public_htmlAlgorithms/Theory%20of%20Algorithms/Selection%20Problem.html#sec-4">Random Selection</a>可以找出任意的第几大值，平均时间复杂度：O(n)，比较次数将是 n 的倍数，最坏时间复杂度可以达到：O(nlogn)。
</p>

<p>
<a href="http://wiki.dreamrunner.org/public_html/Algorithms/Theory%20of%20Algorithms/Selection%20Problem.html#sec-6">Tournament Algorithm</a>找第二大元素比较次数 O(n+logn);找第 k 个最大元素，比较次数为 O(n+klogn)。
</p>
</div>
</div>

<div id="outline-container-sec-2-16" class="outline-3">
<h3 id="sec-2-16">16</h3>
<div class="outline-text-3" id="text-2-16">
<p>
Use the partitioning idea of quicksort to give an algorithm that
finds the median element of an array of n integers in expected O(n)
time. (Hint: must you look at both sides of the partition?)
</p>

<div class="org-src-container">

<pre class="src src-c++"><span style="color: #98fb98;">unsigned</span> <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">seed</span> = time(<span style="color: #7fffd4;">NULL</span>);
<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">randint</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">m</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">n</span>) {
  <span style="color: #00ffff;">return</span> m + rand_r(&amp;seed) / (RAND_MAX / (n + 1 - m) + 1);
}

<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">RandomSelectionK</span>(<span style="color: #98fb98;">int</span> *<span style="color: #eedd82;">array</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">l</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">u</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">k</span>) {
  <span style="color: #00ffff;">if</span> (l &gt;= u) {
    <span style="color: #00ffff;">return</span>;
  }
  swap(array[l], array[randint(l, u)]);
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">pivot</span> = array[l];
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span> = l;
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">j</span> = u + 1;
  <span style="color: #00ffff;">while</span> (<span style="color: #7fffd4;">true</span>) {
    <span style="color: #00ffff;">do</span> {
      ++i;
    } <span style="color: #00ffff;">while</span> (i &lt;= u &amp;&amp; array[i] &lt; pivot);
    <span style="color: #00ffff;">do</span> {
      --j;
    } <span style="color: #00ffff;">while</span> (array[j] &gt; pivot);
    <span style="color: #00ffff;">if</span> (i &gt; j) {
      <span style="color: #00ffff;">break</span>;
    }
    swap(array[i], array[j]);
  }
  swap(array[l], array[j]);
  <span style="color: #00ffff;">if</span> (j &lt; k) {
    RandomSelectionK(array, j + 1, u, k);
  } <span style="color: #00ffff;">else</span> <span style="color: #00ffff;">if</span> (j &gt; k) {
    RandomSelectionK(array, l, j - 1, k);
  }
}
</pre>
</div>
</div>
</div>
<div id="outline-container-sec-2-17" class="outline-3">
<h3 id="sec-2-17">17</h3>
<div class="outline-text-3" id="text-2-17">
The median of a set of n values is the $\lceil n/2 \rceil$ th smallest
value. <br />
1. Suppose quicksort always pivoted on the median of the current
   sub-array. How many comparisons would Quicksort make then in the
   worst case? <br />

2. Suppose quicksort were always to pivot on the $\lceil n/3 \rceil$ th
   smallest value of the current sub-array. How many comparisons would
   be made then in the worst case? <br />

<p>
f(n) = 2*f(n/2) + n ==&gt; f(n) = 2<sup>k</sup> * f(n/2<sup>k</sup>) + kn = (n+2)logn
f(n) = f(n/3) + f(2n/3) + n ==&gt; f(n) = O(nlogn)
</p>
</div>
</div>

<div id="outline-container-sec-2-18" class="outline-3">
<h3 id="sec-2-18">18</h3>
<div class="outline-text-3" id="text-2-18">
<p>
Suppose an array A consists of n elements, each of which is red,
white, or blue. We seek to sort the elements so that all the reds come
before all the whites, which come before all the blues The only
operation permitted on the keys are
</p>

<ul class="org-ul">
<li>Examine(A,i) &#x2013; report the color of the ith element of A.
</li>
<li>Swap(A,i,j) &#x2013; swap the ith element of A with the jth element.
</li>
</ul>
<p>
Find a correct and efficient algorithm for red-white-blue sorting.
There is a linear-time solution.
</p>

<p>
2 次扫描。
</p>
<ul class="org-ul">
<li>第一次：把 red 和 white 当成一样，用 quick 的 partition 分开与 blue。
</li>
<li>第二次：只区分 red 和 white 的子区间。   
</li>
</ul>
</div>
</div>

<div id="outline-container-sec-2-19" class="outline-3">
<h3 id="sec-2-19">21</h3>
<div class="outline-text-3" id="text-2-19">
<p>
Stable sorting algorithms leave equal-key items in the same relative
order as in the original permutation. Explain what must be done to
ensure that mergesort is a stable sorting algorithm.
</p>

<p>
在合并时元素相等时选 index 小的元素在前。
</p>
</div>
</div>

<div id="outline-container-sec-2-20" class="outline-3">
<h3 id="sec-2-20">22-23</h3>
<div class="outline-text-3" id="text-2-20">
<p>
Show that n positive integers in the range 1 to k can be sorted in
O(nlogk) time. The interesting case is when k &lt; &lt; n.
</p>

<p>
We seek to sort a sequence S of n integers with many duplications,
such that the number of distinct integers in S is O(logn). Give an
O(nloglogn) worst-case time algorithm to sort such sequences.
</p>

<p>
balanced binary search tree.
</p>
</div>
</div>

<div id="outline-container-sec-2-21" class="outline-3">
<h3 id="sec-2-21">24</h3>
<div class="outline-text-3" id="text-2-21">
<p>
Let A[1..n] be an array such that the first \(n-\sqrt n\)  elements are
already sorted (though we know nothing about the remaining elements).
Give an algorithm that sorts A in substantially better than nlogn
steps.
</p>

+ $O(\sqrt{n}log(\sqrt{n})$ 排序后面的 $\sqrt{n}$ 个元素。<br />
+ O(n)去 mergesort 前半部分和后半部分。
</div>
</div>

<div id="outline-container-sec-2-22" class="outline-3">
<h3 id="sec-2-22">25</h3>
<div class="outline-text-3" id="text-2-22">
<p>
Assume that the array A[1..n] only has numbers from \(\{1,\ldots, n^2\}\)
but that at most loglogn of these numbers ever appear. Devise an
algorithm that sorts A in substantially less than O(nlogn).
</p>

<p>
和 23 一样，用 balanced binary search tree，树的高度不超过 loglogn,最后的复杂度 O(n*logloglogn)。
</p>
</div>
</div>
<div id="outline-container-sec-2-23" class="outline-3">
<h3 id="sec-2-23">27</h3>
<div class="outline-text-3" id="text-2-23">
<p>
Let P be a simple, but not necessarily convex, polygon and q an
arbitrary point not necessarily in P. Design an efficient algorithm
to find a line segment originating from q that intersects the maximum
number of edges of P. In other words, if standing at point q, in what
direction should you aim a gun so the bullet will go through the
largest number of walls. A bullet through a vertex of P gets credit
for only one wall. An O(nlogn) algorithm is possible.
</p>

<ol class="org-ol">
<li>以ｑ为中心点，顺时针旋转，Ｐ中所有边随着顺时针旋转都有一个起始点
(head)和结束点（end），计算它们的极角（polar angle）; O(n)
</li>
<li>对所有 head 和 end 按照 angle 大小排序，若相等，head 在前; O(nlogn)
</li>
<li>扫描这个排序好的队列，遇到 head 加 1,遇到 end 减 1,最后算出这个区间的最大值。O(n)
</li>
</ol>
</div>
</div>
<div id="outline-container-sec-2-24" class="outline-3">
<h3 id="sec-2-24">30</h3>
<div class="outline-text-3" id="text-2-24">
<p>
A company database consists of 10,000 sorted names, 40% of whom are known as good customers and who together account for 60% of the accesses to the database. There are two data structure options to consider for representing the database:
</p>
<ol class="org-ol">
<li>Put all the names in a single array and use binary search.
</li>
<li>Put the good customers in one array and the rest of them in a
second array.
</li>
</ol>

<p>
Only if we do not find the query name on a binary search of the first
array do we do a binary search of the second array. Demonstrate which
option gives better expected performance. Does this change if linear
search on an unsorted array is used instead of binary search for both
options?
</p>

<ul class="org-ul">
<li>single array: log10000=4
</li>
<li>two array: 0.6*log4000+0.4*(log4000+log6000) = 5.11
</li>
</ul>
<p>
single array is better.
</p>

<ul class="org-ul">
<li>single array: 10000
</li>
<li>two array: 0.6*4000+0.4*6000 = 6400
</li>
</ul>
<p>
two array is better.
</p>
</div>
</div>
<div id="outline-container-sec-2-25" class="outline-3">
<h3 id="sec-2-25">31</h3>
<div class="outline-text-3" id="text-2-25">
<p>
Suppose you are given an array A of n sorted numbers that has been
circularly shifted k positions to the right. For example,
{35,42,5,15,27,29} is a sorted array that has been circularly shifted
k = 2 positions, while {27,29,35,42,5,15} has been shifted k = 4
positions.
</p>

<ol class="org-ol">
<li>Suppose you know what k is. Give an O(1) algorithm to find the
largest number in A.
</li>

<li>Suppose you do not know what k is. Give an O(lgn) algorithm to find
the largest number in A. For partial credit, you may give an O(n)
algorithm.
</li>
</ol>


<div class="org-src-container">

<pre class="src src-c++"><span style="color: #00ffff;">if</span> (k == 0) {
  <span style="color: #00ffff;">return</span> A[n-1];
} <span style="color: #00ffff;">else</span> {
  <span style="color: #00ffff;">return</span> A[k-1];
}
</pre>
</div>

<div class="org-src-container">

<pre class="src src-c++"><span style="color: #98fb98;">int</span> <span style="color: #87cefa;">FindLargestNumber</span>(<span style="color: #98fb98;">int</span> *<span style="color: #eedd82;">array</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">l</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">h</span>) {
  <span style="color: #00ffff;">if</span> (array[l] &lt; array[h]) {
    <span style="color: #00ffff;">return</span> array[h];
  }
  <span style="color: #00ffff;">if</span> (l == h) {
    <span style="color: #00ffff;">return</span> array[h];
  }
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">mid</span>;
  mid = (l + h) / 2;
  <span style="color: #00ffff;">if</span> ((mid + 1 &lt;= h) &amp;&amp; array[mid] &gt; array[mid + 1]) {
    <span style="color: #00ffff;">return</span> array[mid];
  }
  <span style="color: #00ffff;">if</span> ((mid - 1 &gt;= l) &amp;&amp; array[mid - 1] &gt; array[mid]) {
    <span style="color: #00ffff;">return</span> array[mid - 1];
  }
  <span style="color: #00ffff;">if</span> (array[mid] &lt; array[h]) {
    <span style="color: #00ffff;">return</span> FindLargestNumber(array, l, mid - 1);
  } <span style="color: #00ffff;">else</span> {
    <span style="color: #00ffff;">return</span> FindLargestNumber(array, mid + 1, h);
  }
}
</pre>
</div>
</div>
</div>
<div id="outline-container-sec-2-26" class="outline-3">
<h3 id="sec-2-26">32</h3>
<div class="outline-text-3" id="text-2-26">
<p>
Consider the numerical 20 Questions game. In this game, Player 1
thinks of a number in the range 1 to n. Player 2 has to figure out
this number by asking the fewest number of true/false questions.
Assume that nobody cheats.
</p>

<ol class="org-ol">
<li>What is an optimal strategy if n is known?
</li>
<li>What is a good strategy if n is not known?
</li>
</ol>


<ol class="org-ol">
<li>binary search.
</li>
<li>2<sup>i</sup>随机选一个 i，若数小，增加到 2<sup>i+1</sup>,若大就二分搜索。
</li>
</ol>
</div>
</div>

<div id="outline-container-sec-2-27" class="outline-3">
<h3 id="sec-2-27">33</h3>
<div class="outline-text-3" id="text-2-27">
<p>
Suppose that you are given a sorted sequence of distinct integers .
Give an O(lgn) algorithm to determine whether there exists an i index
such as ai = i. For example, in { − 10, − 3,3,5,7}, a3 = 3. In
{2,3,4,5,6,7}, there is no such i.
</p>

<div class="org-src-container">

<pre class="src src-c++"><span style="color: #98fb98;">bool</span> <span style="color: #87cefa;">CheckEqualIndex</span>(<span style="color: #98fb98;">int</span> *<span style="color: #eedd82;">array</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">l</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">h</span>) {
  <span style="color: #00ffff;">while</span> (l &lt;= h) {
    <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">mid</span> = (l + h) / 2;
    <span style="color: #00ffff;">if</span> (array[mid] &gt; (mid + 1)) {
      h = mid - 1;
    } <span style="color: #00ffff;">else</span> <span style="color: #00ffff;">if</span> (array[mid] &lt; (mid + 1)) {
      l = mid + 1;
    } <span style="color: #00ffff;">else</span> {
      <span style="color: #00ffff;">return</span> <span style="color: #7fffd4;">true</span>;
    }
  }
  <span style="color: #00ffff;">return</span> <span style="color: #7fffd4;">false</span>;
}
</pre>
</div>
</div>
</div>
<div id="outline-container-sec-2-28" class="outline-3">
<h3 id="sec-2-28">34</h3>
<div class="outline-text-3" id="text-2-28">
<p>
Suppose that you are given a sorted sequence of distinct integers ,
drawn from 1 to m where n &lt; m. Give an O(lgn) algorithm to find an
integer  that is not present in a. For full credit, find the smallest
such integer.
</p>

<div class="org-src-container">

<pre class="src src-c++"><span style="color: #98fb98;">int</span> <span style="color: #87cefa;">FindMissingElement</span>(<span style="color: #98fb98;">int</span> *<span style="color: #eedd82;">array</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">l</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">h</span>) {
  <span style="color: #00ffff;">while</span> (l &lt;= h) {
    <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">mid</span> = (l + h) / 2;
    <span style="color: #00ffff;">if</span> (array[mid] &gt; (mid + 1)) {
      h = mid - 1;
    } <span style="color: #00ffff;">else</span> <span style="color: #00ffff;">if</span> (array[mid] &lt;= (mid + 1)) {
      l = mid + 1;
    }
  }
  <span style="color: #00ffff;">return</span> l + 1;
}
</pre>
</div>
</div>
</div>

<div id="outline-container-sec-2-29" class="outline-3">
<h3 id="sec-2-29">35</h3>
<div class="outline-text-3" id="text-2-29">
<p>
Let M be an n*m  integer matrix in which the entries of each row are
sorted in increasing order (from left to right) and the entries in
each column are in increasing order (from top to bottom). Give an
efficient algorithm to find the position of an integer x in M, or to
determine that x is not there. How many comparisons of x with matrix
entries does your algorithm use in worst case?
</p>

<p>
O(m+n)
</p>

<div class="org-src-container">

<pre class="src src-c++"><span style="color: #98fb98;">bool</span> <span style="color: #87cefa;">FindElement</span>(<span style="color: #98fb98;">int</span> **<span style="color: #eedd82;">array</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">x</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">n</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">m</span>, <span style="color: #98fb98;">int</span> *<span style="color: #eedd82;">pos_x</span>, <span style="color: #98fb98;">int</span> *<span style="color: #eedd82;">pos_y</span>) {
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">row</span> = 0, <span style="color: #eedd82;">col</span> = m - 1;
  <span style="color: #00ffff;">while</span> (row &lt; n &amp;&amp; col &gt;= 0) {
    <span style="color: #00ffff;">if</span> (array[row][col] == x) {
      *pos_x = row;
      *pos_y = col;
      <span style="color: #00ffff;">return</span> <span style="color: #7fffd4;">true</span>;
    } <span style="color: #00ffff;">else</span> <span style="color: #00ffff;">if</span> (array[row][col] &gt; x) {
      col--;
    } <span style="color: #00ffff;">else</span> {
      row++;
    }
  }
  <span style="color: #00ffff;">return</span> <span style="color: #7fffd4;">true</span>;
}
</pre>
</div>
</div>
</div>

<div id="outline-container-sec-2-30" class="outline-3">
<h3 id="sec-2-30">36</h3>
<div class="outline-text-3" id="text-2-30">
<p>
Consider an n*n  array A containing integer elements (positive, negative,
and zero). Assume that the elements in each row of A are in strictly
increasing order, and the elements of each column of A are in strictly
decreasing order. (Hence there cannot be two zeroes in the same row or
the same column.) Describe an efficient algorithm that counts the
number of occurrences of the element 0 in A. Analyze its running time.
</p>

<div class="org-src-container">

<pre class="src src-c++"><span style="color: #98fb98;">int</span> <span style="color: #87cefa;">CountZero</span>(<span style="color: #98fb98;">int</span> **<span style="color: #eedd82;">array</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">n</span>) {
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">row</span> = n - 1, <span style="color: #eedd82;">col</span> = n - 1;
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">count</span> = 0;
  <span style="color: #00ffff;">while</span> (row &gt;=0 &amp;&amp; col &gt;= 0) {
    <span style="color: #00ffff;">if</span> (array[row][col] == 0) {
      count++;
      row--;
    } <span style="color: #00ffff;">else</span> <span style="color: #00ffff;">if</span>(array[row][col] &gt; 0) {
      col--;
    } <span style="color: #00ffff;">else</span> {
      row--;
    }
  }
  <span style="color: #00ffff;">return</span> count;
}
</pre>
</div>
</div>
</div>
<div id="outline-container-sec-2-31" class="outline-3">
<h3 id="sec-2-31">40</h3>
<div class="outline-text-3" id="text-2-31">
<p>
If you are given a million integers to sort, what algorithm would you
use to sort them? How much time and memory would that consume?
</p>

<ol class="org-ol">
<li>一个整数４字节，10<sup>9</sup>*4=4G,需要 4G 的内存，可以用快排等 O(nlogn)的排序算法．
</li>
<li>用 bitmap,需要 10<sup>9</sup>/8=128M 的内存.
</li>
<li>若内存有限,就 external merge sort,利用外部存储多进行几次.
</li>
</ol>
</div>
</div>

<div id="outline-container-sec-2-32" class="outline-3">
<h3 id="sec-2-32">41</h3>
<div class="outline-text-3" id="text-2-32">
<p>
Describe advantages and disadvantages of the most popular sorting
algorithms.
</p>

<p>
<b>Merge sort:</b>
</p>
<ul class="org-ul">
<li>优点:适合链表,适合外排.
</li>
<li>缺点:需要多余的内存来保存合并的数据.
</li>
</ul>

<p>
<b>Insertion/Selection sort:</b>
</p>
<ul class="org-ul">
<li>优点:简单实现.
</li>
<li>缺点:太慢,当数据很大时,运行不实际.
</li>
</ul>

<p>
<b>Heap sort:</b>
</p>
<ul class="org-ul">
<li>优点:不需要递归,适合大数据.
</li>
<li>缺点:时常慢于 merge sort 和 quick sort.
</li>
</ul>

<p>
<b>Quick sort:</b>
</p>
<ul class="org-ul">
<li>优点:很快.
</li>
<li>缺点:递归,最坏情况比较慢.
</li>
</ul>
</div>
</div>
<div id="outline-container-sec-2-33" class="outline-3">
<h3 id="sec-2-33">42</h3>
<div class="outline-text-3" id="text-2-33">
<p>
Implement an algorithm that takes an input array and returns only the
unique elements in it.
</p>

<p>
排序,然后扫描输出.O(nlogn).
</p>
</div>
</div>
<div id="outline-container-sec-2-34" class="outline-3">
<h3 id="sec-2-34">43</h3>
<div class="outline-text-3" id="text-2-34">
<p>
You have a computer with only 2Mb of main memory. How do you use it to
sort a large file of 500 Mb that is on disk?
</p>

<p>
利用<a href="http://en.wikipedia.org/wiki/External_sorting">external merge sort</a>.
</p>
</div>
</div>

<div id="outline-container-sec-2-35" class="outline-3">
<h3 id="sec-2-35">44</h3>
<div class="outline-text-3" id="text-2-35">
<p>
Design a stack that supports push, pop, and retrieving the minimum
element in constant time. Can you do this?
</p>

<p>
只有一个 stack 办不到.如果两个 stack,可以利用另外一个 stack 存储最小值.
</p>
</div>
</div>

<div id="outline-container-sec-2-36" class="outline-3">
<h3 id="sec-2-36">45</h3>
<div class="outline-text-3" id="text-2-36">
<p>
Given a search string of three words, find the smallest snippet of the
document that contains all three of the search words&#x2014;i.e., the
snippet with smallest number of words in it. You are given the index
positions where these words occur in the document, such as word1: (1,
4, 5), word2: (3, 9, 10), and word3: (2, 6, 15). Each of the lists are
in sorted order, as above.
</p>

<ol class="org-ol">
<li>选取每个字母 index 的首个元素作为起始方案。
</li>
<li>如何改进它的长度：a.增加最小的位置，b.减小最大的位置，这里只能增加最小的位置。
</li>
<li>用 heap 来保存位置，每次取出最小的位置为 O(logk).
</li>
</ol>

<p>
复杂度：O(nlogk)，n 是所有字母的位置个数，k 是字母个数。这里 k=3,所以 O(n)
</p>

<div class="org-src-container">

<pre class="src src-c++"><span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;queue&gt;</span>
<span style="color: #00ffff;">using</span> <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">priority_queue</span>;
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;utility&gt;</span>
<span style="color: #00ffff;">using</span> <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">make_pair</span>;
<span style="color: #00ffff;">using</span> <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">pair</span>;
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;vector&gt;</span>
<span style="color: #00ffff;">using</span> <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">vector</span>;
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;algorithm&gt;</span>
<span style="color: #00ffff;">using</span> <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">max</span>;
<span style="color: #00ffff;">using</span> <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">min</span>;
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;limits&gt;</span>
<span style="color: #00ffff;">using</span> <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">numeric_limits</span>;


<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">FindSmallestSnippet</span>(<span style="color: #98fb98;">vector</span>&lt;<span style="color: #98fb98;">vector</span>&lt;<span style="color: #98fb98;">int</span>&gt; &gt; &amp;<span style="color: #eedd82;">index_positions</span>) {
  <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">max-priority, select smallest position, use -index_positions[i][j], (i,j)</span>
  <span style="color: #98fb98;">priority_queue</span>&lt;<span style="color: #98fb98;">pair</span>&lt;<span style="color: #98fb98;">int</span>, <span style="color: #98fb98;">pair</span>&lt;<span style="color: #98fb98;">int</span> ,<span style="color: #98fb98;">int</span>&gt; &gt; &gt; <span style="color: #eedd82;">queue</span>;
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">max_pos</span> = 0; <span style="color: #ff7f24;">// </span><span style="color: #ff7f24;">the max pos of  the snippet</span>
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span>;
  <span style="color: #00ffff;">for</span> (i = 0; i &lt; index_positions.size(); ++i) {
    <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">pos</span> = index_positions[i][0];
    max_pos = max(max_pos, pos);
    queue.push(make_pair(-pos, make_pair(i, 0)));
  }
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">smallest_len</span> = <span style="color: #7fffd4;">numeric_limits</span>&lt;<span style="color: #98fb98;">int</span>&gt;::max();
  <span style="color: #00ffff;">while</span> (queue.size() == index_positions.size()) {
    <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">min_pos</span> = -queue.top().first;
    smallest_len = min(smallest_len, max_pos - min_pos + 1);
    <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">word_pos</span> = queue.top().second.first;
    <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">index</span> = queue.top().second.second;
    queue.pop();
    ++index;
    <span style="color: #00ffff;">if</span> (index &lt; index_positions[word_pos].size()) {
      <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">next_pos</span> = index_positions[word_pos][index];
      max_pos = max(max_pos, next_pos);
      queue.push(make_pair(-next_pos, make_pair(word_pos, index)));
    }
  }
  <span style="color: #00ffff;">return</span> smallest_len;
}
</pre>
</div>
</div>
</div>

<div id="outline-container-sec-2-37" class="outline-3">
<h3 id="sec-2-37">46</h3>
<div class="outline-text-3" id="text-2-37">
<p>
You are given 12 coins. One of them is heavier or lighter than the
rest. Identify this coin in just three weighings.
</p>

<ol class="org-ol">
<li>分 3 组,每组 4 个,其中两组称重,若相等,重的在第三组.若不等,重的在重的那一组.
</li>
<li>重的那组分 4 组,每组 1 个,第一组和第二组称重,谁重就重的那个.
</li>
<li>若 step2 相等,剩下第三组和第四组称重,谁重就重的那个.
</li>
</ol>
</div>
</div>
</div>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Algorithm Design Manual Chapter 3]]></title>
    <link href="http://dreamrunner.org/blog/2014/06/04/The-Algorithm-Design-Manual3/"/>
    <updated>2014-06-04T00:00:00+08:00</updated>
    <id>http://dreamrunner.org/blog/2014/06/04/The-Algorithm-Design-Manual3</id>
    <content type="html"><![CDATA[<div id="outline-container-sec-1" class="outline-2">
<h2 id="sec-1">Book Notes</h2>
<div class="outline-text-2" id="text-1">
</div><div id="outline-container-sec-1-1" class="outline-3">
<h3 id="sec-1-1">Contiguous vs. Linked Data Structures</h3>
<div class="outline-text-3" id="text-1-1">
<ul class="org-ul">
<li>Contiguously-allocated structuresare composed of single slabs of
memory, and include arrays, matrices, heaps, and hash tables.
</li>
<li>Linked data structuresare composed of distinct chunks of memory
bound together bypointers, and include lists, trees, and graph
adjacency lists.
</li>
</ul>

<!-- more -->
</div>
</div>
<div id="outline-container-sec-1-2" class="outline-3">
<h3 id="sec-1-2">Arrays</h3>
<div class="outline-text-3" id="text-1-2">
<p>
Advantages of contiguously-allocated arrays include:
</p>
<ul class="org-ul">
<li>Constant-time access given the index– Because the index of each
element maps directly to a particular memory address, we can access
arbitrary data items instantly provided we know the index.
</li>
<li>Space efficiency– Arrays consist purely of data, so no space is
wasted with links or other formatting information. Further,
end-of-record information is not needed because arrays are built
from fixed-size records.
</li>
<li>Memory locality– A common programming idiom involves iterating
through all the elements of a data structure. Arrays are good for
this because they exhibit excellent memory locality. Physical
continuity between successive data accesses helps exploit the
high-speedcache memory on modern computer architectures.
</li>
</ul>

<p>
The downside of arrays is that we cannot adjust their size in the middle of
a program’s execution.
</p>

<p>
Actually, we can efficiently enlarge arrays as we need them, through the miracle
of dynamic arrays. The apparent waste in this procedure involves the recopying of the old contents
on each expansion. Thus, each of thenelements move only two times on average, and the total work
of managing the dynamic array is the sameO(n) as it would have been if a single
array of sufficient size had been allocated in advance! The primary thing lost using dynamic arrays is the guarantee that each array
access takes constant time <i>in the worst case</i>.
</p>
</div>
</div>

<div id="outline-container-sec-1-3" class="outline-3">
<h3 id="sec-1-3">Pointers and Linked Structures</h3>
<div class="outline-text-3" id="text-1-3">
<p>
The relative advantages of linked lists over static arrays include:
</p>
<ul class="org-ul">
<li>Overflow on linked structures can never occur unless the memory is
actually full.
</li>
<li>Insertions and deletions aresimplerthan for contiguous (array)
lists.
</li>
<li>With large records, moving pointers is easier and faster than moving
the items themselves.
</li>
</ul>

<p>
while the relative advantages of arrays include:
</p>
<ul class="org-ul">
<li>Linked structures require extra space for storing pointer fields.
</li>
<li>Linked lists do not allow efficient random access to items.
</li>
<li>Arrays allow better memory locality and cache performance than
random pointer jumping.
</li>
</ul>
</div>
</div>
</div>

<div id="outline-container-sec-2" class="outline-2">
<h2 id="sec-2">Exercises</h2>
<div class="outline-text-2" id="text-2">
</div><div id="outline-container-sec-2-1" class="outline-3">
<h3 id="sec-2-1">1</h3>
<div class="outline-text-3" id="text-2-1">
<p>
A common problem for compilers and text editors is determining whether the
parentheses in a string are balanced and properly nested. For example, the string
((())())() contains properly nested pairs of parentheses, which the strings )()( and
()) do not. Give an algorithm that returns true if a string contains properly nested
and balanced parentheses, and false if otherwise. For full credit, identify the position
of the first offending parenthesis if the string is not properly
nested and balanced.
</p>

<div class="org-src-container">

<pre class="src src-c++"><span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;string&gt;</span>
<span style="color: #00ffff;">using</span> <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">string</span>;
<span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;stack&gt;</span>
<span style="color: #00ffff;">using</span> <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">stack</span>;

<span style="color: #98fb98;">bool</span> <span style="color: #87cefa;">BalancedParentheses</span>(<span style="color: #98fb98;">string</span> <span style="color: #eedd82;">parentheses</span>, <span style="color: #98fb98;">int</span> *<span style="color: #eedd82;">pos</span>) {
  <span style="color: #98fb98;">stack</span>&lt;<span style="color: #98fb98;">int</span>&gt; <span style="color: #eedd82;">stk</span>;
  <span style="color: #00ffff;">const</span> <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">kLeftPar</span> = 1;
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span>;
  <span style="color: #00ffff;">for</span> (i = 0; i &lt; parentheses.size(); ++i) {
    <span style="color: #00ffff;">if</span> (parentheses[i] == <span style="color: #ffa07a;">'('</span>) {
      stk.push(kLeftPar);
    } <span style="color: #00ffff;">else</span> {
      <span style="color: #00ffff;">if</span> (stk.empty()) {
        *pos = i;
        <span style="color: #00ffff;">return</span> <span style="color: #7fffd4;">false</span>;
      }
      stk.pop();
    }
  }
  <span style="color: #00ffff;">if</span> (!stk.empty()) {
    *pos = --i;
    <span style="color: #00ffff;">return</span> <span style="color: #7fffd4;">false</span>;
  }
  <span style="color: #00ffff;">return</span> <span style="color: #7fffd4;">true</span>;
}
</pre>
</div>
</div>
</div>

<div id="outline-container-sec-2-2" class="outline-3">
<h3 id="sec-2-2">2</h3>
<div class="outline-text-3" id="text-2-2">
<p>
Write a program to reverse the direction of a given singly-linked list. In other
words, after the reversal all pointers should now point backwards. Your algorithm
should take linear time.
</p>

<div class="org-src-container">

<pre class="src src-c++"><span style="color: #00ffff;">struct</span> <span style="color: #98fb98;">Node</span> {
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">value</span>;
  <span style="color: #00ffff;">struct</span> <span style="color: #98fb98;">Node</span> *<span style="color: #eedd82;">next</span>;
  <span style="color: #87cefa;">Node</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">in_value</span>, <span style="color: #00ffff;">struct</span> <span style="color: #98fb98;">Node</span>* <span style="color: #eedd82;">in_next</span>) : value(in_value), <span style="color: #98fb98;">next</span>(<span style="color: #eedd82;">in_next</span>) {
  }
};

<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">ReverseLinkedList</span>(<span style="color: #98fb98;">Node</span> **<span style="color: #eedd82;">head</span>) {
  <span style="color: #00ffff;">if</span> (!head || *head == <span style="color: #7fffd4;">NULL</span>) {
    <span style="color: #00ffff;">return</span>;
  }
  <span style="color: #98fb98;">Node</span> *<span style="color: #eedd82;">prev</span>, *<span style="color: #eedd82;">p</span>, *<span style="color: #eedd82;">next</span>;
  prev = *head;
  p = prev-&gt;next;
  prev-&gt;next = <span style="color: #7fffd4;">NULL</span>;
  <span style="color: #00ffff;">while</span> (p != <span style="color: #7fffd4;">NULL</span>) {
    next = p-&gt;next;
    p-&gt;next = prev;
    prev = p;
    p = next;
  }
  *head = prev;
}
</pre>
</div>
</div>
</div>
<div id="outline-container-sec-2-3" class="outline-3">
<h3 id="sec-2-3">3</h3>
<div class="outline-text-3" id="text-2-3">
<p>
We have seen how dynamic arrays enable arrays to grow while still achieving
constant-time amortized performance. This problem concerns extending dynamic
arrays to let them both grow and shrink on demand.
</p>

<p>
(a) Consider an underflow strategy that cuts the array size in half whenever the
array falls below half full. Give an example sequence of insertions and deletions
where this strategy gives a bad amortized cost.
</p>

<p>
(b) Then, give a better underflow strategy than that suggested above, one that
achieves constant amortized cost per deletion.
</p>

<ol class="org-ol">
<li>容量是 6 的数组，当有 3 个元素是，insertion，然后 delete。它不断收缩和扩展容量。
</li>
<li>当元素个数是总个数的 1/4 时，把容量收缩成 1/2。
</li>
</ol>
</div>
</div>
<div id="outline-container-sec-2-4" class="outline-3">
<h3 id="sec-2-4">4</h3>
<div class="outline-text-3" id="text-2-4">
<p>
Design a dictionary data structure in which search, insertion, and deletion can
all be processed inO(1) time in the worst case. You may assume the set elements
are integers drawn from a finite set 1,2, .., n, and initialization
can take O(n)time.
</p>

<p>
因为元素个数是有限集合中的数，用 bit array 表示每个数。
</p>
</div>
</div>

<div id="outline-container-sec-2-5" class="outline-3">
<h3 id="sec-2-5">5</h3>
<div class="outline-text-3" id="text-2-5">
<p>
Find the overhead fraction (the ratio of data space over total space) for each
of the following binary tree implementations on n nodes:
</p>

<p>
(a) All nodes store data, two child pointers, and a parent pointer. The data field
requires four bytes and each pointer requires four bytes.
</p>

<p>
(b) Only leaf nodes store data; internal nodes store two child pointers. The data
field requires four bytes and each pointer requires two bytes.
</p>

<ol class="org-ol">
<li>所有点都一样： 4/(4+4*3) = 1/4
</li>
<li>满树中，若页节点个数是 n，那么内部节点个数是 n-1,
4*n/(4*n + 4*(n-1)) = n/(2n-1)
</li>
</ol>
</div>
</div>
<div id="outline-container-sec-2-6" class="outline-3">
<h3 id="sec-2-6">6</h3>
<div class="outline-text-3" id="text-2-6">
<p>
Describe how to modify any balanced tree data structure such that search,
insert, delete, minimum, and maximum still take O(logn) time each, but successor
and predecessor now take O(1) time each. Which operations have to be modified
to support this?
</p>

<p>
在树节点中添加指向 successor 和 predecessor 的指针。不影响操作 search,
minimum, 和 maximum。只需在 insert 和 delete 操作相应更新指向 successor 和 predecessor 的指针。
</p>
</div>
</div>
<div id="outline-container-sec-2-7" class="outline-3">
<h3 id="sec-2-7">7</h3>
<div class="outline-text-3" id="text-2-7">
<p>
Suppose you have access to a balanced dictionary data structure, which
supports each of the operations search, insert, delete, minimum,
maximum, successor, and predecessor in O(logn) time. Explain how to
modify the insert and delete operations so they still take O(logn) but
now minimum and maximum take O(1) time. (Hint: think in terms of using
the abstract dictionary operations, instead of mucking about with
pointers and the like.)
</p>

<p>
存储 max 和 min 这两个数。
</p>
<ul class="org-ul">
<li>insert 时，新元素与这个两数对比并相应更新。
</li>
<li>delete 时，若是 min 元素被 delete，用它的 successor 更新；若是 max 元素被
delete，用它的 predecessor 更新。
</li>
</ul>
</div>
</div>
<div id="outline-container-sec-2-8" class="outline-3">
<h3 id="sec-2-8">8</h3>
<div class="outline-text-3" id="text-2-8">
<p>
Design a data structure to support the following operations:
</p>
<ul class="org-ul">
<li>insert(x,T) – Insert item x into the set T.
</li>
<li>delete(k,T) – Delete the kth smallest element from T.
</li>
<li>member(x,T) – Return true iff x∈T.
</li>
</ul>
<p>
All operations must take O(logn) time on an n-element set.
</p>

<p>
Balanced binary tree.
</p>
</div>
</div>
<div id="outline-container-sec-2-9" class="outline-3">
<h3 id="sec-2-9">9</h3>
<div class="outline-text-3" id="text-2-9">
<p>
A concatenate operation takes two sets S1 and S2, where every key in S1
is smaller than any key in S2, and merges them together. Give an
algorithm to concatenate two binary search trees into one binary
search tree. The worst-case running time should be O(h), where h is the
maximal height of the two trees.
</p>

<p>
S1 中的所有元素小于 S2,用 O（logn）的时间找出 S2 的最小元素，然后 S1 成为它的左子树，S2 成为它的右子树，组成新的搜索树。
</p>
</div>
</div>
<div id="outline-container-sec-2-10" class="outline-3">
<h3 id="sec-2-10">10</h3>
<div class="outline-text-3" id="text-2-10">
<p>
In the bin-packing problem, we are given n metal objects, each weighing
between zero and one kilogram. Our goal is to find the smallest number
of bins that will hold the n objects, with each bin holding one
kilogram at most.
</p>

<ul class="org-ul">
<li>The best-fit heuristicfor bin packing is as follows. Consider the
objects in the order in which they are given. For each object, place
it into the partially filled bin with the smallest amount of extra
room after the object is inserted.. If no such bin exists, start a new
bin. Design an algorithm that implements the best-fit heuristic
(taking as input the n weights w1,w2, &#x2026;, wn and outputting the
number of bins used) in O(nlogn)time.
</li>

<li>Repeat the above using the worst-fit heuristic, where we put the next
object in the partially filled bin with the largest amount of extra
room after the object is inserted.
</li>
</ul>

<p>
使用 BST。主要找到能容纳这个元素的最小 bin，若所有 bin 都小于这个元素大小，就插入一个新的。
</p>
<div class="org-src-container">

<pre class="src src-c++">min_node = <span style="color: #7fffd4;">NULL</span>;
<span style="color: #00ffff;">while</span> node != <span style="color: #7fffd4;">NULL</span>:
    <span style="color: #00ffff;">if</span> (node-&gt;weight &gt;= w &amp;&amp; node-&gt;left &lt; w) {
      min_node = node;
      <span style="color: #00ffff;">break</span>;
    } <span style="color: #00ffff;">else</span> <span style="color: #00ffff;">if</span> (node-&gt;left &gt;= w) {
      node = node-&gt;left;
    } <span style="color: #00ffff;">else</span> {
      node = node-&gt;right;
    }
<span style="color: #00ffff;">if</span> (min_node == <span style="color: #7fffd4;">NULL</span>) {
  bst-&gt;insert(<span style="color: #00ffff;">new</span> <span style="color: #98fb98;">node</span>(w));
} <span style="color: #00ffff;">else</span> {
  bst-&gt;<span style="color: #00ffff;">delete</span>(min_node);
  min_node-&gt;weight -= w;
  bst-&gt;insert(min_node);
}
</pre>
</div>

<p>
最大堆使用。每次选最大容量的 bin。若最大 bin 小于这个元素大小，就插入一个新的。
</p>
</div>
</div>

<div id="outline-container-sec-2-11" class="outline-3">
<h3 id="sec-2-11">11</h3>
<div class="outline-text-3" id="text-2-11">
<p>
Suppose that we are given a sequence of n values x1,x2, &#x2026;, xn and seek
to quickly answer repeated queries of the form: given i and j, find the
smallest value in xi,&#x2026;,xj.
</p>

<p>
(a) Design a data structure that uses O(n<sup>2</sup>) space and answers queries in O(1)
time.
</p>

<p>
(b) Design a data structure that uses O(n) space and answers queries
in O(logn) time. For partial credit, your data structure can
use O(nlogn) space and have O(logn) query time.
</p>

<ol class="org-ol">
<li>n*n 的矩阵，i,j 中存的就是 i-j 的最小元素。
</li>

<li>使用<a href="http://en.wikipedia.org/wiki/Cartesian_tree">Cartesian tree</a>或<a href="http://en.wikipedia.org/wiki/Treap">Treap</a>。
</li>
</ol>
</div>
</div>
<div id="outline-container-sec-2-12" class="outline-3">
<h3 id="sec-2-12">12</h3>
<div class="outline-text-3" id="text-2-12">
<p>
Suppose you are given an input set S of n numbers, and a black box
that if given any sequence of real numbers and an integer k instantly
and correctly answers whether there is a subset of input sequence
whose sum is exactly k. Show how to use the black box O(n) times to
find a subset of S that adds up to k.
</p>

<div class="org-src-container">

<pre class="src src-c++">R = S
<span style="color: #00ffff;">for</span> i = 1 to n:
  <span style="color: #00ffff;">if</span> bb(R/{si}) <span style="color: #98fb98;">is</span> <span style="color: #eedd82;">True</span>:
      R = R / {si}
</pre>
</div>
</div>
</div>
<div id="outline-container-sec-2-13" class="outline-3">
<h3 id="sec-2-13">13</h3>
<div class="outline-text-3" id="text-2-13">
<p>
Let A[1..n] be an array of real numbers. Design an algorithm to perform
any sequence of the following operations:
</p>

<p>
• Add(i,y)– Add the value y to the ith number.
</p>

<p>
• Partial-sum(i)– Return the sum of the first i numbers
</p>

<p>
There are no insertions or deletions; the only change is to the values
of the numbers. Each operation should take O(logn) steps. You may use
one additional array of size n as a work space.
</p>

<p>
建立叶节点数ｎ的 balanced binary tree，ｎ个叶节点依次存储 A[1..n]，书的内节点存储子树的和。
</p>
<ol class="org-ol">
<li>Add(i,y)，比较ｉ与 n/2，决定左子树还是右子树，依次遍历到叶节点，并增加相应子树和，最后找到第ｉ个元素相加。
</li>
<li>Partial-sum(i)，比较ｉ与 n/2，决定左子树还是右子树，每当遍历右子树，加上左子树的和，最后到叶节点，得到总的和。
</li>
</ol>
</div>
</div>
<div id="outline-container-sec-2-14" class="outline-3">
<h3 id="sec-2-14">14</h3>
<div class="outline-text-3" id="text-2-14">
<p>
Extend the data structure of the previous problem to support insertions and
deletions. Each element now has both a key and a value. An element is accessed
by its key. The addition operation is applied to the values, but the
elements are accessed by its key. The Partial sum operation is
different.
</p>

<ul class="org-ul">
<li>Add(k,y)– Add the value y to the item with key k.
</li>
<li>Insert(k,y)– Insert a new item with key k and value y.
</li>
<li>Delete(k)– Delete the item with key k.
</li>
<li>Partial-sum(k)– Return the sum of all the elements currently in the
set whose key is less than y,
</li>
</ul>

<p>
The worst case running time should still be O(nlogn) for any sequence
of O(n) operations.
</p>

<p>
建立以 key 排序的平衡搜索二叉树，并每个节点中添加一个左子树和的值。
</p>

<ul class="org-ul">
<li>Add(k,y)：随着搜索 key k，依次加左子树和，最后 key k 加上 y。
</li>
<li>Insert(k,y)：随着搜索 key k 插入位置，依次加左子树和，最后插入 key k 的元素。
</li>
<li>Delete(k)：：随着搜索 key k，依次减少左子树和，最后删除 key k 元素。
</li>
<li>Partial-sum(k)：随着搜索 key k，依次加上左子树的和（因为左边的元素是小于的元素）。
</li>
</ul>
</div>
</div>
<div id="outline-container-sec-2-15" class="outline-3">
<h3 id="sec-2-15">15</h3>
<div class="outline-text-3" id="text-2-15">
<p>
Design a data structure that allows one to search, insert, and delete
an integer X in O(1) time (i.e. , constant time, independent of the
total number of integers stored). Assume that 1≤X≤n and that there
are m+n units of space available, where m is the maximum number of
integers that can be in the table at any one time. (Hint: use two
arrays A[1..n] and B[1..m].) You are not allowed to initialize
either A or B, as that would take O(m) or O(n) operations. This means
the arrays are full of random garbage to begin with, so you must be
very careful.
</p>

<p>
与<a href="http://dreamrunner.org/blog/2014/05/10/column1/">Programming Pearls</a>的 Column 课后题一样。
</p>

<p>
建立两个数组 A[1..n]，B[1..m]和一个表示元素个数的变量 k。
</p>

<ol class="org-ol">
<li>insert X: k = k + 1，A[X] = k, B[k] = X;
</li>
<li>search X: return (A[X] &lt;= k) &amp;&amp; B[A[X]] == X;
</li>
<li>delete X: 把 A[X]与末端 A[B[k]]交换，A[B[k]] = A[X], B[A[X]] = B[k];
k = k - 1;
</li>
</ol>
</div>
</div>
<div id="outline-container-sec-2-16" class="outline-3">
<h3 id="sec-2-16">18</h3>
<div class="outline-text-3" id="text-2-16">
<p>
What method would you use to look up a word in a dictionary?
</p>

<p>
Hash Table.
</p>
</div>
</div>

<div id="outline-container-sec-2-17" class="outline-3">
<h3 id="sec-2-17">19</h3>
<div class="outline-text-3" id="text-2-17">
<p>
Imagine you have a closet full of shirts. What can you do to organize
your shirts for easy retrieval?
</p>

<p>
以颜色排序，并二分搜索查找。
</p>
</div>
</div>
<div id="outline-container-sec-2-18" class="outline-3">
<h3 id="sec-2-18">20</h3>
<div class="outline-text-3" id="text-2-18">
<p>
Write a function to find the middle node of a singly-linked list.
</p>

<div class="org-src-container">

<pre class="src src-c++"><span style="color: #00ffff;">struct</span> <span style="color: #98fb98;">Node</span> {
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">value</span>;
  <span style="color: #98fb98;">Node</span> *<span style="color: #eedd82;">next</span>;
};

<span style="color: #98fb98;">Node</span>* <span style="color: #87cefa;">FindMidNode</span>(<span style="color: #98fb98;">Node</span> *<span style="color: #eedd82;">head</span>) {
  <span style="color: #98fb98;">Node</span> *<span style="color: #eedd82;">p</span>, *<span style="color: #eedd82;">q</span>;
  p = head;
  q = head;
  i = 0;
  <span style="color: #00ffff;">while</span> (p != <span style="color: #7fffd4;">NULL</span>) {
    i++;
    p = p-&gt;next;
    <span style="color: #00ffff;">if</span> (i == 2) {
      q = q-&gt;next;
      i = 0;
    }
  }
  <span style="color: #00ffff;">return</span> q;
}
</pre>
</div>
</div>
</div>

<div id="outline-container-sec-2-19" class="outline-3">
<h3 id="sec-2-19">21</h3>
<div class="outline-text-3" id="text-2-19">
<p>
Write a function to compare whether two binary trees are identical.
Identical trees have the same key value at each position and the same
structure.
</p>

<div class="org-src-container">

<pre class="src src-c++"><span style="color: #00ffff;">struct</span> <span style="color: #98fb98;">Node</span> {
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">value</span>;
  <span style="color: #98fb98;">Node</span> *<span style="color: #eedd82;">left</span>;
  <span style="color: #98fb98;">Node</span> *<span style="color: #eedd82;">right</span>;
};

<span style="color: #98fb98;">bool</span> <span style="color: #87cefa;">CompareBinaryTree</span>(<span style="color: #98fb98;">Node</span> *<span style="color: #eedd82;">head_m</span>, <span style="color: #98fb98;">Node</span> *<span style="color: #eedd82;">head_n</span>) {
  <span style="color: #00ffff;">if</span> (head_m == <span style="color: #7fffd4;">NULL</span> &amp;&amp; head_n == <span style="color: #7fffd4;">NULL</span>) {
    <span style="color: #00ffff;">return</span> <span style="color: #7fffd4;">true</span>;
  }
  <span style="color: #00ffff;">if</span> (head_m == <span style="color: #7fffd4;">NULL</span> || head_n == <span style="color: #7fffd4;">NULL</span>) {
    <span style="color: #00ffff;">return</span> <span style="color: #7fffd4;">false</span>;
  }
  <span style="color: #00ffff;">return</span> (head_m-&gt;value == head_n-&gt;value) &amp;&amp;
      CompareBinaryTree(head_m-&gt;left, head_n-&gt;left) &amp;&amp;
      CompareBinaryTree(head_m-&gt;right, head_n-&gt;right);
}
</pre>
</div>
</div>
</div>
<div id="outline-container-sec-2-20" class="outline-3">
<h3 id="sec-2-20">22</h3>
<div class="outline-text-3" id="text-2-20">
<p>
Write a program to convert a binary search tree into a linked list
</p>

<div class="org-src-container">

<pre class="src src-c++"><span style="color: #00ffff;">struct</span> <span style="color: #98fb98;">Node</span> {
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">value</span>;
  <span style="color: #98fb98;">Node</span> *<span style="color: #eedd82;">next</span>;
};

<span style="color: #00ffff;">struct</span> <span style="color: #98fb98;">TNode</span> {
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">value</span>;
  <span style="color: #98fb98;">TNode</span> *<span style="color: #eedd82;">left</span>;
  <span style="color: #98fb98;">TNode</span> *<span style="color: #eedd82;">right</span>;
  <span style="color: #87cefa;">TNode</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">value_in</span>) {
    value = value_in;
    left = <span style="color: #7fffd4;">NULL</span>;
    right = <span style="color: #7fffd4;">NULL</span>;
  }
};

<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">InsertToList</span>(<span style="color: #98fb98;">Node</span> **<span style="color: #eedd82;">head</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">value</span>) {
  <span style="color: #98fb98;">Node</span> *<span style="color: #eedd82;">new_node</span> = <span style="color: #00ffff;">new</span> <span style="color: #98fb98;">Node</span>;
  new_node-&gt;value = value;
  new_node-&gt;next = *head;
  *head = new_node;
}

<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">ConvertTreeToList</span>(<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">TNode</span> *<span style="color: #eedd82;">root</span>, <span style="color: #98fb98;">Node</span> **<span style="color: #eedd82;">head</span>) {
  <span style="color: #00ffff;">if</span> (root == <span style="color: #7fffd4;">NULL</span>) {
    <span style="color: #00ffff;">return</span>;
  }
  ConvertTreeToList(root-&gt;right, head);
  InsertToList(head, root-&gt;value);
  ConvertTreeToList(root-&gt;left, head);
}
</pre>
</div>
</div>
</div>

<div id="outline-container-sec-2-21" class="outline-3">
<h3 id="sec-2-21">23</h3>
<div class="outline-text-3" id="text-2-21">
<p>
Implement an algorithm to reverse a linked list. Now do it without
recursion.
</p>

<div class="org-src-container">

<pre class="src src-c++"><span style="color: #98fb98;">void</span> <span style="color: #87cefa;">ReverseLinkedList</span>(<span style="color: #98fb98;">Node</span> **<span style="color: #eedd82;">head</span>) {
  <span style="color: #00ffff;">if</span> (!head || *head == <span style="color: #7fffd4;">NULL</span>) {
    <span style="color: #00ffff;">return</span>;
  }
  <span style="color: #98fb98;">Node</span> *<span style="color: #eedd82;">prev</span>, *<span style="color: #eedd82;">p</span>, *<span style="color: #eedd82;">next</span>;
  prev = *head;
  p = prev-&gt;next;
  prev-&gt;next = <span style="color: #7fffd4;">NULL</span>;
  <span style="color: #00ffff;">while</span> (p != <span style="color: #7fffd4;">NULL</span>) {
    next = p-&gt;next;
    p-&gt;next = prev;
    prev = p;
    p = next;
  }
  *head = prev;
}
</pre>
</div>
</div>
</div>

<div id="outline-container-sec-2-22" class="outline-3">
<h3 id="sec-2-22">24</h3>
<div class="outline-text-3" id="text-2-22">
<p>
What is the best data structure for maintaining URLs that have been visited by
a Web crawler? Give an algorithm to test whether a given URL has already been
visited, optimizing both space and time.
</p>

<p>
Hash Table.
</p>
</div>
</div>
<div id="outline-container-sec-2-23" class="outline-3">
<h3 id="sec-2-23">26</h3>
<div class="outline-text-3" id="text-2-23">
<p>
Reverse the words in a sentence—i.e., “My name is Chris” becomes “Chris is
name My.” Optimize for time and space.
</p>

<ol class="org-ol">
<li>reverse 每个单词;
</li>
<li>reverse 整句。
</li>
</ol>

<div class="org-src-container">

<pre class="src src-c++"><span style="color: #98fb98;">void</span> <span style="color: #87cefa;">Reverse</span>(<span style="color: #98fb98;">char</span> *<span style="color: #eedd82;">begin</span>, <span style="color: #98fb98;">char</span> *<span style="color: #eedd82;">end</span>) {
  <span style="color: #98fb98;">char</span> <span style="color: #eedd82;">temp</span>;
  <span style="color: #00ffff;">while</span> (begin &lt; end) {
    temp = *begin;
    *begin = *end;
    *end = temp;
    begin++;
    end--;
  }
}

<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">ReverseWords</span>(<span style="color: #98fb98;">char</span> *<span style="color: #eedd82;">str</span>) {
  <span style="color: #98fb98;">char</span> *<span style="color: #eedd82;">word_begin</span>;
  word_begin = <span style="color: #7fffd4;">NULL</span>;
  <span style="color: #98fb98;">char</span> *<span style="color: #eedd82;">p</span>;
  p = str;
  <span style="color: #00ffff;">while</span> (*p != <span style="color: #ffa07a;">'\0'</span>) {
    <span style="color: #00ffff;">if</span> (word_begin == <span style="color: #7fffd4;">NULL</span> &amp;&amp; *p != <span style="color: #ffa07a;">' '</span>) {
      word_begin = p;
    }
    <span style="color: #00ffff;">if</span> (word_begin != <span style="color: #7fffd4;">NULL</span> &amp;&amp; (*(p+1) == <span style="color: #ffa07a;">' '</span> || *(p+1) == <span style="color: #ffa07a;">'\0'</span>)) {
      Reverse(word_begin, p);
      word_begin = <span style="color: #7fffd4;">NULL</span>;
    }
    ++p;
  }
  Reverse(str, p - 1);
}
</pre>
</div>
</div>
</div>
<div id="outline-container-sec-2-24" class="outline-3">
<h3 id="sec-2-24">27</h3>
<div class="outline-text-3" id="text-2-24">
<p>
Determine whether a linked list contains a loop as quickly as possible
without using any extra storage. Also, identify the location of the
loop.
</p>

<p>
利用两个指针，一个快指针和一个慢指针，快的每次都比慢的多前进一个节点，如果存在 loop,快的总会与慢的相重叠。
</p>

<p>
loop 的起始点：
</p>
<ol class="org-ol">
<li>当快的与慢的指针相重叠时，验证有 loop，之后慢的指针不动，通过快的指针计算出 loop 的长度
</li>
<li>重新从链表头开始，快指针比慢指针先前进 loop 的长度距离，提增慢和快指针，直到第一次相遇，相遇点就是 loop 的起始点。
</li>
</ol>
</div>
</div>
<div id="outline-container-sec-2-25" class="outline-3">
<h3 id="sec-2-25">28</h3>
<div class="outline-text-3" id="text-2-25">
<p>
You have an unordered array X of n integers. Find the array M containing
n elements where Mi is the product of all integers in X except for Xi. You may
not use division. You can use extra memory. (Hint: There are solutions
faster than O(n<sup>2</sup>).)
</p>

<p>
对数组 X 扫描 2 次计算出如下 2 组数组：
</p>

$$
\begin{align}
P_{0} = 1; P_{k}=X_{k}P_{k-1}=\prod_{i=1}^{k}X_{i} \newline
Q_{n+1} = 1; Q_{k}=X_{k}Q_{k+1}=\prod_{i=k}^{n}X_{i}
\end{align}
$$


<p>
所以得到 M：
</p>

$$
\begin{align}
M_{i} = P_{i-1} Q_{i+1}, i\in[1,n]
\end{align}
$$
</div>
</div>
<div id="outline-container-sec-2-26" class="outline-3">
<h3 id="sec-2-26">29</h3>
<div class="outline-text-3" id="text-2-26">
<p>
Give an algorithm for finding an ordered word pair (e.g., “New
York”) occurring with the greatest frequency in a given webpage.
Which data structures would you use? Optimize both time and space.
</p>

<p>
Hash Table.
</p>
</div>
</div>
</div>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[The Last Thing D Needs总结]]></title>
    <link href="http://dreamrunner.org/blog/2014/06/01/the-last-thing-d-needszong-jie/"/>
    <updated>2014-06-01T16:24:47+08:00</updated>
    <id>http://dreamrunner.org/blog/2014/06/01/the-last-thing-d-needszong-jie</id>
    <content type="html"><![CDATA[<ul id="markdown-toc">
  <li><a href="#initialization">Initialization</a></li>
  <li><a href="#type-deduction">Type Deduction</a></li>
  <li><a href="#inheritance">Inheritance</a></li>
  <li><a href="#computational-complexity">Computational Complexity</a></li>
  <li><a href="#apis">APIs</a></li>
  <li><a href="#specifications">Specifications</a></li>
  <li><a href="#essential-and-accidental-complexity">Essential and Accidental Complexity</a></li>
</ul>

<p><a href="http://www.amazon.com/gp/product/0321334876?ie=UTF8&amp;tag=aristeia.com-20&amp;linkCode=as2&amp;camp=1789&amp;creative=9325&amp;creativeASIN=0321334876">Effective C++</a>
系列的作者 <a href="http://www.aristeia.com/">Scott Meyers</a> 在 Dconf 中 <a href="http://www.ustream.tv/recorded/47947981">The Last Thing D Needs</a> 聊了些 C++的特性，稍微总结一下。</p>

<h2 id="initialization">Initialization</h2>

<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span>Initialization</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
<span class="line-number">5</span>
<span class="line-number">6</span>
<span class="line-number">7</span>
<span class="line-number">8</span>
<span class="line-number">9</span>
<span class="line-number">10</span>
<span class="line-number">11</span>
</pre></td><td class="code"><pre><code class="c++"><span class="line"><span class="kt">int</span> <span class="n">x1</span><span class="p">;</span>         <span class="c1">// unknown, initial(pay for it)</span>
</span><span class="line"><span class="kt">int</span> <span class="n">x2</span><span class="p">;</span>         <span class="c1">// (at global scope) 0, no run time cost</span>
</span><span class="line"><span class="k">static</span> <span class="kt">int</span> <span class="n">x3</span><span class="p">;</span>  <span class="c1">// 0, static initialization</span>
</span><span class="line"><span class="kt">int</span> <span class="o">*</span><span class="n">px</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">int</span><span class="p">;</span>  <span class="c1">// heap memory, unknown, has run time cost</span>
</span><span class="line"><span class="p">{</span>
</span><span class="line">    <span class="kt">int</span> <span class="n">x4</span><span class="p">;</span>    <span class="c1">// unknown, has run time cost </span>
</span><span class="line"><span class="p">}</span>
</span><span class="line"><span class="kt">int</span> <span class="n">a1</span><span class="p">[</span><span class="mi">100</span><span class="p">];</span>   <span class="c1">// unknown</span>
</span><span class="line"><span class="kt">int</span> <span class="n">a2</span><span class="p">[</span><span class="mi">100</span><span class="p">];</span>   <span class="c1">// (at global scope) 0</span>
</span><span class="line"><span class="k">static</span> <span class="kt">int</span> <span class="n">a3</span><span class="p">[</span><span class="mi">100</span><span class="p">];</span>  <span class="c1">// 0</span>
</span><span class="line"><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">v</span><span class="p">(</span><span class="mi">100</span><span class="p">);</span>  <span class="c1">// 0, use run time cost</span>
</span></code></pre></td></tr></table></div></figure></notextile></div>

<!-- more -->

<h2 id="type-deduction">Type Deduction</h2>
<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span>Type Deduction</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
<span class="line-number">5</span>
<span class="line-number">6</span>
<span class="line-number">7</span>
<span class="line-number">8</span>
<span class="line-number">9</span>
<span class="line-number">10</span>
<span class="line-number">11</span>
<span class="line-number">12</span>
<span class="line-number">13</span>
<span class="line-number">14</span>
<span class="line-number">15</span>
<span class="line-number">16</span>
<span class="line-number">17</span>
<span class="line-number">18</span>
<span class="line-number">19</span>
<span class="line-number">20</span>
<span class="line-number">21</span>
<span class="line-number">22</span>
<span class="line-number">23</span>
<span class="line-number">24</span>
<span class="line-number">25</span>
<span class="line-number">26</span>
<span class="line-number">27</span>
<span class="line-number">28</span>
<span class="line-number">29</span>
<span class="line-number">30</span>
<span class="line-number">31</span>
<span class="line-number">32</span>
<span class="line-number">33</span>
<span class="line-number">34</span>
<span class="line-number">35</span>
<span class="line-number">36</span>
<span class="line-number">37</span>
<span class="line-number">38</span>
<span class="line-number">39</span>
<span class="line-number">40</span>
<span class="line-number">41</span>
<span class="line-number">42</span>
<span class="line-number">43</span>
</pre></td><td class="code"><pre><code class="c++"><span class="line"><span class="k">const</span> <span class="kt">int</span> <span class="n">cx</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span><span class="line"><span class="k">auto</span> <span class="n">my_cx1</span> <span class="o">=</span> <span class="n">cx</span><span class="p">;</span>          <span class="c1">// int, new independent value</span>
</span><span class="line"><span class="n">decltype</span><span class="p">(</span><span class="n">cx</span><span class="p">)</span> <span class="n">my_cx2</span> <span class="o">=</span> <span class="n">cx</span><span class="p">;</span>  <span class="c1">// const int, standard said</span>
</span><span class="line">
</span><span class="line"><span class="k">template</span><span class="o">&lt;</span><span class="n">typname</span> <span class="n">T</span><span class="o">&gt;</span>
</span><span class="line"><span class="kt">void</span> <span class="n">f1</span><span class="p">(</span><span class="n">T</span> <span class="n">param</span><span class="p">);</span>
</span><span class="line"><span class="n">f1</span><span class="p">(</span><span class="n">cx</span><span class="p">);</span>                    <span class="c1">// T&#39;s type, int, same rules with auto</span>
</span><span class="line">
</span><span class="line"><span class="k">template</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">&gt;</span>
</span><span class="line"><span class="kt">void</span> <span class="n">f2</span><span class="p">(</span><span class="n">T</span><span class="o">&amp;</span> <span class="n">param</span><span class="p">);</span>
</span><span class="line"><span class="n">f2</span><span class="p">(</span><span class="n">cx</span><span class="p">);</span>                   <span class="c1">//T&#39;s type, const int, reference a chunk of memory, preserve the const</span>
</span><span class="line">
</span><span class="line"><span class="k">template</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">&gt;</span>
</span><span class="line"><span class="kt">void</span> <span class="n">f3</span><span class="p">(</span><span class="n">T</span><span class="o">&amp;&amp;</span> <span class="n">param</span><span class="p">);</span>
</span><span class="line"><span class="n">f3</span><span class="p">(</span><span class="n">cx</span><span class="p">);</span>                  <span class="c1">//T&#39;s type, const int&amp;, perfect argument forwarding, a special rule</span>
</span><span class="line">
</span><span class="line"><span class="k">const</span> <span class="kt">int</span> <span class="n">cx</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span><span class="line"><span class="k">auto</span> <span class="n">lam</span><span class="o">=</span> <span class="p">[</span><span class="n">cx</span><span class="p">]</span> <span class="p">{</span><span class="n">cx</span> <span class="o">=</span> <span class="mi">10</span><span class="p">;};</span>       <span class="c1">//error!</span>
</span><span class="line"><span class="k">class</span> <span class="nc">UpToTheCompiler</span> <span class="p">{</span>
</span><span class="line"><span class="k">private</span><span class="o">:</span>
</span><span class="line">  <span class="o">???</span> <span class="n">cx</span><span class="p">;</span>                      <span class="c1">//const int</span>
</span><span class="line">  <span class="p">...</span>
</span><span class="line"><span class="p">};</span>
</span><span class="line">
</span><span class="line"><span class="k">const</span> <span class="kt">int</span> <span class="n">cx</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span><span class="line"><span class="k">auto</span> <span class="n">lam</span><span class="o">=</span> <span class="p">[</span><span class="n">cx</span> <span class="o">=</span> <span class="n">cx</span><span class="p">]</span> <span class="p">{</span><span class="n">cx</span> <span class="o">=</span> <span class="mi">10</span><span class="p">;};</span>     <span class="c1">//error!</span>
</span><span class="line"><span class="k">class</span> <span class="nc">UpToTheCompiler</span> <span class="p">{</span>
</span><span class="line"><span class="k">private</span><span class="o">:</span>
</span><span class="line">  <span class="o">???</span> <span class="n">cx</span><span class="p">;</span>                          <span class="c1">//int (but acts like const int)</span>
</span><span class="line">  <span class="p">...</span>
</span><span class="line"><span class="k">public</span><span class="o">:</span>
</span><span class="line">  <span class="kt">void</span> <span class="k">operator</span><span class="p">()</span> <span class="k">const</span>
</span><span class="line">  <span class="p">{</span><span class="n">cx</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;}</span>
</span><span class="line"><span class="p">};</span>
</span><span class="line">
</span><span class="line"><span class="k">const</span> <span class="kt">int</span> <span class="n">cx</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span><span class="line"><span class="k">auto</span> <span class="n">lam1</span><span class="o">=</span> <span class="p">[</span><span class="n">cx</span> <span class="o">=</span> <span class="n">cx</span><span class="p">]</span> <span class="k">mutable</span> <span class="p">{</span><span class="n">cx</span> <span class="o">=</span> <span class="mi">10</span><span class="p">;};</span>     <span class="c1">//error!</span>
</span><span class="line"><span class="k">auto</span> <span class="n">lam2</span><span class="o">=</span> <span class="p">[</span><span class="n">cx</span> <span class="o">=</span> <span class="n">cx</span><span class="p">]()</span> <span class="k">mutable</span> <span class="p">{</span><span class="n">cx</span> <span class="o">=</span> <span class="mi">10</span><span class="p">;};</span>     <span class="c1">//correct</span>
</span><span class="line"><span class="k">class</span> <span class="nc">UpToTheCompiler</span> <span class="p">{</span>
</span><span class="line"><span class="k">private</span><span class="o">:</span>
</span><span class="line">  <span class="o">???</span> <span class="n">cx</span><span class="p">;</span>                          <span class="c1">//int (but acts like int)</span>
</span><span class="line">  <span class="p">...</span>
</span><span class="line"><span class="p">};</span>
</span></code></pre></td></tr></table></div></figure></notextile></div>

<p>For</p>

<div class="bogus-wrapper"><notextile><figure class="code"><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
</pre></td><td class="code"><pre><code class=""><span class="line">const int cx = 0;</span></code></pre></td></tr></table></div></figure></notextile></div>

<p>type deduction for cx yields:</p>

<style>
table,th,td
{
border:1px solid black;
}
</style>

<table border="1" style="width:500px">
<tr>
<th> Context </th>
<th> Type </th>
</tr>

<tr>
<td> auto </td>
<td> int </td>
</tr>

<tr>
<td> decltype </td>
<td>  const int</td>
</tr>

<tr>
<td> template(T parameter)  </td>
<td> int </td>
</tr>

<tr>
<td> template(T&amp; parameter)  </td>
<td> const int </td>
</tr>

<tr>
<td> template(T&amp;&amp; parameter)  </td>
<td> const int&amp; </td>
</tr>

<tr>
<td> lambda (by-value capture) </td>
<td> const int  </td>
</tr>

<tr>
<td> lambda (int capture) </td>
<td>  int</td>
</tr>
</table>

<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span>Type Deduction</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
<span class="line-number">5</span>
<span class="line-number">6</span>
<span class="line-number">7</span>
<span class="line-number">8</span>
<span class="line-number">9</span>
<span class="line-number">10</span>
<span class="line-number">11</span>
<span class="line-number">12</span>
<span class="line-number">13</span>
<span class="line-number">14</span>
</pre></td><td class="code"><pre><code class="c++"><span class="line"><span class="c1">//all do the same thing</span>
</span><span class="line"><span class="kt">int</span> <span class="n">x1</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span><span class="line"><span class="kt">int</span> <span class="n">x2</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
</span><span class="line"><span class="kt">int</span> <span class="n">x3</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span>
</span><span class="line"><span class="kt">int</span> <span class="n">x4</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span>
</span><span class="line">
</span><span class="line"><span class="k">auto</span> <span class="n">x1</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>  <span class="c1">// int</span>
</span><span class="line"><span class="k">auto</span> <span class="n">x2</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>   <span class="c1">// int</span>
</span><span class="line"><span class="k">auto</span> <span class="n">x3</span> <span class="o">=</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span><span class="c1">// initializer_list&lt;int&gt;</span>
</span><span class="line"><span class="k">auto</span> <span class="n">x4</span> <span class="p">{</span><span class="mi">0</span><span class="p">};</span>  <span class="c1">// initializer_list&lt;int&gt;</span>
</span><span class="line">
</span><span class="line"><span class="k">template</span> <span class="o">&lt;</span><span class="n">typname</span> <span class="n">T</span><span class="o">&gt;</span>
</span><span class="line"><span class="kt">void</span> <span class="n">f</span><span class="p">(</span><span class="n">T</span> <span class="n">param</span><span class="p">);</span>
</span><span class="line"><span class="n">f</span><span class="p">({</span><span class="mi">0</span><span class="p">});</span>       <span class="c1">// error! &quot;{0}&quot; has no type</span>
</span></code></pre></td></tr></table></div></figure></notextile></div>

<h2 id="inheritance">Inheritance</h2>
<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span>inheritance</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
<span class="line-number">5</span>
<span class="line-number">6</span>
<span class="line-number">7</span>
<span class="line-number">8</span>
<span class="line-number">9</span>
<span class="line-number">10</span>
<span class="line-number">11</span>
<span class="line-number">12</span>
<span class="line-number">13</span>
<span class="line-number">14</span>
<span class="line-number">15</span>
<span class="line-number">16</span>
<span class="line-number">17</span>
<span class="line-number">18</span>
<span class="line-number">19</span>
<span class="line-number">20</span>
<span class="line-number">21</span>
<span class="line-number">22</span>
<span class="line-number">23</span>
<span class="line-number">24</span>
<span class="line-number">25</span>
<span class="line-number">26</span>
<span class="line-number">27</span>
<span class="line-number">28</span>
<span class="line-number">29</span>
</pre></td><td class="code"><pre><code class="c++"><span class="line"><span class="k">class</span> <span class="nc">Base</span> <span class="p">{</span>
</span><span class="line"><span class="k">public</span><span class="o">:</span>
</span><span class="line">  <span class="kt">void</span> <span class="n">doBaseWork</span><span class="p">();</span>
</span><span class="line"><span class="p">};</span>
</span><span class="line"><span class="k">class</span> <span class="nc">Derived</span> <span class="o">:</span> <span class="k">public</span> <span class="n">Base</span> <span class="p">{</span>
</span><span class="line"><span class="k">public</span><span class="o">:</span>
</span><span class="line">  <span class="kt">void</span> <span class="n">doDerivedWord</span><span class="p">()</span> <span class="p">{</span>
</span><span class="line">    <span class="n">doBaseWord</span><span class="p">();</span>               <span class="c1">//ok</span>
</span><span class="line">  <span class="p">}</span>
</span><span class="line"><span class="p">};</span>
</span><span class="line">
</span><span class="line"><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">&gt;</span>
</span><span class="line"><span class="k">class</span> <span class="nc">Base</span> <span class="p">{</span>
</span><span class="line"><span class="k">public</span><span class="o">:</span>
</span><span class="line">  <span class="kt">void</span> <span class="n">doBaseWork</span><span class="p">();</span>
</span><span class="line"><span class="p">};</span>
</span><span class="line"><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">&gt;</span>
</span><span class="line"><span class="k">class</span> <span class="nc">Derived</span> <span class="o">:</span> <span class="k">public</span> <span class="n">Base</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class="line"><span class="k">public</span><span class="o">:</span>
</span><span class="line">  <span class="kt">void</span> <span class="n">doDerivedWord</span><span class="p">()</span> <span class="p">{</span>
</span><span class="line">    <span class="n">doBaseWord</span><span class="p">();</span>               <span class="c1">//no compile, later specialized version</span>
</span><span class="line">  <span class="p">}</span>
</span><span class="line"><span class="p">};</span>
</span><span class="line">
</span><span class="line"><span class="k">template</span> <span class="o">&lt;&gt;</span>
</span><span class="line"><span class="k">class</span> <span class="nc">Base</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="p">();</span>  <span class="c1">// no doBasework</span>
</span><span class="line">
</span><span class="line"><span class="n">Derived</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">d</span><span class="p">;</span>
</span><span class="line"><span class="n">d</span><span class="p">.</span><span class="n">doDerivedWord</span><span class="p">();</span>  <span class="c1">// fail</span>
</span></code></pre></td></tr></table></div></figure></notextile></div>

<p>In essence, the <strong>One Definition Rule</strong> states that the same entity should have the exact same definition throughout an application, otherwise the effects are undefined.</p>

<p>The fundamental problem is that the code that doesn’t see the specialized version of your class template member function might still compile, is likely to link, and sometimes might even run. This is because in the absence of (a forward declaration of) the explicit specialization, the non-specialized version kicks in, likely implementing a generic functionality that works for your specialized type as well.</p>

<h2 id="computational-complexity">Computational Complexity</h2>
<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span>computational Complexity</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
<span class="line-number">5</span>
<span class="line-number">6</span>
<span class="line-number">7</span>
<span class="line-number">8</span>
<span class="line-number">9</span>
<span class="line-number">10</span>
<span class="line-number">11</span>
<span class="line-number">12</span>
<span class="line-number">13</span>
</pre></td><td class="code"><pre><code class="c++"><span class="line"><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">v</span><span class="p">;</span>
</span><span class="line"><span class="p">...</span>
</span><span class="line"><span class="n">std</span><span class="o">::</span><span class="n">sort</span><span class="p">(</span><span class="n">v</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">v</span><span class="p">.</span><span class="n">end</span><span class="p">());</span>   <span class="c1">// O(nlogn)</span>
</span><span class="line">
</span><span class="line"><span class="n">std</span><span class="o">::</span><span class="n">list</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">li</span><span class="p">;</span>
</span><span class="line"><span class="p">...</span>
</span><span class="line"><span class="n">std</span><span class="o">::</span><span class="n">sort</span><span class="p">(</span><span class="n">li</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">li</span><span class="p">.</span><span class="n">end</span><span class="p">());</span>  <span class="c1">// not compile, list doesnot have random access iterator</span>
</span><span class="line">
</span><span class="line"><span class="k">auto</span> <span class="n">it1</span> <span class="o">=</span>
</span><span class="line"><span class="n">std</span><span class="o">::</span><span class="n">binary_search</span><span class="p">(</span><span class="n">v</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">v</span><span class="p">.</span><span class="n">end</span><span class="p">(),</span> <span class="mi">10</span><span class="p">);</span>  <span class="c1">// O(logn)</span>
</span><span class="line">
</span><span class="line"><span class="k">auto</span> <span class="n">it2</span> <span class="o">=</span>
</span><span class="line"><span class="n">std</span><span class="o">::</span><span class="n">binary_search</span><span class="p">(</span><span class="n">li</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">li</span><span class="p">.</span><span class="n">end</span><span class="p">(),</span> <span class="mi">10</span><span class="p">);</span>  <span class="c1">// O(n), officially(number of compares): O(logn)</span>
</span></code></pre></td></tr></table></div></figure></notextile></div>

<h2 id="apis">APIs</h2>

<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span>example</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
</pre></td><td class="code"><pre><code class="c++"><span class="line"><span class="n">std</span><span class="o">::</span><span class="n">set</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">si</span><span class="p">;</span>
</span><span class="line"><span class="p">...</span>
</span><span class="line"><span class="n">si</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span><span class="mi">14</span><span class="p">);</span>    <span class="c1">// eliminate all 14s from si</span>
</span></code></pre></td></tr></table></div></figure></notextile></div>

<ul>
  <li>set             –&gt;  erase</li>
  <li>multiset        –&gt;     erase</li>
  <li>map             –&gt;     erase</li>
  <li>multimap        –&gt;     erase</li>
  <li>unordered_set   –&gt;     erase</li>
  <li>unordered_multiset –&gt;  erase</li>
  <li>unordered_map      –&gt;  erase</li>
  <li>unordered_multimap –&gt;  erase</li>
  <li>list               –&gt;  remove</li>
  <li>forward_list       –&gt;  remove</li>
</ul>

<p>Sorts can be stable or unstable. Which are guaranteed to be stable?
* sort –&gt; not guaranteed
* stable_sort  –&gt; guaranteed
* list::sort –&gt; guaranteed</p>

<h2 id="specifications">Specifications</h2>
<p>Five sequence containers:</p>

<ul>
  <li>array –&gt; No</li>
  <li>deque –&gt; Yes</li>
  <li>forward_list  –&gt; No(fulfill of 1 of 16)</li>
  <li>list  –&gt; Yes</li>
  <li>vector – &gt; Yes</li>
</ul>

<h2 id="essential-and-accidental-complexity">Essential and Accidental Complexity</h2>
<p>Essential Complexity: due to inherent design tensions.</p>

<ul>
  <li>Simplicity and regularity vs expressiveness.</li>
  <li>Abstraction and portability vs efficiency.</li>
  <li>New approaches vs compatibility with legacy systems.</li>
  <li>Expressiveness vs ability to issue good diagnostics.</li>
</ul>

<p><em>Essential Complexity</em></p>

<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span>Point</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
</pre></td><td class="code"><pre><code class="c++"><span class="line"><span class="k">struct</span> <span class="n">Point</span> <span class="p">{</span>
</span><span class="line">  <span class="kt">int</span> <span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">;</span>
</span><span class="line"><span class="p">};</span>
</span></code></pre></td></tr></table></div></figure></notextile></div>
<p>What is the type of Point::x?</p>

<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span>Point</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
</pre></td><td class="code"><pre><code class="c++"><span class="line"><span class="n">Point</span> <span class="n">p</span><span class="p">;</span>
</span><span class="line"><span class="k">const</span> <span class="n">Point</span> <span class="o">&amp;</span><span class="n">cp</span> <span class="o">=</span> <span class="n">p</span><span class="p">;</span>
</span></code></pre></td></tr></table></div></figure></notextile></div>
<p>What is the type of cp.x?</p>

<p>C++ soluction:</p>

<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
</pre></td><td class="code"><pre><code class="c++"><span class="line"><span class="n">decltype</span><span class="p">(</span><span class="n">cp</span><span class="p">.</span><span class="n">x</span><span class="p">)</span> <span class="o">=</span> <span class="kt">int</span>
</span><span class="line"><span class="n">decltype</span><span class="p">((</span><span class="n">cp</span><span class="p">.</span><span class="n">x</span><span class="p">))</span> <span class="o">=</span> <span class="k">const</span> <span class="kt">int</span><span class="o">&amp;</span>
</span></code></pre></td></tr></table></div></figure></notextile></div>

<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span>inheritance</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
<span class="line-number">5</span>
<span class="line-number">6</span>
<span class="line-number">7</span>
<span class="line-number">8</span>
<span class="line-number">9</span>
<span class="line-number">10</span>
<span class="line-number">11</span>
<span class="line-number">12</span>
</pre></td><td class="code"><pre><code class="c++"><span class="line"><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">&gt;</span>
</span><span class="line"><span class="k">class</span> <span class="nc">Base</span> <span class="p">{</span>
</span><span class="line"><span class="k">public</span><span class="o">:</span>
</span><span class="line">  <span class="kt">void</span> <span class="n">doBaseWork</span><span class="p">();</span>
</span><span class="line"><span class="p">};</span>
</span><span class="line"><span class="k">template</span> <span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">&gt;</span>
</span><span class="line"><span class="k">class</span> <span class="nc">Derived</span> <span class="o">:</span> <span class="k">public</span> <span class="n">Base</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span> <span class="p">{</span>
</span><span class="line"><span class="k">public</span><span class="o">:</span>
</span><span class="line">  <span class="kt">void</span> <span class="n">doDerivedWord</span><span class="p">()</span> <span class="p">{</span>
</span><span class="line">    <span class="n">doBaseWrd</span><span class="p">();</span>               <span class="c1">//okay?</span>
</span><span class="line">  <span class="p">}</span>
</span><span class="line"><span class="p">};</span>
</span></code></pre></td></tr></table></div></figure></notextile></div>

<p>Assume typo and diagnose now?</p>

<ul>
  <li>Wrong if later specialization offers doBaseWrk.</li>
</ul>

<p>Assume later specialization and defer lookup until instantiation?</p>

<ul>
  <li>If typo, imposes diagnostics for library errors on clients.</li>
</ul>

<p>C++ solution:</p>

<ul>
  <li>Template author has control
    <ul>
      <li>doBaseWrk() -&gt; lookup name when parsing template.</li>
      <li>this-&gt;doBaseWrk() -&gt; lookup name when instantiating template.</li>
    </ul>
  </li>
</ul>

<p><em>Accidental Complexity</em></p>

<ul>
  <li>ints are sometimes initialized to 0.</li>
  <li>By-value lambda capture somtimes retains the constness of what’s captured.</li>
  <li>mutable lambdas must declare a parameter list, but non-mutable lambdas don’t</li>
  <li>Braced initializers (e.g.”{0}”) sometimes have a type.</li>
  <li>Computation complexity guarantees usually meaningful.</li>
  <li>Elimination all container elements with a given value usually means
calling <code>erase</code>.</li>
  <li><code>sort</code> is sometimes stable.</li>
  <li>Container “requirements” are sometimes required.</li>
</ul>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Algorithm Design Manual Chapter 2]]></title>
    <link href="http://dreamrunner.org/blog/2014/05/29/The-Algorithm-Design-Manual2/"/>
    <updated>2014-05-29T00:00:00+08:00</updated>
    <id>http://dreamrunner.org/blog/2014/05/29/The-Algorithm-Design-Manual2</id>
    <content type="html"><![CDATA[<div id="outline-container-sec-1" class="outline-2">
<h2 id="sec-1">Book Notes</h2>
<div class="outline-text-2" id="text-1">
<p>
Our two most important tools are (1) the RAM model of
computation and (2) the asymptotic analysis of worst-case complexity.
</p>

<!-- more -->
</div>
</div>

<div id="outline-container-sec-2" class="outline-2">
<h2 id="sec-2">Exercises</h2>
<div class="outline-text-2" id="text-2">
</div><div id="outline-container-sec-2-1" class="outline-3">
<h3 id="sec-2-1">1</h3>
<div class="outline-text-3" id="text-2-1">
<p>
What value is returned by the following function? Express your answer
as a function of n. Give the worst-case running time using the Big Oh
notation.
</p>

<div class="org-src-container">

<pre class="src src-sh"><span style="color: #00ffff;">function</span> <span style="color: #87cefa;">mystery</span>(n)
      <span style="color: #b0c4de;">r</span>:=0
      <span style="color: #00ffff;">for</span> i:=1 to n-1 do
          <span style="color: #00ffff;">for</span> j:=i+1 to n do
              <span style="color: #00ffff;">for</span> k:=1 to j do
                  <span style="color: #b0c4de;">r</span>:=r+1
       <span style="color: #00ffff;">return</span>(<span style="color: #b0c4de;">r</span>)
</pre>
</div>

$$
\begin{align}
\sum_{i=1}^{n-1}\sum_{j=i+1}^{n}\sum_{k=1}^{j}1 = 
\sum_{i=1}^{n-1}\sum_{j=i+1}^{n}j =
\sum_{i=1}^{n-1}(\sum_{j=1}^{n}j - \sum_{j=1}^{i}j) = \newline 
\sum_{i=1}^{n-1}(\frac{n(n+1)}{2} - \frac{i(i+1)}{2} = 
\frac{1}{2}\sum_{i=1}^{n-1}(n^2+n-i^2-i) = \newline 
\frac{1}{2}((n-1)n^2+(n-1)n-(\frac{n(n+1)(2n+1)}{6}-n^2)-(\frac{n(n+1)}{2}-n))
\end{align}
$$

<p>
Time: O(n<sup>3</sup>)
</p>
</div>
</div>

<div id="outline-container-sec-2-2" class="outline-3">
<h3 id="sec-2-2">2</h3>
<div class="outline-text-3" id="text-2-2">
<p>
What value is returned by the following function? Express your answer as a
function of n. Give the worst-case running time using Big Oh notation.
</p>

<div class="org-src-container">

<pre class="src src-sh"><span style="color: #00ffff;">function</span> <span style="color: #87cefa;">pesky</span>(n)
      <span style="color: #b0c4de;">r</span>:=0
      <span style="color: #00ffff;">for</span> i:=1 to n do
          <span style="color: #00ffff;">for</span> j:=1 to i do
              <span style="color: #00ffff;">for</span> k:=j to i+j do
                  <span style="color: #b0c4de;">r</span>:=r+1
      <span style="color: #00ffff;">return</span>(<span style="color: #b0c4de;">r</span>)
</pre>
</div>

\begin{align}
f(n) = \frac{n(n+1)(n+2)}{3}
\end{align}


<p>
Time: O(n<sup>3</sup>).
</p>
</div>
</div>

<div id="outline-container-sec-2-3" class="outline-3">
<h3 id="sec-2-3">3</h3>
<div class="outline-text-3" id="text-2-3">
<p>
What value is returned by the following function? Express your answer as a
function of n. Give the worst-case running time using Big Oh notation.
</p>

<div class="org-src-container">

<pre class="src src-sh"><span style="color: #00ffff;">function</span> <span style="color: #87cefa;">prestiferous</span>(n)
       <span style="color: #b0c4de;">r</span>:=0
       <span style="color: #00ffff;">for</span> i:=1 to n do
           <span style="color: #00ffff;">for</span> j:=1 to i do
               <span style="color: #00ffff;">for</span> k:=j to i+j do
                   <span style="color: #00ffff;">for</span> l:=1 to i+j-k do
                       <span style="color: #b0c4de;">r</span>:=r+1
       <span style="color: #00ffff;">return</span>(<span style="color: #b0c4de;">r</span>)
</pre>
</div>


\begin{align}
f(n) = \frac{n(n+1)(n+2)}{3}
\end{align}


<p>
Time: O(n<sup>4</sup>).
</p>
</div>
</div>

<div id="outline-container-sec-2-4" class="outline-3">
<h3 id="sec-2-4">19</h3>
<div class="outline-text-3" id="text-2-4">
\begin{align}
(1/3)^n &lt; 6 &lt; loglogn &lt; logn = lnn &lt; (logn)^2 &lt; n^\frac{1}{3}+logn &lt; \sqrt{n}
 \newline 
 &lt; \frac{n}{logn} &lt; n &lt; nlogn &lt; n^2 = n^2+logn &lt; n^3 &lt; n-n^3+7n^5 &lt; (3/2)^2 
 \newline 
= 2^n &lt; n!
\end{align}
</div>
</div>
<div id="outline-container-sec-2-5" class="outline-3">
<h3 id="sec-2-5">34</h3>
<div class="outline-text-3" id="text-2-5">
<p>
Assume that Christmas hasndays. Exactly how many presents did my “true
love” send me? (Do some research if you do not understand this
question.)
</p>

<p>
假设一共有ｎ天，每 i 天收到的礼物数是： 
</p>

\begin{align}
p_i = \sum_{k=1}^{i}k
\end{align}


<p>
总的礼物数：
</p>

\begin{align}
\sum_{i=1}^{n} p_i = \sum_{i=1}^{n}\sum_{k=1}^{i}k=\frac{n^3+3n^2+2n}{6}
\end{align}
</div>
</div>
<div id="outline-container-sec-2-6" class="outline-3">
<h3 id="sec-2-6">43</h3>
<div class="outline-text-3" id="text-2-6">
<p>
You are given a set S of n numbers. You must pick a subset S&#8217; of k
numbers from S such that the probability of each element of S
occurring in S&#8217; is equal (i.e., each is selected with probability k /
n). You may make only one pass over the numbers. What if n is unknown?
</p>

<p>
<a href="http://wiki.dreamrunner.org/public_html/Algorithms/Theory%20of%20Algorithms/Reservoir%20Sampling.html">Reservoir sampling issue</a>.
</p>
</div>
</div>

<div id="outline-container-sec-2-7" class="outline-3">
<h3 id="sec-2-7">44</h3>
<div class="outline-text-3" id="text-2-7">
<p>
We have 1,000 data items to store on 1,000 nodes. Each node can store
copies of exactly three different items. Propose a replication scheme
to minimize data loss as nodes fail. What is the expected number of
data entries that get lost when three random nodes fail?
</p>

<p>
不考虑 RAID 的 XOR 做法这里。
</p>

<p>
1000 个数据做 3 份拷贝，如何做 3 份拷贝呢？
</p>

<ol class="org-ol">
<li>随机的 3 个点失败只损失一个数据
</li>
</ol>
<p>
3 份拷贝以相邻一格的方式存储，如下
</p>
<div class="org-src-container">

<pre class="src src-sh">nodes:    1       2        3   ...   1000
copy1:   data1    data2    data3 ..  data1000
copy2:   data1000 data1    data2 ..  data999
copy3:   data999  data1000 data1 ..  data998
</pre>
</div>

随机选取 3 个点的组合个数： $\binom{1000}{3}$ 
其中丢失数据点的组合个数： 1000, 每种组合丢失一个数据所以丢失数据期望 $1000 / \binom{1000}{3} = 6.01804e-06$ 

<ol class="org-ol">
<li>随机的 3 个点失败损失 3 个数据
</li>
</ol>
<p>
每 3 个点共享 3 个拷贝点，如下
</p>
<div class="org-src-container">

<pre class="src src-sh">nodes:    1       2        3   ...   1000
copy1:   data1    data2    data3 ..  data1000
copy2:   data3    data1    data2 ..  data999
copy3:   data2    data3    data1 ..  data998
</pre>
</div>

随机选取 3 个点的组合个数： $\binom{1000}{3}$ 
其中丢失数据点的组合个数： 1000/3, 每种组合丢失 3 个数据，所以丢失数据期望 $1000/3×3 / \binom{1000}{3} = 6.01804e-06$ 
</div>
</div>
<div id="outline-container-sec-2-8" class="outline-3">
<h3 id="sec-2-8">45</h3>
<div class="outline-text-3" id="text-2-8">
<p>
Consider the following algorithm to find the minimum element in an
array of numbers . One extra variable tmp is allocated to hold the
current minimum value. Start from <code>A[0]</code>; &#8220;tmp&#8221; is compared against
<code>A[1], A[2], , A[N]</code> in order. When <code>A[i] &lt; tmp, tmp = A[i]</code>. What is the
expected number of times that the assignment operation tmp = A[i] is
performed?
</p>

<p>
期望的次数是第ｎ个元素是最小值的概率的总和。ｎ个元素平均分布，任意元素是最小值的概率是 1/ｎ。
</p>

<p>
<code>E(n) = E(n-1) +1/n， E[1] = 1</code>
</p>


\begin{align}
E(n) = \sum_{i=1}^{n}\frac{1}{i} \approx lnn
\end{align}
</div>
</div>

<div id="outline-container-sec-2-9" class="outline-3">
<h3 id="sec-2-9">46</h3>
<div class="outline-text-3" id="text-2-9">
<p>
You have a 100-story building and a couple of marbles. You must
identify the lowest floor for which a marble will break if you drop it
from this floor. How fast can you find this floor if you are given an
infinite supply of marbles? What if you have only two marbles?
</p>

<ol class="org-ol">
<li>无限个玻璃球，采用二分搜索法，celing(log100) = 7. 最快 7 次。
</li>
<li>如果只有 2 个玻璃球
</li>
</ol>
<p>
n 个球时在总楼层 r 中某个楼层 x 抛，两种情况： 1.破碎，剩下的总楼层 x-1 用剩下的 n-1 个球; 2.没破碎，剩下的总楼层 r-x 用 n 个球
</p>

<p>
如此把问题分解成小问题。如下代码求得最快的次数为 14。其中一条最坏情况：
9&#x2013;&gt;22&#x2013;&gt;34&#x2013;&gt;45&#x2013;&gt;55&#x2013;&gt;64&#x2013;&gt;72&#x2013;&gt;79&#x2013;&gt;85&#x2013;&gt;90&#x2013;&gt;94&#x2013;&gt;97&#x2013;&gt;99
</p>


<div class="org-src-container">

<pre class="src src-c++"><span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">Drop Marbles</span>
<span style="color: #ff7f24;">   n: num of marbles</span>
<span style="color: #ff7f24;">   r: num of floors</span>
<span style="color: #ff7f24;">   drop_qeq: the drop sequence</span>
<span style="color: #ff7f24;">   marble_drop: minimum number of trails needed to find the critical floor in</span>
<span style="color: #ff7f24;">   worst case</span>
<span style="color: #ff7f24;">   marble_drop[n][r] = 1 + min{max(marble_drop[n-1][x-1], marble[n][r-x]) :</span>
<span style="color: #ff7f24;">   x in {1,2,...,r}}</span>
<span style="color: #ff7f24;">*/</span>
<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">DropMarbles</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">n</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">r</span>, <span style="color: #98fb98;">int</span> **<span style="color: #eedd82;">drop_seq</span>) {
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">marble_drop</span>[n+1][r+1];
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span>, <span style="color: #eedd82;">j</span>;
  <span style="color: #00ffff;">for</span> (j = 0; j &lt;= r; ++j) {
    marble_drop[1][j] = j;
  }
  <span style="color: #00ffff;">for</span> (i = 0; i &lt;= n; ++i) {
    marble_drop[i][1] = 1;
    marble_drop[i][0] = 0;
  }
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">min_sofar</span>;
  <span style="color: #00ffff;">for</span> (i = 2; i &lt;= n; ++i) {
    <span style="color: #00ffff;">for</span> (j = 2; j &lt;= r; ++j) {
      marble_drop[i][j] = <span style="color: #7fffd4;">numeric_limits</span>&lt;<span style="color: #98fb98;">int</span>&gt;::max();
      <span style="color: #00ffff;">for</span> (<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">x</span> = 1; x &lt;= j; ++x) {
        min_sofar = 1 + max(marble_drop[i-1][x-1], marble_drop[i][j-x]);
        <span style="color: #00ffff;">if</span> (min_sofar &lt; marble_drop[i][j]) {
          marble_drop[i][j] = min_sofar;
          drop_seq[i][j] = x;
        }
      }
    }
  }
  <span style="color: #00ffff;">return</span> marble_drop[n][r];
}
</pre>
</div>
</div>
</div>
<div id="outline-container-sec-2-10" class="outline-3">
<h3 id="sec-2-10">47</h3>
<div class="outline-text-3" id="text-2-10">
<p>
You are given 10 bags of gold coins. Nine bags contain coins that each
weigh 10 grams. One bag contains all false coins that weigh one gram
less. You must identify this bag in just one weighing. You have a
digital balance that reports the weight of what is placed on it.
</p>

<p>
一共 10 袋 bag1-10, 分别从 bag1 中取 1 个金币，bag2 中取 2 个金币……bag10 中取 10
个金币，称重总的重量 W。如果每个金币都是 10grams 的话，所以金币总重量是 550。N=550-W。得到缺失的重量，也是 bag 的号数，所以 bagN 中含有错误金币。
</p>
</div>
</div>
<div id="outline-container-sec-2-11" class="outline-3">
<h3 id="sec-2-11">48</h3>
<div class="outline-text-3" id="text-2-11">
<p>
You have eight balls all of the same size. Seven of them weigh the
same, and one of them weighs slightly more. How can you find the ball
that is heavier by using a balance and only two weighings?
</p>

<p>
8==&gt; 3,3,2
</p>

<ol class="org-ol">
<li>称重 3 和 3 两组
</li>
<li>若不同，选出重的一组，3==&gt; 1,1,1 称重 1 和 1,不同，那么重的就是，相同，另外个是。
</li>
<li>若相同，2==&gt;1,1，称重 1 和 1,重的就是
</li>
</ol>
</div>
</div>

<div id="outline-container-sec-2-12" class="outline-3">
<h3 id="sec-2-12">49</h3>
<div class="outline-text-3" id="text-2-12">
<p>
Suppose we start with n companies that eventually merge into one big
company. How many different ways are there for them to merge?
</p>

1. 2 个公司(a,b)时，合并只有一种方法 [ab]
2. 当有 n 个公司时，如何把它用 n-1 个公司表示，f(n)=f(n-1)g(n)
3. n 个公司第一步从中选择两个公司合并，连带合并后的新公司一共 n-1 个公司，化简到 n-1 个公司表示。
4. n 个选 2 个的组合个数是： $\binom{1000}{2}=n(n-1)/2$

<p>
所以
</p>

<p>
f(n) = &sum;<sub>i=2</sub><sup>n</sup>\frac{i(i-1)}{2} = \frac{n!(n-1)!}{2<sup>n-2</sup>}
</p>
</div>
</div>

<div id="outline-container-sec-2-13" class="outline-3">
<h3 id="sec-2-13">50</h3>
<div class="outline-text-3" id="text-2-13">
<p>
A Ramanujam number can be written two different ways as the sum of two
cubes&#x2014;i.e., there exist distinct a, b, c, and d such that a3 + b3 =
c3 + d3. Generate all Ramanujam numbers where a,b,c,d &lt; n.
</p>

<div class="org-src-container">

<pre class="src src-c++"><span style="color: #b0c4de;">#include</span> <span style="color: #ffa07a;">&lt;vector&gt;</span>
<span style="color: #00ffff;">using</span> <span style="color: #7fffd4;">std</span>::<span style="color: #98fb98;">vector</span>;

<span style="color: #98fb98;">bool</span> <span style="color: #87cefa;">FindEqual</span>(<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">vector</span>&lt;<span style="color: #98fb98;">int</span>&gt; &amp;<span style="color: #eedd82;">num_cube</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">low</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">high</span>, <span style="color: #00ffff;">const</span> <span style="color: #98fb98;">int</span> &amp;<span style="color: #eedd82;">sum</span>,
               <span style="color: #98fb98;">vector</span>&lt;<span style="color: #98fb98;">int</span>&gt; *<span style="color: #eedd82;">res</span>) {
  <span style="color: #00ffff;">if</span> (low &gt;= high) {
    <span style="color: #00ffff;">return</span> <span style="color: #7fffd4;">false</span>;
  }
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span>, <span style="color: #eedd82;">j</span>;
  i = low;
  j = high;
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">add</span>;
  <span style="color: #00ffff;">while</span> (i &lt; j) {
    add = num_cube[i] + num_cube[j];
    <span style="color: #00ffff;">if</span> (add == sum) {
      res-&gt;push_back(i);
      res-&gt;push_back(j);
      <span style="color: #00ffff;">return</span> <span style="color: #7fffd4;">true</span>;
    }
    <span style="color: #00ffff;">if</span> (add &gt; sum) {
      --j;
    } <span style="color: #00ffff;">else</span> {
      ++i;
    }
  }
  <span style="color: #00ffff;">return</span> <span style="color: #7fffd4;">false</span>;
}

<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">RamanujamNum</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">n</span>, <span style="color: #98fb98;">vector</span>&lt;<span style="color: #98fb98;">vector</span>&lt;<span style="color: #98fb98;">int</span>&gt; &gt; *<span style="color: #eedd82;">res</span>) {
  <span style="color: #98fb98;">vector</span>&lt;<span style="color: #98fb98;">int</span>&gt; <span style="color: #eedd82;">num_cube</span>(n);
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span>, <span style="color: #eedd82;">j</span>;
  <span style="color: #00ffff;">for</span> (i = 0; i &lt; n; ++i) {
    num_cube[i] = i*i*i;
  }
  <span style="color: #98fb98;">vector</span>&lt;<span style="color: #98fb98;">int</span>&gt; <span style="color: #eedd82;">ram_num</span>;
  <span style="color: #98fb98;">bool</span> <span style="color: #eedd82;">find</span>;
  <span style="color: #00ffff;">for</span> (i = 0; i &lt; n - 1; ++i) {
    <span style="color: #00ffff;">for</span> (j = i + 3; j &lt; n; ++j) {
      find = FindEqual(num_cube, i+1, j-1, num_cube[i] + num_cube[j], &amp;ram_num);
      <span style="color: #00ffff;">if</span> (find) {
        ram_num.push_back(i);
        ram_num.push_back(j);
        res-&gt;push_back(ram_num);
        ram_num.clear();
      }
    }
  }
}
</pre>
</div>
</div>
</div>
<div id="outline-container-sec-2-14" class="outline-3">
<h3 id="sec-2-14">51</h3>
<div class="outline-text-3" id="text-2-14">
<p>
Six pirates must divide $300 dollars among themselves. The division is
to proceed as follows. The senior pirate proposes a way to divide the
money. Then the pirates vote. If the senior pirate gets at least half
the votes he wins, and that division remains. If he doesn&#8217;t, he is
killed and then the next senior-most pirate gets a chance to do the
division. Now you have to tell what will happen and why (i.e., how
many pirates survive and how the division is done)? All the pirates
are intelligent and the first priority is to stay alive and the next
priority is to get as much money as possible.
</p>

<p>
从后往前推
</p>
<ul class="org-ul">
<li>2 个海盗，(1, 2) &#x2014;&gt; (0, 300)
</li>
<li>3 个海盗，(1, 2, 3) &#x2014;&gt; (1, 0, 299)
</li>
<li>4 个海盗，(1, 2, 3, 4) &#x2014;&gt; (0, 1, 0, 299)
</li>
<li>5 个海盗，(1, 2, 3, 4, 5) &#x2014;&gt; (1, 0, 1, 0, 298)
</li>
<li>6 个海盗，(1, 2, 3, 4, 5, 6) &#x2014;&gt; (0, 1, 0, 1, 298)
</li>
</ul>
</div>
</div>
<div id="outline-container-sec-2-15" class="outline-3">
<h3 id="sec-2-15">52</h3>
<div class="outline-text-3" id="text-2-15">
<p>
Reconsider the pirate problem above, where only one indivisible dollar
is to be divided. Who gets the dollar and how many are killed?
</p>

<ul class="org-ul">
<li>2: (1, 2) &#x2014;&gt; (0, 1)
</li>
<li>3: (1, 2, 3) &#x2014;&gt; （1, 0, 0)
</li>
<li>4: (1, 2, 3, 4) &#x2014;&gt; (0, 0, 1, 0)
</li>
<li>5: dead
</li>
<li>6: (1, 2, 3, 4, 5, 6) &#x2014;&gt; (0, 0, 0, 1, 0, 0)
</li>
</ul>
<p>
要至少一半的同意，间隔要有一半的人会死去才会同意之前那个人，所以之后每
2+2<sup>K</sup> (K&gt;=1)的海盗才能活。
</p>
</div>
</div>
</div>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Algorithm Design Manual Chapter 1]]></title>
    <link href="http://dreamrunner.org/blog/2014/05/26/The-Algorithm-Design-Manual1/"/>
    <updated>2014-05-26T00:00:00+08:00</updated>
    <id>http://dreamrunner.org/blog/2014/05/26/The-Algorithm-Design-Manual1</id>
    <content type="html"><![CDATA[<div id="outline-container-sec-1" class="outline-2">
<h2 id="sec-1">Book Notes</h2>
<div class="outline-text-2" id="text-1">
</div><div id="outline-container-sec-1-1" class="outline-3">
<h3 id="sec-1-1">Combinatorial Objects</h3>
<div class="outline-text-3" id="text-1-1">
<ul class="org-ul">
<li>Permutations - arrangements, or orderings, of items (&#8220;arrangement&#8221;
&#8220;tour&#8221; &#8220;ordering&#8221; or &#8220;sequence&#8221; )
</li>
<li>Subsets - selections from a set of items (&#8220;cluster&#8221; &#8220;collection&#8221;
&#8220;committee&#8221; &#8220;group&#8221; &#8220;packaging&#8221; or &#8220;selection&#8221;)
</li>
<li>Trees - hierarchical relationships between items (&#8220;hierarchy&#8221;
&#8220;dominance relationship&#8221; &#8220;ancestor/descendant relationship&#8221; or
&#8220;taxonomy&#8221;)
</li>
<li>Graphs - relationships between arbitrary pairs of objects (&#8220;network&#8221;
&#8220;circuit&#8221; &#8220;web&#8221; or &#8220;relationship&#8221;)
</li>
<li>Points - locations in some geometric space (&#8220;sites&#8221; &#8220;positions&#8221; or
&#8220;locations.)
</li>
<li>Polygons - regions in some geometric spaces (&#8220;shapes&#8221; &#8220;regions&#8221; or
&#8220;boundaries&#8221;)
</li>
<li>Strings - sequences of characters or patterns. (&#8220;text&#8221; &#8220;characters&#8221;
&#8220;patterns&#8221; or &#8220;labels&#8221;)
</li>
</ul>

<!-- more -->
</div>
</div>

<div id="outline-container-sec-1-2" class="outline-3">
<h3 id="sec-1-2">Recursive Objects</h3>
<div class="outline-text-3" id="text-1-2">
<p>
Big things that are made from smaller things of exactly the same type
as the big thing. A decomposition rule describes how to get smaller
things from big things.
</p>

<p>
As all combinatorial objects above are recursive objects here are a
few possible decompositon rules for them:
</p>

<ul class="org-ul">
<li>Permutations - Deleting the first/last element of a permutation
</li>
<li>Subsets - Deleting an element n if present
</li>
<li>Trees - Deleting the root (results in a set of subtrees), deleting a
leaf (a smaller tree)
</li>
<li>Graphs - Deleting a vertex, dividing vertices to groups
</li>
<li>Point - divide them to groups
</li>
<li>Polygons - Inserting any internal chord between two nonadjacent vertices
</li>
<li>Strings - Deleting a character (first or last)
</li>
</ul>
</div>
</div>
</div>

<div id="outline-container-sec-2" class="outline-2">
<h2 id="sec-2">Exercises</h2>
<div class="outline-text-2" id="text-2">
</div><div id="outline-container-sec-2-1" class="outline-3">
<h3 id="sec-2-1">1-28.</h3>
<div class="outline-text-3" id="text-2-1">
<p>
Write a function to perform integer division without using either
the / or * operators. Find a fast way to do it.
</p>

<div class="org-src-container">

<pre class="src src-c++"><span style="color: #98fb98;">void</span> <span style="color: #87cefa;">DivideCore</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">m</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">n</span>, <span style="color: #98fb98;">int</span> *<span style="color: #eedd82;">quot</span>, <span style="color: #98fb98;">int</span> *<span style="color: #eedd82;">rem</span>) {
  rem = m;
  quot = 0;
  <span style="color: #00ffff;">while</span> (rem &gt;= n) {
    rem -= n;
    quot++;
  }
}

<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">Divide</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">m</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">n</span>, <span style="color: #98fb98;">int</span> *<span style="color: #eedd82;">quot</span>, <span style="color: #98fb98;">int</span> *<span style="color: #eedd82;">rem</span>) {
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">mult_n</span> = 0;
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">last_n</span>;
  <span style="color: #00ffff;">while</span> (m % n == 0) {
    last_n = n;
    n = n + n;
    mult_n++;
  }
  DivideCore(m, n, quot, rem);
  <span style="color: #00ffff;">for</span> (<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span> = 0; i &lt; mult_n; ++i) {
    quot = quot + quot;
  }
}
</pre>
</div>
</div>
</div>
<div id="outline-container-sec-2-2" class="outline-3">
<h3 id="sec-2-2">1-29.</h3>
<div class="outline-text-3" id="text-2-2">
<p>
There are 25 horses. At most, 5 horses can race together at a time.
You must determine the fastest, second fastest, and third fastest
horses. Find the minimum number of races in which this can be done.
</p>

<p>
7 次。
</p>

<ol class="org-ol">
<li>5 次：25 匹分成 5 组，比赛 5 次，得到前 5 名。
</li>
<li>6 次：前 5 名比赛一次。因为只要得到前 3 名，这里剔除 5 名中的 2 名，剩下的 3
匹按比赛排名所在组为 G1，G2，G3。
</li>
<li>7 次：G3 组只能去角逐第 3 名，派第一名 G31,G2 组只能去角逐第 2,3 名，派第一，二名，G21 和 G22。G1 组 G11 已经是第一名，去角逐第 2,3 名，派 G12,G13。最后
G12,G13，G21，G22 和 G31，得到第二，三名。
</li>
</ol>
</div>
</div>
<div id="outline-container-sec-2-3" class="outline-3">
<h3 id="sec-2-3">1-30.</h3>
<div class="outline-text-3" id="text-2-3">
<p>
How many piano tuners are there in the entire world?
</p>

<p>
需要把问题分解：1.世界有多少架钢琴;2.每位钢琴调音师能调多少台钢琴。
</p>

<p>
估算世界有多少架钢琴，需要知道：
</p>
<ol class="org-ol">
<li>世界的人口。
</li>
<li>拥有钢琴的人口比例。
</li>
<li>拥有钢琴的学校，教堂等场所的数量。
</li>
</ol>

<p>
估算每位钢琴调音师能调多少台钢琴，需要知道：
</p>
<ol class="org-ol">
<li>每架钢琴平均多久需要调音一次。
</li>
<li>对钢琴调音需要多长时间。
</li>
<li>调音师的工作时间。
</li>

<li>世界人口 70 亿，70×10<sup>9</sup> 。
</li>
<li>人口中弹奏乐器的人约占 10%（肯定大于 1%,小于 100%），其中最多 10%的人弹奏钢琴，而其中拥有钢琴的比例为 2%-3%，约人口总数 2×10<sup>-3</sup> 。每
5000-10000 个人有一座教堂，每座教堂有一架钢琴，每 500-1000 个学生有一所学校，每所学校有一架钢琴，每人大约拥有 3×10<sup>-3</sup> 架钢琴，所以钢琴数
70×10<sup>9</sup> × 3×10<sup>-3</sup> = 2.1 * 10<sup>8</sup> 。
</li>
<li>钢琴调音的频率低于每月一次但多于 10 年一次，估计为一年一次。
</li>
<li>调音所需时间多余 30 分钟，少于 1 天，估计为 2 小时。或钢琴有 88 个键，如果每个键花 1 分钟，需要 1.5 小时，若需 2 分钟，则需要 3 小时。
</li>
<li>每天工作 8 小时，每周 5 天，每年工作 50 周，得出 8×5×50=2000 小时。2000 小时能调音大学 1000 架钢琴。
</li>
<li>2.1 * 10<sup>8</sup> / 1000 = 2.1 × 10<sup>5</sup> 个调音师。
</li>
</ol>
</div>
</div>
<div id="outline-container-sec-2-4" class="outline-3">
<h3 id="sec-2-4">1-31.</h3>
<div class="outline-text-3" id="text-2-4">
<p>
How many gas stations are there in the United States?
</p>

<p>
分解问题成：
</p>
<ol class="org-ol">
<li>每天大约有多少辆汽车去加油。
</li>
<li>每天一个加油站能给多少辆汽车加油。
</li>

<li>美国人口总数约 300×10<sup>6</sup> , 一家平均有 2 辆车左右，所以一共有车辆
150×10<sup>6</sup> ，每辆汽车每 5 天加油一次，一天有 30×10<sup>6</sup> 辆车去加油。
</li>
<li>一个加油站平均每小时最少为 1 辆，最多 100 多辆汽车加油，取平均 20-30 辆每小时，一个加油站工作时间大概 14 小时（7am-9am），每个加油站每天平均大约为 280 辆车加油。
</li>
<li>30×10<sup>6</sup> / 280 = 1.07 × 10<sup>5</sup> 个加油站。
</li>
</ol>
</div>
</div>
<div id="outline-container-sec-2-5" class="outline-3">
<h3 id="sec-2-5">1-32.</h3>
<div class="outline-text-3" id="text-2-5">
<p>
How much does the ice in a hockey rink weigh?
</p>

<p>
分解成：
</p>
<ol class="org-ol">
<li>冰的体积。
</li>
<li>冰的密度。
</li>
</ol>

<p>
做如下估算：
1.冰场的长度：70m;
2.冰场的宽度：30m;
3.冰的厚度：10cm=0.1;
4.冰的密度与水相当，估算 1000kg/m<sup>3</sup> .
</p>

<p>
V = 70 * 30 * 0.1 = 210 m<sup>3</sup>
W = 210 *1000 = 210，000kg
</p>
</div>
</div>
<div id="outline-container-sec-2-6" class="outline-3">
<h3 id="sec-2-6">1-33.</h3>
<div class="outline-text-3" id="text-2-6">
<p>
How many miles of road are there in the United States?
</p>

<p>
美国近似是一个矩形，高 1000mile 和长 3000mile。美国大部分地区是乡村，道路比较稀疏，平均下来可以把美国想成一个网状的道路结构，每隔 1mile 一条道路，最后如下网格，1000 条 3000mile 和 3000 条 1000mile 的路，总的 6,000,000mile 的路。
</p>
</div>
</div>
<div id="outline-container-sec-2-7" class="outline-3">
<h3 id="sec-2-7">1-34.</h3>
<div class="outline-text-3" id="text-2-7">
<p>
On average, how many times would you have to flip open the Manhattan
phone book at random in order to find a specific name?
</p>


<p>
假设电话本有 1000 页，也就是 500 个翻面。
</p>

<p>
简单答案：翻到正确页的概率是 1/500。
</p>

<p>
复杂点答案：上面没有考虑不断翻页，会翻到相同的页面。翻到错误页面的概率是 499/500，N 次后的错误概率是（499/500）<sup>N</sup> ,所以 N 次后的正确页面概率是 P=1-
（499/500）<sup>N</sup> 。
</p>

<p>
那么：
N=1  P = 0.002
N=2  P = 0.004
&#x2026;
N=1150 P = 0.89999
</p>

<p>
达到 90%的概率，所以需要 1150 翻页。
</p>
</div>
</div>
</div>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Programming Pearls Overview]]></title>
    <link href="http://dreamrunner.org/blog/2014/05/24/programming-pearls-overview/"/>
    <updated>2014-05-24T10:34:37+08:00</updated>
    <id>http://dreamrunner.org/blog/2014/05/24/programming-pearls-overview</id>
    <content type="html"><![CDATA[<p>全书分为 3 部分：</p>

<ul>
  <li>预备知识：总的概括代码涉及的知识点，比如算法和数据结构的重要性和合理性，如何写出正确的代码并证明，如何测试代码，性能评估代码，debug 等。 </li>
  <li>性能：先是介绍一些估算的技巧，比如 72 法则，利特尔法则(Little’s law)
等，之后展开代码算法的性能，如何调试代码使得性能更好或更省空间。</li>
  <li>产品：讲解具体的算法，如排序，搜索等。</li>
</ul>

<p>书本和习题大部分代码<a href="https://github.com/shishougang/Programming-Pearls">实现</a>。</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Programming Pearls: Column14-15]]></title>
    <link href="http://dreamrunner.org/blog/2014/05/24/column14_15/"/>
    <updated>2014-05-24T00:00:00+08:00</updated>
    <id>http://dreamrunner.org/blog/2014/05/24/column14_15</id>
    <content type="html"><![CDATA[<div id="outline-container-sec-1" class="outline-2">
<h2 id="sec-1">Book notes</h2>
<div class="outline-text-2" id="text-1">
</div><div id="outline-container-sec-1-1" class="outline-3">
<h3 id="sec-1-1">Hash 存储 word 次数</h3>
<div class="outline-text-3" id="text-1-1">
<!-- more -->

<div class="org-src-container">

<pre class="src src-c++"><span style="color: #00ffff;">typedef</span> <span style="color: #00ffff;">struct</span> <span style="color: #98fb98;">Node</span>* <span style="color: #98fb98;">Nodeptr</span>;
<span style="color: #00ffff;">struct</span> <span style="color: #98fb98;">Node</span> {
  <span style="color: #87cefa;">Node</span>(<span style="color: #98fb98;">string</span> <span style="color: #eedd82;">inword</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">incount</span>, <span style="color: #98fb98;">Nodeptr</span> <span style="color: #eedd82;">innext</span>) {
    word = inword;
    count = incount;
    next = innext;
  }
  <span style="color: #98fb98;">string</span> <span style="color: #eedd82;">word</span>;
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">count</span>;
  <span style="color: #98fb98;">Nodeptr</span> <span style="color: #eedd82;">next</span>;
};

<span style="color: #b0c4de;">#define</span> <span style="color: #eedd82;">NHASH</span> 29989
<span style="color: #b0c4de;">#define</span> <span style="color: #eedd82;">MULT</span> 31
<span style="color: #98fb98;">Nodeptr</span> <span style="color: #eedd82;">bin</span>[NHASH];

<span style="color: #98fb98;">unsigned</span> <span style="color: #98fb98;">int</span> <span style="color: #87cefa;">Hash</span>(<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">string</span> &amp;<span style="color: #eedd82;">str</span>) {
  <span style="color: #98fb98;">unsigned</span> <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">h</span> = 0;
  <span style="color: #00ffff;">for</span> (<span style="color: #7fffd4;">string</span>::<span style="color: #98fb98;">const_iterator</span> <span style="color: #eedd82;">it</span> = str.begin(); it != str.end(); ++it) {
    h = MULT * h + *it;
  }
  <span style="color: #00ffff;">return</span> h % NHASH;
}

<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">InWord</span>(<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">string</span> &amp;<span style="color: #eedd82;">str</span>) {
  <span style="color: #98fb98;">Nodeptr</span> <span style="color: #eedd82;">p</span>;
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">h</span>;
  h = Hash(str);
  <span style="color: #00ffff;">for</span> (p = bin[h]; p != <span style="color: #7fffd4;">NULL</span>; p = p-&gt;next) {
    <span style="color: #00ffff;">if</span> (str.compare(p-&gt;word) == 0) {
      (p-&gt;count)++;
      <span style="color: #00ffff;">return</span>;
    }
  }
  p = <span style="color: #00ffff;">new</span> <span style="color: #98fb98;">Node</span>(str, 1, bin[h]);
  bin[h] = p;
}

<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">main</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">argc</span>, <span style="color: #98fb98;">char</span> *<span style="color: #eedd82;">argv</span>[]) {
  <span style="color: #98fb98;">string</span> <span style="color: #eedd82;">str</span>;
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span>;
  <span style="color: #00ffff;">for</span> (i = 0; i &lt; NHASH; ++i) {
    bin[i] = <span style="color: #7fffd4;">NULL</span>;
  }
  <span style="color: #00ffff;">while</span> (cin &gt;&gt; str) {
    InWord(str);
  }
  <span style="color: #00ffff;">for</span> (i = 0; i &lt; NHASH; ++i) {
    <span style="color: #00ffff;">for</span> (<span style="color: #98fb98;">Nodeptr</span> <span style="color: #eedd82;">p</span> = bin[i]; p != <span style="color: #7fffd4;">NULL</span>; p = p-&gt;next) {
      cout &lt;&lt; p-&gt;word &lt;&lt; <span style="color: #ffa07a;">" "</span> &lt;&lt; p-&gt;count &lt;&lt; endl;
    }
  }
  <span style="color: #00ffff;">return</span> 0;
}
</pre>
</div>
</div>
</div>

<div id="outline-container-sec-1-2" class="outline-3">
<h3 id="sec-1-2">Markov 产生随机词汇</h3>
<div class="outline-text-3" id="text-1-2">
<p>
利用指针指向不同单词的开头，并按照 K 个单词对比方式排序，利用二分搜索定位相同 K 长度的文本，并利用<a href="http://wiki.dreamrunner.org/public_html/Algorithms/Theory%20of%20Algorithms/Reservoir%20Sampling.html">Reservoir sampling</a>在不知道长度的情况下，均等的随机选取一个。
</p>

<div class="org-src-container">

<pre class="src src-c++"><span style="color: #b0c4de;">#define</span> <span style="color: #eedd82;">MAXINPUT</span> 4000000
<span style="color: #b0c4de;">#define</span> <span style="color: #eedd82;">MAXWORDS</span> 800000
<span style="color: #b0c4de;">#define</span> <span style="color: #eedd82;">K</span> 2
<span style="color: #98fb98;">char</span> <span style="color: #eedd82;">input_letters</span>[MAXINPUT];
<span style="color: #98fb98;">char</span> *<span style="color: #eedd82;">word</span>[MAXWORDS];

<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">WordNcmp</span>(<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">char</span> *<span style="color: #eedd82;">p</span>, <span style="color: #00ffff;">const</span> <span style="color: #98fb98;">char</span> *<span style="color: #eedd82;">q</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">n</span>) {
  <span style="color: #00ffff;">while</span> (*p == *q) {
    <span style="color: #00ffff;">if</span> (*p == 0 &amp;&amp; --n == 0) {
      <span style="color: #00ffff;">return</span> 0;
    }
    ++p;
    ++q;
  }
  <span style="color: #00ffff;">return</span> *p - *q;
}


<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">SortCmp</span>(<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">void</span> *<span style="color: #eedd82;">a</span>, <span style="color: #00ffff;">const</span> <span style="color: #98fb98;">void</span> *<span style="color: #eedd82;">b</span>) {
  <span style="color: #00ffff;">const</span> <span style="color: #98fb98;">char</span> **<span style="color: #eedd82;">p</span> = (<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">char</span>**)(a);
  <span style="color: #00ffff;">const</span> <span style="color: #98fb98;">char</span> **<span style="color: #eedd82;">q</span> = (<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">char</span>**)(b);
  <span style="color: #00ffff;">return</span> WordNcmp(*p, *q, K);
}

<span style="color: #98fb98;">char</span>* <span style="color: #87cefa;">SkipNword</span>(<span style="color: #98fb98;">char</span> *<span style="color: #eedd82;">p</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">n</span>) {
  <span style="color: #00ffff;">for</span> (; n &gt; 0; p++) {
    <span style="color: #00ffff;">if</span> (*p == 0) {
      --n;
    }
  }
  <span style="color: #00ffff;">return</span> p;
}

<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">FindPhrase</span>(<span style="color: #98fb98;">char</span> **<span style="color: #eedd82;">word</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">n</span>, <span style="color: #98fb98;">char</span> *<span style="color: #eedd82;">phrase</span>) {
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">l</span> = -1;
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">u</span> = n;
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">m</span>;
  <span style="color: #00ffff;">while</span> (l + 1 != u) {
    m = (l + u) / 2;
    <span style="color: #00ffff;">if</span> (WordNcmp(word[m], phrase, K) &lt; 0) {
      l = m;
    } <span style="color: #00ffff;">else</span> {
      u = m;
    }
  }
  <span style="color: #00ffff;">return</span> u;
}

<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">main</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">argc</span>, <span style="color: #98fb98;">char</span> *<span style="color: #eedd82;">argv</span>[]) {
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">nword</span> = 0;
  word[0] = input_letters;
  <span style="color: #00ffff;">while</span> (scanf(<span style="color: #ffa07a;">"%s"</span>, word[nword]) != EOF) {
    word[nword + 1] = word[nword] + strlen(word[nword]) + 1;
    nword++;
    <span style="color: #00ffff;">if</span> (nword == MAXWORDS) {
      <span style="color: #00ffff;">break</span>;
    }
  }
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span>;
  <span style="color: #00ffff;">for</span> (i = 0; i &lt; K; ++i) {
    word[nword][i] = 0;
  }
  <span style="color: #00ffff;">for</span> (i = 0; i &lt; K; ++i) {
    printf(<span style="color: #ffa07a;">"%s "</span>, word[i]);
  }
  qsort(word, nword, <span style="color: #00ffff;">sizeof</span>(word[0]), SortCmp);
  <span style="color: #98fb98;">char</span> *<span style="color: #eedd82;">phrase</span> = input_letters;
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">printlen</span> = 100;
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">find_index</span>;
  <span style="color: #98fb98;">char</span> *<span style="color: #eedd82;">p</span>;
  <span style="color: #00ffff;">for</span> (; printlen &gt; 0; --printlen) {
    <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">find_index</span> = FindPhrase(word, nword, phrase);
    <span style="color: #00ffff;">for</span> (i = 0; WordNcmp(phrase, word[find_index + i], K) == 0; ++i) {
      <span style="color: #00ffff;">if</span> ((rand() % (i + 1)) == 0) {
        p = word[find_index + i];
      }
    }
    phrase = SkipNword(p, 1);
    <span style="color: #00ffff;">if</span> (strlen(SkipNword(phrase, K - 1)) == 0) {
      <span style="color: #00ffff;">break</span>;
    }
    printf(<span style="color: #ffa07a;">"%s "</span>, SkipNword(phrase, K - 1));
  }
  printf(<span style="color: #ffa07a;">"\n"</span>);
  <span style="color: #00ffff;">return</span> 0;
}
</pre>
</div>
</div>
</div>

<div id="outline-container-sec-1-3" class="outline-3">
<h3 id="sec-1-3">Markov 利用 Hash 产生随机词汇</h3>
<div class="outline-text-3" id="text-1-3">
<p>
利用 Hash 表加快搜索相同 K 长度的文本。
</p>

<div class="org-src-container">

<pre class="src src-c++"><span style="color: #b0c4de;">#define</span> <span style="color: #eedd82;">MAXINPUT</span> 4000000
<span style="color: #b0c4de;">#define</span> <span style="color: #eedd82;">MAXWORDS</span> 800000
<span style="color: #b0c4de;">#define</span> <span style="color: #eedd82;">K</span> 2
<span style="color: #98fb98;">char</span> <span style="color: #eedd82;">input_letters</span>[MAXINPUT];
<span style="color: #98fb98;">char</span> *<span style="color: #eedd82;">word</span>[MAXWORDS];

<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">WordNcmp</span>(<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">char</span> *<span style="color: #eedd82;">p</span>, <span style="color: #00ffff;">const</span> <span style="color: #98fb98;">char</span> *<span style="color: #eedd82;">q</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">n</span>) {
  <span style="color: #00ffff;">while</span> (*p == *q) {
    <span style="color: #00ffff;">if</span> (*p == 0 &amp;&amp; --n == 0) {
      <span style="color: #00ffff;">return</span> 0;
    }
    ++p;
    ++q;
  }
  <span style="color: #00ffff;">return</span> *p - *q;
}

<span style="color: #98fb98;">char</span>* <span style="color: #87cefa;">SkipNword</span>(<span style="color: #98fb98;">char</span> *<span style="color: #eedd82;">p</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">n</span>) {
  <span style="color: #00ffff;">for</span> (; n &gt; 0; p++) {
    <span style="color: #00ffff;">if</span> (*p == 0) {
      --n;
    }
  }
  <span style="color: #00ffff;">return</span> p;
}

<span style="color: #b0c4de;">#define</span> <span style="color: #eedd82;">NHASH</span> 499979
<span style="color: #b0c4de;">#define</span> <span style="color: #eedd82;">MULT</span> 31
<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">bin</span>[NHASH];
<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">next</span>[MAXWORDS];

<span style="color: #98fb98;">unsigned</span> <span style="color: #98fb98;">int</span> <span style="color: #87cefa;">Hash</span>(<span style="color: #98fb98;">char</span> *<span style="color: #eedd82;">str</span>) {
  <span style="color: #98fb98;">unsigned</span> <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">h</span> = 0;
  <span style="color: #98fb98;">char</span> *<span style="color: #eedd82;">p</span> = str;
  <span style="color: #00ffff;">for</span> (<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">n</span> = K; n &gt; 0; p++) {
    h = MULT * h + (<span style="color: #98fb98;">unsigned</span> <span style="color: #98fb98;">char</span>)(*p);
    <span style="color: #00ffff;">if</span> (*p == 0) {
      --n;
    }
  }
  <span style="color: #00ffff;">return</span> h % NHASH;
}

<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">InitHash</span>(<span style="color: #98fb98;">char</span> **<span style="color: #eedd82;">word</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">nword</span>) {
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span>;
  <span style="color: #00ffff;">for</span> (i = 0; i &lt; NHASH; ++i) {
    bin[i] = - 1;
  }
  <span style="color: #00ffff;">for</span> (i = 0; i &lt; nword; ++i) {
    <span style="color: #98fb98;">unsigned</span> <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">h</span> = Hash(word[i]);
    next[i] = bin[h];
    bin[h] = i;
  }
}

<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">main</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">argc</span>, <span style="color: #98fb98;">char</span> *<span style="color: #eedd82;">argv</span>[]) {
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">nword</span> = 0;
  word[0] = input_letters;
  <span style="color: #00ffff;">while</span> (scanf(<span style="color: #ffa07a;">"%s"</span>, word[nword]) != EOF) {
    word[nword + 1] = word[nword] + strlen(word[nword]) + 1;
    nword++;
    <span style="color: #00ffff;">if</span> (nword == MAXWORDS) {
      <span style="color: #00ffff;">break</span>;
    }
  }
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span>;
  <span style="color: #00ffff;">for</span> (i = 0; i &lt; K; ++i) {
    word[nword][i] = 0;
  }
  InitHash(word, nword);
  <span style="color: #00ffff;">for</span> (i = 0; i &lt; K; ++i) {
    printf(<span style="color: #ffa07a;">"%s "</span>, word[i]);
  }
  <span style="color: #98fb98;">char</span> *<span style="color: #eedd82;">phrase</span> = input_letters;
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">printlen</span> = 100;
  <span style="color: #98fb98;">char</span> *<span style="color: #eedd82;">p</span>;
  <span style="color: #00ffff;">for</span> (; printlen &gt; 0; --printlen) {
    i = 0;
    <span style="color: #00ffff;">for</span> (<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">j</span> = bin[Hash(phrase)]; j &gt;= 0; j = next[j]) {
      <span style="color: #00ffff;">if</span> (WordNcmp(word[j], phrase, K) == 0 &amp;&amp; (rand() % (++i) == 0)) {
        p = word[j];
      }
    }
    phrase = SkipNword(p, 1);
    <span style="color: #00ffff;">if</span> (strlen(SkipNword(phrase, K - 1)) == 0) {
      <span style="color: #00ffff;">break</span>;
    }
    printf(<span style="color: #ffa07a;">"%s "</span>, SkipNword(phrase, K - 1));
  }
  printf(<span style="color: #ffa07a;">"\n"</span>);
  <span style="color: #00ffff;">return</span> 0;
}
</pre>
</div>
</div>
</div>
</div>

<div id="outline-container-sec-2" class="outline-2">
<h2 id="sec-2">Problems</h2>
<div class="outline-text-2" id="text-2">
</div><div id="outline-container-sec-2-1" class="outline-3">
<h3 id="sec-2-1">Column14-2</h3>
<div class="outline-text-3" id="text-2-1">
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #98fb98;">void</span> <span style="color: #87cefa;">SiftDown</span>(<span style="color: #98fb98;">int</span> *<span style="color: #eedd82;">x</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">l</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">u</span>) {
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span> = l;
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">child</span>;
  <span style="color: #00ffff;">for</span> (;;) {
    child = i * 2;
    <span style="color: #00ffff;">if</span> (child &gt; u) {
      <span style="color: #00ffff;">break</span>;
    }
    <span style="color: #00ffff;">if</span> (child + 1 &lt;= u) {
      <span style="color: #00ffff;">if</span> (x[child + 1] &lt; x[child]) {
        child++;
      }
    }
    <span style="color: #00ffff;">if</span> (x[i] &lt;= x[child]) {
      <span style="color: #00ffff;">break</span>;
    }
    swap(x[i], x[child]);
    i = child;
  }
}

<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">HeapSort</span>(<span style="color: #98fb98;">int</span> *<span style="color: #eedd82;">x</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">n</span>) {
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span>;
  <span style="color: #00ffff;">for</span> (i = n / 2; i &gt;= 1; --i) {
    SiftDown(x, i, n);
  }
  <span style="color: #00ffff;">for</span> (i = n; i &gt;= 2; --i) {
    swap(x[1], x[i]);
    SiftDown(x, 1, i - 1);
  }
}
</pre>
</div>
</div>
</div>

<div id="outline-container-sec-2-2" class="outline-3">
<h3 id="sec-2-2">Column15-8</h3>
<div class="outline-text-3" id="text-2-2">
<p>
找出最长重复超过 M 次的字符串。
</p>

<p>
经过排序后，越是相邻的越是相同的多，至少重复 M 次，就是计算相邻 M 个位置的字符所重复的字符长度，即 <code>ComLen(pstr[i], pstr[i + kM])</code>
</p>

<div class="org-src-container">

<pre class="src src-c++"><span style="color: #98fb98;">int</span> <span style="color: #87cefa;">CmpPstr</span>(<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">void</span> *<span style="color: #eedd82;">a</span>, <span style="color: #00ffff;">const</span> <span style="color: #98fb98;">void</span> *<span style="color: #eedd82;">b</span>) {
  <span style="color: #00ffff;">const</span> <span style="color: #98fb98;">char</span> **<span style="color: #eedd82;">p</span> = (<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">char</span> **)a;
  <span style="color: #00ffff;">const</span> <span style="color: #98fb98;">char</span> **<span style="color: #eedd82;">q</span> = (<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">char</span> **)b;
  <span style="color: #00ffff;">return</span> strcmp(*p, *q);
}

<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">ComLen</span>(<span style="color: #98fb98;">char</span> *<span style="color: #eedd82;">p</span>, <span style="color: #98fb98;">char</span> *<span style="color: #eedd82;">q</span>) {
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span> = 0;
  <span style="color: #00ffff;">while</span> (*p &amp;&amp; (*p == *q)) {
    ++i;
    ++p;
    ++q;
  }
  <span style="color: #00ffff;">return</span> i;
}

<span style="color: #b0c4de;">#define</span> <span style="color: #eedd82;">kMaxN</span> 500000
<span style="color: #b0c4de;">#define</span> <span style="color: #eedd82;">kM</span> 1
<span style="color: #98fb98;">char</span> <span style="color: #eedd82;">str</span>[kMaxN];
<span style="color: #98fb98;">char</span> *<span style="color: #eedd82;">pstr</span>[kMaxN];
<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">main</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">argc</span>, <span style="color: #98fb98;">char</span> *<span style="color: #eedd82;">argv</span>[]) {
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">ch</span>;
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">n</span> = 0;
  <span style="color: #00ffff;">while</span> ((ch = getchar()) != EOF) {
    str[n] = ch;
    pstr[n] = &amp;str[n];
    ++n;
  }
  str[n] = 0;
  qsort(pstr, n, <span style="color: #00ffff;">sizeof</span>(<span style="color: #98fb98;">char</span> *), CmpPstr);
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">maxlen</span> = 0;
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">maxindex</span> = 0;
  <span style="color: #00ffff;">for</span> (<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span> = 0; i &lt; n - kM; ++i) {
    <span style="color: #00ffff;">if</span> (ComLen(pstr[i], pstr[i + kM]) &gt; maxlen) {
      maxlen = ComLen(pstr[i], pstr[i + kM]);
      maxindex = i;
    }
  }
  printf(<span style="color: #ffa07a;">"%.*s\n"</span>, maxlen, pstr[maxindex]);
  <span style="color: #00ffff;">return</span> 0;
}
</pre>
</div>
</div>
</div>
<div id="outline-container-sec-2-3" class="outline-3">
<h3 id="sec-2-3">Column15-9</h3>
<div class="outline-text-3" id="text-2-3">
<p>
找出两个文本中最长的共同字符串。
</p>

<p>
经典<a href="http://en.wikipedia.org/wiki/Longest_common_substring_problem">Longest common substring problem</a>.
利用 Dynamic Programming 解决。复杂度 O(mn).
</p>

<div class="org-src-container">

<pre class="src src-c++"><span style="color: #98fb98;">vector</span>&lt;<span style="color: #98fb98;">string</span>&gt; <span style="color: #87cefa;">LongestCommonString</span>(<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">string</span> &amp;<span style="color: #eedd82;">s</span>, <span style="color: #00ffff;">const</span> <span style="color: #98fb98;">string</span> &amp;<span style="color: #eedd82;">t</span>) {
  <span style="color: #98fb98;">vector</span>&lt;<span style="color: #98fb98;">vector</span>&lt;<span style="color: #98fb98;">int</span>&gt; &gt; <span style="color: #eedd82;">array</span>;
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">len_s</span> = s.size();
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">len_t</span> = t.size();
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span>, <span style="color: #eedd82;">j</span>;
  array.resize(len_s);
  <span style="color: #00ffff;">for</span> (i = 0; i &lt; len_s; ++i) {
    array[i].resize(len_t);
  }
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">max_len</span> = 0;
  <span style="color: #98fb98;">vector</span>&lt;<span style="color: #98fb98;">int</span>&gt; <span style="color: #eedd82;">end_indexs</span>;
  <span style="color: #00ffff;">for</span> (i = 0; i &lt; len_s; ++i) {
    <span style="color: #00ffff;">for</span> (j = 0; j &lt; len_t; ++j) {
      <span style="color: #00ffff;">if</span> (s[i] == t[j]) {
        <span style="color: #00ffff;">if</span> (i == 0 || j == 0) {
          array[i][j] = 1;
        } <span style="color: #00ffff;">else</span> {
          array[i][j] = array[i-1][j-1] + 1;
        }
        <span style="color: #00ffff;">if</span> (array[i][j] == max_len) {
          end_indexs.push_back(i);
        } <span style="color: #00ffff;">else</span> <span style="color: #00ffff;">if</span> (array[i][j] &gt; max_len) {
          max_len = array[i][j];
          end_indexs.clear();
          end_indexs.push_back(i);
        }
      }
    }
  }
  <span style="color: #98fb98;">vector</span>&lt;<span style="color: #98fb98;">string</span>&gt; <span style="color: #eedd82;">res</span>;
  <span style="color: #00ffff;">for</span> (<span style="color: #7fffd4;">vector</span>&lt;<span style="color: #98fb98;">int</span>&gt;::<span style="color: #98fb98;">iterator</span> <span style="color: #eedd82;">it</span> = end_indexs.begin(); it != end_indexs.end();
       ++it) {
    res.push_back(s.substr(*it - max_len + 1, max_len));
  }
  <span style="color: #00ffff;">return</span> res;
}
</pre>
</div>
</div>
</div>

<div id="outline-container-sec-2-4" class="outline-3">
<h3 id="sec-2-4">Column15-11</h3>
<div class="outline-text-3" id="text-2-4">
<p>
产生单词层次的 Markov 文本。
</p>

<div class="org-src-container">

<pre class="src src-c++"><span style="color: #98fb98;">int</span> <span style="color: #87cefa;">main</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">argc</span>, <span style="color: #98fb98;">char</span> *<span style="color: #eedd82;">argv</span>[]) {
  <span style="color: #00ffff;">const</span> <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">kMax</span> = 50000;
  <span style="color: #00ffff;">const</span> <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">kK</span> = 5;
  <span style="color: #00ffff;">const</span> <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">kPrintlen</span> = 1000;
  <span style="color: #98fb98;">char</span> <span style="color: #eedd82;">str</span>[kMax];
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">c</span>, <span style="color: #eedd82;">n</span>;
  n = 0;
  <span style="color: #00ffff;">while</span> ((c = getchar()) != EOF) {
    str[n++] = c;
  }
  str[n] = 0;
  <span style="color: #98fb98;">char</span> *<span style="color: #eedd82;">p</span>, *<span style="color: #eedd82;">q</span>, *<span style="color: #eedd82;">next_p</span>;
  p = str;
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span>, <span style="color: #eedd82;">eq_sofar</span>, <span style="color: #eedd82;">j</span>;
  <span style="color: #00ffff;">for</span> (i = 0; i &lt; kK; ++i) {
    printf(<span style="color: #ffa07a;">"%c"</span>, str[i]);
  }
  <span style="color: #00ffff;">for</span> (i = 0; i &lt; kPrintlen; ++i) {
    eq_sofar = 0;
    <span style="color: #00ffff;">for</span> (q = str; q &lt; str + n - kK + 1; ++q) {
      <span style="color: #00ffff;">for</span> (j = 0; j &lt; kK &amp;&amp; *(p + j) == *(q + j); ++j) {
      }
      <span style="color: #00ffff;">if</span> (j == kK) {
        eq_sofar++;
        <span style="color: #00ffff;">if</span> (rand() % eq_sofar == 0) {
          next_p = q;
        }
      }
    }
    c = *(next_p + kK);
    <span style="color: #00ffff;">if</span> (c == 0) {
      <span style="color: #00ffff;">break</span>;
    }
    putchar(c);
    p = next_p + 1;
  }
  <span style="color: #00ffff;">return</span> 0;
}
</pre>
</div>
</div>
</div>
</div>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Programming Pearls: Column11-12]]></title>
    <link href="http://dreamrunner.org/blog/2014/05/18/column11_12/"/>
    <updated>2014-05-18T00:00:00+08:00</updated>
    <id>http://dreamrunner.org/blog/2014/05/18/column11_12</id>
    <content type="html"><![CDATA[<div id="outline-container-sec-1" class="outline-2">
<h2 id="sec-1">Book notes</h2>
<div class="outline-text-2" id="text-1">
</div><div id="outline-container-sec-1-1" class="outline-3">
<h3 id="sec-1-1">QuickSort</h3>
<div class="outline-text-3" id="text-1-1">
<!-- more -->

<div class="org-src-container">

<pre class="src src-c++"><span style="color: #98fb98;">void</span> <span style="color: #87cefa;">swap</span>(<span style="color: #98fb98;">int</span> *<span style="color: #eedd82;">array</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">m</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">n</span>) {
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">temp</span>;
  temp = array[m];
  array[m] = array[n];
  array[n] = temp;
}

<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">randint</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">m</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">n</span>) {
  <span style="color: #00ffff;">return</span> m + (rand() / (RAND_MAX / (n - m + 1) + 1));
}

<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">isort</span>(<span style="color: #98fb98;">int</span> *<span style="color: #eedd82;">array</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">n</span>) {
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span>, <span style="color: #eedd82;">j</span>, <span style="color: #eedd82;">t</span>;
  <span style="color: #00ffff;">for</span> (i = 1; i &lt; n; ++i) {
    t = array[i];
    <span style="color: #00ffff;">for</span> (j = i; j &gt;= 0  &amp;&amp; array[j - 1] &lt; t; --j) {
      array[j] = array[j - 1];
    }
    array[j - 1] = t;
  }
}

<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">qsort1</span>(<span style="color: #98fb98;">int</span> *<span style="color: #eedd82;">array</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">l</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">u</span>) {
  <span style="color: #ff7f24;">/*</span><span style="color: #ff7f24;">use array[l] for the mid element */</span>
  <span style="color: #00ffff;">if</span> (l &gt;= u) {
    <span style="color: #00ffff;">return</span>;
  }
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">m</span>;
  m = l;
  <span style="color: #00ffff;">for</span> (<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span> = l + 1; i &lt;= u; ++i) {
    <span style="color: #00ffff;">if</span> (array[i] &lt; array[l]) {
      swap(array, ++m, i);
    }
  }
  swap(array, l, m);
  qsort1(array, l, m - 1);
  qsort1(array, m + 1, u);
}

<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">qsort2</span>(<span style="color: #98fb98;">int</span> *<span style="color: #eedd82;">array</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">l</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">u</span>) {
  <span style="color: #ff7f24;">/*</span><span style="color: #ff7f24;">use array[l] for the mid element, from back to start,</span>
<span style="color: #ff7f24;">    always swap the first element */</span>
  <span style="color: #00ffff;">if</span> (l &gt;= u) {
    <span style="color: #00ffff;">return</span>;
  }
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span>, <span style="color: #eedd82;">m</span>;
  i = m = u + 1;
  <span style="color: #00ffff;">do</span> {
    <span style="color: #00ffff;">do</span> {
      --i;
    } <span style="color: #00ffff;">while</span> (array[i] &lt; array[l]);
    swap(array, --m, i);
  } <span style="color: #00ffff;">while</span> (i &gt; l);
  qsort2(array, l, m - 1);
  qsort2(array, m + 1, u);
}

<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">qsort3</span>(<span style="color: #98fb98;">int</span> *<span style="color: #eedd82;">array</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">l</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">u</span>) {
  <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">two-way partition, use array[l] for the mid element */</span>
  <span style="color: #00ffff;">if</span> (l &gt;= u) {
    <span style="color: #00ffff;">return</span>;
  }
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">t</span>, <span style="color: #eedd82;">i</span> , <span style="color: #eedd82;">j</span>;
  t = array[l];
  i = l;
  j = u + 1;
  <span style="color: #00ffff;">for</span> (;;) {
    <span style="color: #00ffff;">do</span> {
      ++i;
    } <span style="color: #00ffff;">while</span> (i &lt;= u &amp;&amp; array[i] &lt; t);
    <span style="color: #00ffff;">do</span> {
      --j;
    } <span style="color: #00ffff;">while</span> (array[j] &gt; t);
    <span style="color: #00ffff;">if</span> (i &gt; j) {
      <span style="color: #00ffff;">break</span>;
    }
    swap(array, i, j);
  }
  swap(array, l, j);
  qsort3(array, l, j - 1);
  qsort3(array, j + 1, u);
}

<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">kCutOff</span> = 50;
<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">qsort4</span>(<span style="color: #98fb98;">int</span> *<span style="color: #eedd82;">array</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">l</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">u</span>) {
  <span style="color: #ff7f24;">/* </span><span style="color: #ff7f24;">qsort3 + randomization + isort small subarrays + swap inline */</span>
  <span style="color: #00ffff;">if</span> (u - l &lt; kCutOff) {
    <span style="color: #00ffff;">return</span>;
  }
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">t</span>, <span style="color: #eedd82;">i</span> , <span style="color: #eedd82;">j</span>;
  swap(array, l, randint(l, u));
  t = array[l];
  i = l;
  j = u + 1;
  <span style="color: #00ffff;">for</span> (;;) {
    <span style="color: #00ffff;">do</span> {
      ++i;
    } <span style="color: #00ffff;">while</span> (i &lt;= u &amp;&amp; array[i] &lt; t);
    <span style="color: #00ffff;">do</span> {
      --j;
    } <span style="color: #00ffff;">while</span> (array[j] &gt; t);
    <span style="color: #00ffff;">if</span> (i &gt; j) {
      <span style="color: #00ffff;">break</span>;
    }
    swap(array, i, j);
  }
  swap(array, l, j);
  qsort3(array, l, j - 1);
  qsort3(array, j + 1, u);
}
</pre>
</div>
</div>
</div>
<div id="outline-container-sec-1-2" class="outline-3">
<h3 id="sec-1-2">生成随机数</h3>
<div class="outline-text-3" id="text-1-2">
<p>
从 n 中生成不重复的 m 个随机数。
</p>
</div>

<div id="outline-container-sec-1-2-1" class="outline-4">
<h4 id="sec-1-2-1">1</h4>
<div class="outline-text-4" id="text-1-2-1">
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #98fb98;">void</span> <span style="color: #87cefa;">GenerateSortedRand</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">m</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">n</span>) {
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">select</span> = m;
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">remaining</span> = n;
  <span style="color: #00ffff;">for</span> (<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span> = 0; i &lt; n &amp;&amp; select &gt; 0; ++i) {
    <span style="color: #00ffff;">if</span> (rand() % remaining &lt; select) {
      cout &lt;&lt; i &lt;&lt; <span style="color: #ffa07a;">" "</span>;
      --select;
    }
    --remaining;
  }
  cout &lt;&lt; endl;
}
</pre>
</div>
</div>
</div>

<div id="outline-container-sec-1-2-2" class="outline-4">
<h4 id="sec-1-2-2">2</h4>
<div class="outline-text-4" id="text-1-2-2">
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #98fb98;">void</span> <span style="color: #87cefa;">GenKnuth</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">m</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">n</span>) {
  <span style="color: #00ffff;">for</span> (<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span> = 0; i &lt; n &amp;&amp; m &gt; 0; ++i) {
    <span style="color: #00ffff;">if</span> (rand() % (n - i) &lt; m) {
      cout &lt;&lt; i &lt;&lt; <span style="color: #ffa07a;">" "</span>;
      --m;
    }
  }
  cout &lt;&lt; endl;
}
</pre>
</div>
</div>
</div>

<div id="outline-container-sec-1-2-3" class="outline-4">
<h4 id="sec-1-2-3">3</h4>
<div class="outline-text-4" id="text-1-2-3">
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #98fb98;">void</span> <span style="color: #87cefa;">GenSets</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">m</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">n</span>) {
  <span style="color: #98fb98;">set</span>&lt;<span style="color: #98fb98;">int</span>&gt; <span style="color: #eedd82;">num_set</span>;
  <span style="color: #00ffff;">while</span> (num_set.size() &lt; m) {
    num_set.insert(rand() % n);
  }
  <span style="color: #00ffff;">for</span> (<span style="color: #7fffd4;">set</span>&lt;<span style="color: #98fb98;">int</span>&gt;::<span style="color: #98fb98;">iterator</span> <span style="color: #eedd82;">it</span> = num_set.begin(); it != num_set.end(); ++it) {
    cout &lt;&lt; *it &lt;&lt; <span style="color: #ffa07a;">" "</span>;
  }
  cout &lt;&lt; endl;
}
</pre>
</div>
</div>
</div>

<div id="outline-container-sec-1-2-4" class="outline-4">
<h4 id="sec-1-2-4">4</h4>
<div class="outline-text-4" id="text-1-2-4">
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #98fb98;">int</span> <span style="color: #87cefa;">randint</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">m</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">n</span>) {
  <span style="color: #00ffff;">return</span> m + (rand() / (RAND_MAX / (n - m + 1) + 1));
}

<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">compare</span>(<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">void</span> *<span style="color: #eedd82;">a</span>, <span style="color: #00ffff;">const</span> <span style="color: #98fb98;">void</span> *<span style="color: #eedd82;">b</span>) {
  <span style="color: #00ffff;">return</span> (*<span style="color: #00ffff;">static_cast</span>&lt;<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">int</span>*&gt;(a) - *<span style="color: #00ffff;">static_cast</span>&lt;<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">int</span>*&gt;(b));
}

<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">GenShuf</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">m</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">n</span>) {
  <span style="color: #98fb98;">int</span> *<span style="color: #eedd82;">x</span> = <span style="color: #00ffff;">new</span> <span style="color: #98fb98;">int</span>[n];
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span> = 0;
  <span style="color: #00ffff;">for</span> (i = 0; i &lt; n; ++i) {
    x[i] = i;
  }
  <span style="color: #00ffff;">for</span> (i = 0; i &lt; m; ++i) {
    <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">j</span> = randint(i, n - 1);
    <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">t</span> = x[j];
    x[j] = x[i];
    x[i] = t;
  }
  qsort(x, m, <span style="color: #00ffff;">sizeof</span>(<span style="color: #98fb98;">int</span>), compare);
  <span style="color: #00ffff;">for</span> (i = 0; i &lt; m; ++i) {
    cout &lt;&lt; x[i] &lt;&lt; <span style="color: #ffa07a;">" "</span>;
  }
  cout &lt;&lt; endl;
  <span style="color: #00ffff;">delete</span> x;
}
</pre>
</div>
</div>
</div>
</div>

<div id="outline-container-sec-1-3" class="outline-3">
<h3 id="sec-1-3">原则</h3>
<div class="outline-text-3" id="text-1-3">
<ul class="org-ul">
<li>理解问题。与用户讨论提出问题的有关场景。问题的陈述中往往包含问题的想法，和所有早期的想法一样，它们应该被考虑而不是与其他排斥。
</li>
<li>指出一个抽象问题。一个清晰，整洁的问题陈述不旦帮助我们解决这个问题，并且能体现如何把这个解答应用到其他的问题上。
</li>
<li>探索设计空间。不要急于立刻去解决问题，思考一分钟，花一天时间编程。应该思考一小时，编程一小时。使用通俗的上层语言帮助我们描述设计：伪代码描述控制六，抽象化表示关键数据结构的数据类型。
</li>
<li>实现一种解答。我们应该追求以直接清晰的代码来实现选择的设计，使用最强大的能用的操作。
</li>
<li>回顾。Polya 的<a href="http://www.amazon.com/How-Solve-It-Mathematical-Princeton/dp/069111966X">How to Solve It</a>能帮助任何程序员成为更好的问题解决者。在
15 页他说：”基本存在一些东西去做，随着足够的学习和突破，我们能改善每个解答，并且在任何情况下，我们都能经常改善我们对解答的理解。“
</li>
</ul>
</div>
</div>
</div>
<div id="outline-container-sec-2" class="outline-2">
<h2 id="sec-2">Problems</h2>
<div class="outline-text-2" id="text-2">
</div><div id="outline-container-sec-2-1" class="outline-3">
<h3 id="sec-2-1">Column11-9</h3>
<div class="outline-text-3" id="text-2-1">
<p>
在数组 n 中以算法复杂度 O(n)找出第 k 个小的元素。
</p>

<div class="org-src-container">

<pre class="src src-c++"><span style="color: #98fb98;">void</span> <span style="color: #87cefa;">swap</span>(<span style="color: #98fb98;">int</span> *<span style="color: #eedd82;">array</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">m</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">n</span>) {
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">temp</span>;
  temp = array[m];
  array[m] = array[n];
  array[n] = temp;
}

<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">randint</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">m</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">n</span>) {
  <span style="color: #00ffff;">return</span> m + (rand() / (RAND_MAX / (n - m + 1) + 1));
}

<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">SelectK</span>(<span style="color: #98fb98;">int</span> *<span style="color: #eedd82;">array</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">l</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">u</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">k</span>) {
  <span style="color: #00ffff;">if</span> (l &gt;= u) {
    <span style="color: #00ffff;">return</span>;
  }
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">t</span>, <span style="color: #eedd82;">i</span>, <span style="color: #eedd82;">j</span>;
  swap(array, l, randint(l, u));
  t = array[l];
  i = l;
  j = u + 1;
  <span style="color: #00ffff;">for</span> (;;) {
    <span style="color: #00ffff;">do</span> {
      ++i;
    } <span style="color: #00ffff;">while</span> (i &lt;= u &amp;&amp; array[i] &lt; t);
    <span style="color: #00ffff;">do</span> {
      --j;
    } <span style="color: #00ffff;">while</span> (array[j] &gt; t);
    <span style="color: #00ffff;">if</span> (i &gt; j) {
      <span style="color: #00ffff;">break</span>;
    }
    swap(array, i, j);
  }
  swap(array, l, j);
  <span style="color: #00ffff;">if</span> (j &lt; k) {
    SelectK(array, j + 1, u, k);
  }
  <span style="color: #00ffff;">else</span> <span style="color: #00ffff;">if</span> (j &gt; k) {
    SelectK(array, l, j - 1, k);
  }
}
</pre>
</div>
</div>
</div>

<div id="outline-container-sec-2-2" class="outline-3">
<h3 id="sec-2-2">1</h3>
<div class="outline-text-3" id="text-2-2">
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #98fb98;">int</span> <span style="color: #87cefa;">randint</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">m</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">n</span>) {
  <span style="color: #00ffff;">return</span> m + (rand() / (RAND_MAX / (n - m + 1) + 1));
}

<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">bigrand</span>() {
  <span style="color: #00ffff;">return</span> RAND_MAX * rand() + rand();
}
</pre>
</div>
</div>
</div>

<div id="outline-container-sec-2-3" class="outline-3">
<h3 id="sec-2-3">2</h3>
<div class="outline-text-3" id="text-2-3">
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #98fb98;">int</span> <span style="color: #87cefa;">randint</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">m</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">n</span>) {
  <span style="color: #00ffff;">return</span> m + (rand() / (RAND_MAX / (n - m + 1) + 1));
}

<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">GenerateM</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">m</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">n</span>) {
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span>, <span style="color: #eedd82;">t</span>;
  i = randint(0, n - 1);
  <span style="color: #00ffff;">for</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">j</span> = 0; j &lt; m; ++j) {
    t = i + j;
    <span style="color: #00ffff;">if</span> (t &gt;= n) {
      t -= n;
    }
    cout &lt;&lt; t &lt;&lt; <span style="color: #ffa07a;">" "</span> &lt;&lt; endl;
  }
  cout &lt;&lt; endl;
}
</pre>
</div>
</div>
</div>

<div id="outline-container-sec-2-4" class="outline-3">
<h3 id="sec-2-4">8</h3>
<div class="outline-text-3" id="text-2-4">
<p>
0..n-1 中生成 m 个随机数。
</p>

<div class="org-src-container">

<pre class="src src-c++"><span style="color: #98fb98;">int</span> <span style="color: #87cefa;">randint</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">m</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">n</span>) {
  <span style="color: #00ffff;">return</span> m + (rand() / (RAND_MAX / (n - m + 1) + 1));
}

<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">compare</span>(<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">void</span> *<span style="color: #eedd82;">a</span>, <span style="color: #00ffff;">const</span> <span style="color: #98fb98;">void</span> *<span style="color: #eedd82;">b</span>) {
  <span style="color: #00ffff;">return</span> (*<span style="color: #00ffff;">static_cast</span>&lt;<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">int</span>*&gt;(a) - *<span style="color: #00ffff;">static_cast</span>&lt;<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">int</span>*&gt;(b));
}

<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">GenShuf</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">m</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">n</span>) {
  <span style="color: #98fb98;">int</span> *<span style="color: #eedd82;">x</span> = <span style="color: #00ffff;">new</span> <span style="color: #98fb98;">int</span>[n];
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span> = 0;
  <span style="color: #00ffff;">for</span> (i = 0; i &lt; n; ++i) {
    x[i] = i;
  }
  <span style="color: #00ffff;">for</span> (i = 0; i &lt; m; ++i) {
    <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">j</span> = randint(i, n - 1);
    <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">t</span> = x[j];
    x[j] = x[i];
    x[i] = t;
  }

  <span style="color: #00ffff;">for</span> (i = 0; i &lt; m; ++i) {
    cout &lt;&lt; x[i] &lt;&lt; <span style="color: #ffa07a;">" "</span>;
  }
  cout &lt;&lt; endl;
  <span style="color: #00ffff;">delete</span> x;
}
</pre>
</div>

<p>
如果允许有重复的数，如何生成排序的 m 个随机数。
</p>
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #98fb98;">void</span> <span style="color: #87cefa;">GenSets</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">m</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">n</span>) {
  <span style="color: #98fb98;">multiset</span>&lt;<span style="color: #98fb98;">int</span>&gt; <span style="color: #eedd82;">num_set</span>;
  <span style="color: #00ffff;">while</span> (num_set.size() &lt; m) {
    num_set.insert(rand() % n);
  }
  <span style="color: #00ffff;">for</span> (<span style="color: #7fffd4;">multiset</span>&lt;<span style="color: #98fb98;">int</span>&gt;::<span style="color: #98fb98;">iterator</span> <span style="color: #eedd82;">it</span> = num_set.begin(); it != num_set.end();
       ++it) {
    cout &lt;&lt; *it &lt;&lt; <span style="color: #ffa07a;">" "</span>;
  }
  cout &lt;&lt; endl;
}
</pre>
</div>

<p>
如果可以重复并顺序随机。
</p>
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #98fb98;">void</span> <span style="color: #87cefa;">GenM</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">m</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">n</span>) {
  <span style="color: #00ffff;">for</span> (<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span> = 0; i &lt; m; ++i) {
    cout &lt;&lt; randint(0, n - 1) &lt;&lt; <span style="color: #ffa07a;">" "</span>;
  }
  cout &lt;&lt; endl;
}
</pre>
</div>
</div>
</div>

<div id="outline-container-sec-2-5" class="outline-3">
<h3 id="sec-2-5">9</h3>
<div class="outline-text-3" id="text-2-5">
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #98fb98;">int</span> <span style="color: #87cefa;">randint</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">m</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">n</span>) {
  <span style="color: #00ffff;">return</span> m + (rand() / (RAND_MAX / (n - m + 1) + 1));
}

<span style="color: #98fb98;">void</span> <span style="color: #87cefa;">GenSets</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">m</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">n</span>) {
  <span style="color: #98fb98;">set</span>&lt;<span style="color: #98fb98;">int</span>&gt; <span style="color: #eedd82;">num_set</span>;
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">t</span>;
  <span style="color: #00ffff;">for</span> (<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span> = n - m ; i &lt; n; ++i) {
    t = randint(0, i);
    <span style="color: #00ffff;">if</span> (num_set.find(t) == num_set.end()) {
      num_set.insert(t);
    } <span style="color: #00ffff;">else</span> {
      num_set.insert(i);
    }
  }
  <span style="color: #00ffff;">for</span> (<span style="color: #7fffd4;">set</span>&lt;<span style="color: #98fb98;">int</span>&gt;::<span style="color: #98fb98;">iterator</span> <span style="color: #eedd82;">it</span> = num_set.begin(); it != num_set.end(); ++it) {
    cout &lt;&lt; *it &lt;&lt; <span style="color: #ffa07a;">" "</span>;
  }
  cout &lt;&lt; endl;
}
</pre>
</div>
</div>
</div>

<div id="outline-container-sec-2-6" class="outline-3">
<h3 id="sec-2-6">10</h3>
<div class="outline-text-3" id="text-2-6">
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #98fb98;">int</span> <span style="color: #87cefa;">randint</span>(<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">m</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">n</span>) {
  <span style="color: #00ffff;">return</span> m + (rand() / (RAND_MAX / (n - m + 1) + 1));
}

<span style="color: #98fb98;">int</span> <span style="color: #87cefa;">Select</span>() {
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">res</span>;
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span> = 0;
  res = object[i];
  ++i;
  <span style="color: #00ffff;">while</span> (IsEnd(object[i])) {
      <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">j</span> = randint(0, i);
      <span style="color: #00ffff;">if</span> (j &lt; 1) {
        res = object[i];
      }
      ++i;
  }
  <span style="color: #00ffff;">return</span> res;
}
</pre>
</div>

<p>
More: <a href="http://wiki.dreamrunner.org/public_html/Algorithms/Random%20and%20Sampling.html#sec-2">选 k 个</a>
</p>
</div>
</div>

<div id="outline-container-sec-2-7" class="outline-3">
<h3 id="sec-2-7">12</h3>
<div class="outline-text-3" id="text-2-7">
<p>
生成 N&gt;1e6 组的 m 个随机数，计算生成每个随机数出现的概率，是不是符合预期，还是偏差很大而不是随机的。
</p>
</div>
</div>
</div>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Programming Pearls: Column8]]></title>
    <link href="http://dreamrunner.org/blog/2014/05/17/column8/"/>
    <updated>2014-05-17T00:00:00+08:00</updated>
    <id>http://dreamrunner.org/blog/2014/05/17/column8</id>
    <content type="html"><![CDATA[<div id="outline-container-sec-1" class="outline-2">
<h2 id="sec-1">Book notes</h2>
<div class="outline-text-2" id="text-1">
</div><div id="outline-container-sec-1-1" class="outline-3">
<h3 id="sec-1-1">问题与算法</h3>
<div class="outline-text-3" id="text-1-1">
<p>
给出数组中找出连续子数组最大和。
</p>

<!-- more -->
</div>

<div id="outline-container-sec-1-1-1" class="outline-4">
<h4 id="sec-1-1-1">1</h4>
<div class="outline-text-4" id="text-1-1-1">
<p>
直接算每个子区间的和并比较得出最大值。算法复杂度 O(n<sup>3</sup>)。
</p>

<div class="org-src-container">

<pre class="src src-c++"><span style="color: #98fb98;">float</span> <span style="color: #87cefa;">FindMaxSubvectorAlg1</span>(<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">vector</span>&lt;<span style="color: #98fb98;">float</span>&gt; &amp;<span style="color: #eedd82;">num</span>) {
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span>, <span style="color: #eedd82;">j</span>, <span style="color: #eedd82;">k</span>;
  <span style="color: #98fb98;">float</span> <span style="color: #eedd82;">sum</span>, <span style="color: #eedd82;">max_sofar</span>;
  max_sofar = 0;
  <span style="color: #00ffff;">for</span> (i = 0; i &lt; num.size(); ++i) {
    <span style="color: #00ffff;">for</span> (j = 0; j &lt; num.size(); ++j) {
      sum = 0;
      <span style="color: #00ffff;">for</span> (k = i; k &lt;= j; k++) {
        sum += num[k];
        <span style="color: #00ffff;">if</span> (sum &gt; max_sofar) {
          max_sofar = sum;
        }
      }
    }
  }
  <span style="color: #00ffff;">return</span> max_sofar;
}
</pre>
</div>
</div>
</div>
<div id="outline-container-sec-1-1-2" class="outline-4">
<h4 id="sec-1-1-2">2</h4>
<div class="outline-text-4" id="text-1-1-2">
</div><div id="outline-container-sec-1-1-2-1" class="outline-5">
<h5 id="sec-1-1-2-1">2.1</h5>
<div class="outline-text-5" id="text-1-1-2-1">
<p>
因为 x[i..j]直接的和可以基于 x[i..j-1]的和算出，不用重头开始算。算法复杂度 O(n<sup>2</sup>)。
</p>

<div class="org-src-container">

<pre class="src src-c++"><span style="color: #98fb98;">float</span> <span style="color: #87cefa;">FindMaxSubvectorAlg2</span>(<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">vector</span>&lt;<span style="color: #98fb98;">float</span>&gt; &amp;<span style="color: #eedd82;">num</span>) {
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span>, <span style="color: #eedd82;">j</span>;
  <span style="color: #98fb98;">float</span> <span style="color: #eedd82;">sum</span>, <span style="color: #eedd82;">max_sofar</span>;
  max_sofar = 0;
  <span style="color: #00ffff;">for</span> (i = 0; i &lt; num.size(); ++i) {
    sum = 0;
    <span style="color: #00ffff;">for</span> (j = i; j &lt; num.size(); ++j) {
      sum += num[j];
      <span style="color: #00ffff;">if</span> (sum &gt; max_sofar) {
        max_sofar = sum;
      }
    }
  }
  <span style="color: #00ffff;">return</span> max_sofar;
}
</pre>
</div>
</div>
</div>
<div id="outline-container-sec-1-1-2-2" class="outline-5">
<h5 id="sec-1-1-2-2">2.2</h5>
<div class="outline-text-5" id="text-1-1-2-2">
<p>
先算出 x[0..i]区间的和为 <code>cum_vector[i]</code> ，那么 x[i..j]区间的和就是
<code>cum_vector[j] - cum-vector[i-1]</code>
</p>
<div class="org-src-container">

<pre class="src src-c++"><span style="color: #98fb98;">float</span> <span style="color: #87cefa;">FindMaxSubvectorAlg2b</span>(<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">vector</span>&lt;<span style="color: #98fb98;">float</span>&gt; &amp;<span style="color: #eedd82;">num</span>) {
  <span style="color: #98fb98;">vector</span>&lt;<span style="color: #98fb98;">float</span>&gt; <span style="color: #eedd82;">cum_vector</span>(num.size() + 1);
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span>, <span style="color: #eedd82;">j</span>;
  cum_vector[0] = 0;
  <span style="color: #00ffff;">for</span> (i = 1; i &lt; cum_vector.size(); ++i) {
    cum_vector[i] = cum_vector[i - 1] + num[i];
  }
  <span style="color: #98fb98;">float</span> <span style="color: #eedd82;">sum</span>, <span style="color: #eedd82;">max_sofar</span>;
  max_sofar = 0;
  <span style="color: #00ffff;">for</span> (i = 1; i &lt; cum_vector.size(); ++i) {
    <span style="color: #00ffff;">for</span> (j = i; j &lt; cum_vector.size(); ++j) {
      sum = cum_vector[j] - cum_vector[i - 1];
      <span style="color: #00ffff;">if</span> (sum &gt; max_sofar) {
        max_sofar = sum;
      }
    }
  }
  <span style="color: #00ffff;">return</span> max_sofar;
}
</pre>
</div>
</div>
</div>
</div>

<div id="outline-container-sec-1-1-3" class="outline-4">
<h4 id="sec-1-1-3">3</h4>
<div class="outline-text-4" id="text-1-1-3">
<p>
Divide-and-Conquer 算法。
</p>
<ol class="org-ol">
<li>求整个数组的子数组和，可以分成前面一半和后面一半
</li>
</ol>
<img src="http://dreamrunner.org/images/blog/2014/programmingpearls/column8_3_1.jpg" title="'column8_3_1'" />

<ol class="org-ol">
<li>求出前半部分的最大子数组和后半部分的最大子数组和
</li>
</ol>
<img src="http://dreamrunner.org/images/blog/2014/programmingpearls/column8_3_2.jpg" title="'column8_3_2'" />

<ol class="org-ol">
<li>求出两部分中间连着的子数组最大和
</li>
</ol>
<img src="http://dreamrunner.org/images/blog/2014/programmingpearls/column8_3_3.jpg" title="'column8_3_3'" />

<ol class="org-ol">
<li>最后比较这 3 部分和就能得出整个个数组的子数组最大和
</li>
</ol>

<div class="org-src-container">

<pre class="src src-c++"><span style="color: #98fb98;">float</span> <span style="color: #87cefa;">FindMaxSubvectorAlg3Core</span>(<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">vector</span>&lt;<span style="color: #98fb98;">float</span>&gt; &amp;<span style="color: #eedd82;">num</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">l</span>, <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">u</span>) {
  <span style="color: #00ffff;">if</span> (l &gt; u) {
    <span style="color: #00ffff;">return</span> 0;
  }
  <span style="color: #00ffff;">if</span> (l == u) {
    <span style="color: #00ffff;">return</span> <span style="color: #98fb98;">max</span>&lt;<span style="color: #98fb98;">float</span>&gt;(num[l], 0);
  }
  <span style="color: #98fb98;">int</span> <span style="color: #eedd82;">m</span>;
  m = (l + u) / 2;
  <span style="color: #98fb98;">float</span> <span style="color: #eedd82;">lmax</span>, <span style="color: #eedd82;">rmax</span>, <span style="color: #eedd82;">sum</span>;
  lmax = sum = 0;
  <span style="color: #00ffff;">for</span> (<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span> = m; i &gt;= l; --i) {
    sum += num[i];
    <span style="color: #00ffff;">if</span> (sum &gt; lmax) {
      lmax = sum;
    }
  }
  rmax = sum = 0;
  <span style="color: #00ffff;">for</span> (<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span> = m + 1; i &lt;= u; ++i) {
    sum += num[i];
    <span style="color: #00ffff;">if</span> (sum &gt; rmax) {
      rmax = sum;
    }
  }
  <span style="color: #00ffff;">return</span> max(lmax + rmax, max(FindMaxSubvectorAlg3Core(num, l, m),
                              FindMaxSubvectorAlg3Core(num, m + 1, u)));
}

<span style="color: #98fb98;">float</span> <span style="color: #87cefa;">FindMaxSubvectorAlg3</span>(<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">vector</span>&lt;<span style="color: #98fb98;">float</span>&gt; &amp;<span style="color: #eedd82;">num</span>) {
  <span style="color: #00ffff;">return</span> FindMaxSubvectorAlg3Core(num, 0, num.size() - 1);
}
</pre>
</div>
</div>
</div>
<div id="outline-container-sec-1-1-4" class="outline-4">
<h4 id="sec-1-1-4">4</h4>
<div class="outline-text-4" id="text-1-1-4">
<p>
假定已经解决了 x[0..i-1]的情况，那么如何扩展到 x[0..i]的情况，只多了 x[i]
元素？
</p>

<ol class="org-ol">
<li>解决了 x[0..i-1]的情况，有这区间的最大子数组和 <code>max_sofar</code> ，和必须以
x[i-1]结尾的子数组最大和;
</li>
<li>到 x[0..i]的情况，就要把必须以 x[i-1]结尾的子数组最大和与 x[i]相加，如果以 x[i-1]结尾的子数组为负数的话，加了反而减少总和。所以此种情况以
x[i]的和就是 x[i];
</li>
<li>最后把以 x[i]与在区间 x[0..i-1]的最大子数组和 <code>max_sofar</code> 比较，就能解决
x[0..i]的情况;
</li>
<li>如此一直扩展到 x[0..n]算出整个数组的最大子数组和。
</li>
</ol>

<p>
只扫描一遍，算法复杂度 O(n)。
</p>

<div class="org-src-container">

<pre class="src src-c++"><span style="color: #98fb98;">float</span> <span style="color: #87cefa;">FindMaxSubvectorAlg4</span>(<span style="color: #00ffff;">const</span> <span style="color: #98fb98;">vector</span>&lt;<span style="color: #98fb98;">float</span>&gt; &amp;<span style="color: #eedd82;">num</span>) {
  <span style="color: #98fb98;">float</span> <span style="color: #eedd82;">max_sofar</span>, <span style="color: #eedd82;">max_ending_here</span>;
  max_sofar = max_ending_here = 0;
  <span style="color: #00ffff;">for</span> (<span style="color: #98fb98;">int</span> <span style="color: #eedd82;">i</span> = 0; i &lt; num.size(); ++i) {
    max_ending_here += num[i];
    <span style="color: #00ffff;">if</span> (max_ending_here &lt; 0) {
      max_ending_here = 0;
    }
    <span style="color: #00ffff;">if</span> (max_ending_here &gt; max_sofar) {
      max_sofar = max_ending_here;
    }
  }
  <span style="color: #00ffff;">return</span> max_sofar;
}
</pre>
</div>
</div>
</div>
</div>

<div id="outline-container-sec-1-2" class="outline-3">
<h3 id="sec-1-2">算法设计技巧</h3>
<div class="outline-text-3" id="text-1-2">
<ul class="org-ul">
<li>保存状态防止重复计算。
</li>
<li>预处理信息到适当的数据结构中来加快之后的计算。比如先建立堆，先排序等。
</li>
<li>分而治之，把大问题分成类似的小问题解决。
</li>
<li>扫描算法。比如解出了 x[0..i-1]如何扩展到 x[0..i].
</li>
<li>累积。
</li>
<li>确定问题的算法复杂度下界。
</li>
</ul>
</div>
</div>
</div>
<div id="outline-container-sec-2" class="outline-2">
<h2 id="sec-2">Problems</h2>
<div class="outline-text-2" id="text-2">
</div><div id="outline-container-sec-2-1" class="outline-3">
<h3 id="sec-2-1">10</h3>
<div class="outline-text-3" id="text-2-1">
<ol class="org-ol">
<li>初始化累积和数组 cum，使得 <code>cum[i]=x[0]+x[1]...x[i]</code> ， 那么要 x[l..u]
区间的和为 0 的话，cum[l-1] = cum[u]
</li>
<li>排序 cum 数组;
</li>
<li>扫描排序好的数组 cum，找出最相近的相邻数组元素即得到结果。
</li>
</ol>

<p>
算法复杂度 O(n) + O(nlogn) + O(n-1) = O(nlogn).
</p>

<p>
找出子数组和与一个特定值 r 最相近，算法类似，只是 step3 找出与 r 最相近的相邻数组元素。
</p>
</div>
</div>
<div id="outline-container-sec-2-2" class="outline-3">
<h3 id="sec-2-2">11</h3>
<div class="outline-text-3" id="text-2-2">
<ol class="org-ol">
<li>累积收费和数组 cum，使得 <code>cum[i]=x[0]+x[1]...x[i]</code>
</li>
<li>计算 l 和 u 关卡之间的收费 cum[u]-cum[l]
</li>
</ol>
</div>
</div>
</div>
]]></content>
  </entry>
  
</feed>
