Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

Auto-unlink hooks 自斷鉤子

What's an auto-unlink hook? 什麼是自斷鉤子?
Auto-unlink hook example 自斷鉤子的例子
Auto-unlink hooks and containers with constant-time size() 自斷鉤子和帶常量時間 size() 的容器

Boost.Intrusive offers additional hooks with unique features:
Boost.Intrusive 提供了其它具有特色的鉤子:

  • When the destructor of the hook is called, the hook checks if the node is inserted in a container. If so, the hook removes the node from the container.
    當鉤子的析構函數被調用時,鉤子會檢查該節點是否已被插入到某個容器中。如果是,則鉤子將節點從容器中移除。
  • The hook has a member function called unlink() that can be used to unlink the node from the container at any time, without having any reference to the container, if the user wants to do so.
    鉤子具有一個名為 unlink() 的成員函數,它可用於隨時將節點從容器移除,而無需具有到容器的引用,如果用戶想這樣做的話。

These hooks have exactly the same size overhead as their analog non auto-unlinking hooks, but they have a restriction: they can only be used with non-constant time containers. There is a reason for this:
這些鉤子與非自斷鉤子具有完全相同的空間開銷,但是它們有一個限制:它們只能用於 非常量時間的容器。這是因為:

  • Auto-unlink hooks don't store any reference to the container where they are inserted.
    自斷鉤子並沒有保存任何到它們所插入的容器的引用。
  • Only containers with non constant-time size() allow removing an object from the container without referring to the container.
    只有帶有非常量時間 size() 的容器允許無需知道容器就可以從容器中移除一個對象。

This auto-unlink feature is useful in certain applications but it must be used very carefuly:
在特定的應用程序中,這個自斷鉤子特性是很有用的,但是必須非常小心地使用:

  • If several threads are using the same container the destructor of the auto-unlink hook will be called without any thread synchronization so removing the object is thread-unsafe.
    如果有多個線程使用同一個容器,由於自斷鉤子的析構函數被調用時沒有線程同步,所以移除對像不是線程安全的。
  • Container contents change silently without modifying the container directly. This can lead to surprising effects.
    容器的內容會未經直接修改容器就悄然改變。這可能會導致令人驚訝的效果。

These auto-unlink hooks have also safe-mode properties:
這些自斷鉤子也有安全模式屬性:

  • Hooks' constructors put the hook in a well-known default state.
    鉤子的構造函數將鉤子置於一個可知的缺省狀態。
  • Every time an object is inserted in the intrusive container, the container checks if the hook is in the well-known default state. If not, an assertion is raised.
    每當有對象被插入到介入式容器中時,容器檢查其鉤子是否處於缺省狀態。如否,則引發斷言。
  • Every time an object is erased from an intrusive container, the container puts the erased object in the well-known default state.
    每當從介入式容器移除對像時,容器將被移除對像重置回缺省狀態。

Let's see an example of an auto-unlink hook:
我們來看一個自斷鉤子的例子:

#include <boost/intrusive/list.hpp>
#include <cassert>
using namespace boost::intrusive;
typedef list_base_hook<link_mode<auto_unlink> > auto_unlink_hook;
class MyClass : public auto_unlink_hook
//This hook removes the node in the destructor 這個鉤子在析構函數中移除節點
{
int int_;
public:
MyClass(int i = 0) : int_(i) {}
void unlink() { auto_unlink_hook::unlink(); }
bool is_linked() { return auto_unlink_hook::is_linked(); }
};
//Define a list that will store values using the base hook
//The list can't have constant-time size!
//定義一個使用基類鉤子保存值的鏈表,該鏈表不能有常量時間的size函數!
typedef list< MyClass, constant_time_size<false> > List;
int main()
{
//Create the list 創建鏈表
List l;
{
//Create myclass and check it's linked 創建 myclass 並檢查是否已被鏈接
MyClass myclass;
assert(myclass.is_linked() == false);
//Insert the object 插入對像
l.push_back(myclass);
//Check that we have inserted the object 檢查我們是否已插入該對像
assert(l.empty() == false);
assert(&l.front() == &myclass);
assert(myclass.is_linked() == true);
//Now myclass' destructor will unlink it
//automatically 現在 myclass 的析構函數將自動斷開鏈接
}
//Check auto-unlink has been executed 檢查自動斷鏈是否已執行
assert(l.empty() == true);
{
//Now test the unlink() function 現在測試 unlink() 函數

//Create myclass and check it's linked 創建 myclass 並檢查是否已鏈接
MyClass myclass;
assert(myclass.is_linked() == false);
//Insert the object 插入對像
l.push_back(myclass);
//Check that we have inserted the object 檢查我們是否已插入該對像
assert(l.empty() == false);
assert(&l.front() == &myclass);
assert(myclass.is_linked() == true);
//Now unlink the node 現在斷開節點
myclass.unlink();
//Check auto-unlink has been executed 檢查自動斷鏈是否已執行
assert(l.empty() == true);
}
return 0;
}

As explained, Boost.Intrusive auto-unlink hooks are incompatible with containers that have constant-time size(), so if you try to define such container with an auto-unlink hook's value_traits, you will get a static assertion:
如上所說,Boost.Intrusive 自斷鉤子不能兼容於帶有常量時間 size() 的容器,因此,如果你想定義一個這樣的容器並帶有自斷鉤子 value_traits,你將得到一個靜態斷言:

#include <boost/intrusive/list.hpp>
using boost::intrusive;
struct MyTag;
class MyClass : public list_base_hook< link_mode<auto_unlink> >
{/**/};
list <MyClass, constant_time_size<true> > bad_list;
int main()
{
bad_list list;
return 0;
}

leads to an error similar to:
將引發一個如下的錯誤:

error : use of undefined type 'boost::STATIC_ASSERTION_FAILURE<false>'

Pointing to code like this:
指向如下代碼:

//Constant-time size is incompatible with auto-unlink hooks! 常量時間 size 不兼容於自斷鉤子!
BOOST_STATIC_ASSERT(!(constant_time_size && ((int)value_traits::link_mode == (int)auto_unlink)));

This way, there is no way to compile a program if you try to use auto-unlink hooks in constant-time size containers.
這樣,如果你試圖在一個帶有常量時間 size 函數的容器中使用自斷鉤子,則無法編譯程序。


PrevUpHomeNext