學習 LLVM(10) ilist.h

位於 llvm/include/llvm/[[ADT]]/ilist.hnode

== 簡介 ==
主要實現侵入式連接列表模板(Intrusive Linked List Template),實際是雙向的列表。dom

主要類是 iplist, ilist 用於實現 列表模板。ide

其它是主要類的輔助的 iterator, traits 的實現。函數

這個文件定義類用於實現一個侵入式(intrusive)雙向連接列表,也即列表中每一個元素節點必須包含一個 next 和 previous 字段來做爲鏈表指針。ui

This file defines classes to implement an intrusive doubly linked list class(i.e. each node of the list must contain a next and previous field for the list.this

== 實現的類 ==
* ilist_nextprev_traits -- 提供 T 類型缺省 get|set Prev|Next 訪問策略。
* ilist_sentinel_traits -- 哨兵(sentinel)節點新建、刪除、訪問策略。
* ilist_node_traits -- 節點缺省操做策略實現。
* ilist_default_traits -- 缺省的 next,prev,sentinel,node 訪問。
* ilist_traits -- 缺省 ilist 模板特性,留給特化用。
* ilist_iterator指針

* [[iplist]]
* [[ilist]]
模板類 ilist 實現時,在鏈表建立的時候分配一個 '尾(tail)' 節點(使用 ilist_traits<>::createSentinel() 方法)。這個 tail 節點很是須要,由於用戶須要使用它計算 end()-1。爲此,若是用戶直接訪問 next/prev 指針指向的鏈表,將在尾部看到一個額外的連接(sentinel 哨兵節點),它應該被忽略的。ip

爲使用 ilist(iplist),要求元素類 T 必須實現 (get|set)(Next|Prev) 方法來獲取/設置指針,或者特化 ilist_traits<T> 以訪問 next/prev 指針。ci

The ilist class is implemented by allocating a 'tail' node when the list is
created (using ilist_traits<>::createSentinel()).  This tail node is
absolutely required because the user must be able to compute end()-1. Because
of this, users of the direct next/prev links will see an extra link on the
end of the list, which should be ignored.get

* 參考 llvm/ADT/[[ilist_node.h]]
* Sentinels

== ilist_nextprev_traits ==
模板類 [[ilist_nextprev_traits]] 實現模板 traits 來爲 ilist 提供缺省的 next/prev 指針公共操做的實現。

A fragment for template traits for intrusive list that provides default next/prev implementations for common operations.

類概要:
<syntaxhighlight lang="cpp">
template<typename T> struct ilist_nextprev_traits {
  getNext(),getPrev()  // 實現爲 T->getNext(),T->getPrev()
       // 也即缺省要求 T 有 getNext, getPrev 方法來獲取指針
  setNext(), setPrev() // 要求 T 有 setNext, setPrev 方法
}
</syntaxhighlight>

這種實現方式意味着能夠特化 ilist_nextprev_traits<T> 來爲本身的 T 類定義 get|set Next|Prev 的訪問方式。

== ilist_sentinel_traits ==
模板類 [[ilist_sentinel_traits]] 爲 ilist 提供缺省的哨兵(sentinel)節點公共操做的實現。

[[ilist_sentinel_traits]] 實現了一種延遲哨兵分配的策略。哨兵節點存儲在 Head.prev 成員中。

A fragment for template traits for intrusive list that provides default sentinel implementations for common operations.

ilist_sentinel_traits implements a lazy dynamic sentinel allocation
strategy. The sentinel is stored in the prev field of ilist's Head.

類概要:
<syntaxhighlight lang="cpp">
template<typename T> struct ilist_sentinel_traits {
  createSentinel() // 注1。建立一個哨兵節點,缺省實現爲 new T()
  destroySentinel() // 同 createSentinel() 匹配,用於釋放哨兵節點。

  provideInitialHead() // 建立 ilist 的時候提供缺省 Head 指針。返回 null 表示延遲分配。
  ensureHead() // 確保有一個 Head 指針。返回 sentinel 的指針。
  noteHead() // 保存 sentinel 指針到合適的(缺省的)位置。
}
</syntaxhighlight>

* 注1:這裏要分配一個額外的 T() 做爲哨兵節點,爲此若是 sizeof(T) 比較大會形成空間浪費。而且要求 T 要提供一個缺省構造函數。
* 注1:爲此某些特定類如 Value(及其派生類體系),實現有本身的 ilist_sentinel_traits 特化版,其不分配 Value 作爲哨兵節點。參見 [[Value]], [[GlobalVariable]] 。

這個類用於提供延遲建立 Head, sentinel 節點策略的一種實現。固然也能特化它以知足特定須要。

== ilist_node_traits ==
模板類 ilist_node_traits 爲 ilist 提供缺省的節點相關操做。

ilist_node_traits - A fragment for template traits for intrusive list
that provides default node related operations.

類概要:
<syntaxhighlight lang="cpp">
template<T=NODE_TYPE> struct ilist_node_traits {
  createNode() // 建立新節點,缺省爲 new T()
  deleteNode() // 釋放節點,缺省爲 delete
  // 其它幾個方法暫略。 
}
</syntaxhighlight>

== ilist_default_traits ==
模板類 ilist_default_traits 爲 ilist 提供缺省的模板特性(traits)。經過今後類派生,可以方便的得到 ilist 所需的公共操做的缺省實現。

ilist_default_traits - Default template traits for intrusive list.
By inheriting from this, you can easily use default implementations
for all common operations.

類概要:
<syntaxhighlight lang="cpp">
template<typename NodeTy>
struct ilist_default_traits
  : public ilist_nextprev_traits<NodeTy>,  // 提供 next,prev 訪問
    public ilist_sentinel_traits<NodeTy>,  // 提供 sentinel 訪問
    public ilist_node_traits<NodeTy> {  // 提供 node 訪問
}
</syntaxhighlight>

ilist, iplist 通常經過此類提供的方法來實現對數據的建立、刪除、及訪問。

== ilist_traits ==
爲 ilist 提供模板特性。經過特化這個模板,你能改變如何保存 next/prev 指針。。。

Template traits for intrusive list.  By specializing this template class, you
can change what next/prev fields are used to store the links...

模板 trait 類 ilist_traits 用於得到對鏈表元素中 next, previous 指針的訪問。若是 ilist_traits 沒有對元素類型進行特化,則它缺省使用 getNext(), getPrev() 方法來訪問 next, previous 指針。

The ilist_traits trait class is used to gain access to the next and previous fields of the node type that the list is instantiated with.  If it is not
specialized, the list defaults to using the getPrev(), getNext() method calls
to get the next and previous pointers.

類概要:
<syntaxhighlight lang="cpp">
template<typename NodeTy>
struct ilist_traits : public ilist_default_traits<NodeTy> {
  // 沒有本身的數據和方法,留給特化版特化用。
};
</syntaxhighlight>

* 特化版 const Ty 的特化:
  template<typename Ty>
  struct ilist_traits<const Ty> : public ilist_traits<Ty> {};

== ilist_iterator ==
ilist 的迭代器。實現爲 std 的雙向迭代器(bi-directional)。非 random-access 的。

實現中使用 ilist_traits<NodeTy> 提供的方式來訪問 next/prev 節點。

具體參見 std 迭代器的實現。

== ilist_iterator 針對 simplify_type 的特化 ==
在 [[isa]] 和 [[cast]] 模板函數中,大量使用了 simplify_type<> 來獲取類型的信息。
這裏 ilist.h 中,針對 ilist_iterator 提供了 [[simplify_type]] 的特化,從中能夠直接獲取 NodeTy* 的原始類型,及其值。也包括對 const ilist_iterator 的特化。

稍後有機會實驗這個狀況。

== 參見 == * [[iplist]] -- ilist 的基本實現。 * [[ilist]]  -- 派生自 iplist,實現 ilist。

相關文章
相關標籤/搜索