2019-05-22 20:15:35 +00:00
|
|
|
/*
|
2020-07-20 16:35:17 +00:00
|
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
2019-05-22 20:15:35 +00:00
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
2020-07-20 16:35:17 +00:00
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
2019-05-22 20:15:35 +00:00
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This file contains convenience aliases that make boost::intrusive::list
|
|
|
|
* easier to use.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <boost/intrusive/list.hpp>
|
|
|
|
|
|
|
|
namespace folly {
|
|
|
|
|
|
|
|
/**
|
|
|
|
* An auto-unlink intrusive list hook.
|
|
|
|
*/
|
|
|
|
using IntrusiveListHook = boost::intrusive::list_member_hook<
|
|
|
|
boost::intrusive::link_mode<boost::intrusive::auto_unlink>>;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* An intrusive list.
|
|
|
|
*
|
|
|
|
* An IntrusiveList always uses an auto-unlink hook.
|
|
|
|
* Beware that IntrusiveList::size() is an O(n) operation, since it has to walk
|
|
|
|
* the entire list.
|
|
|
|
*
|
|
|
|
* Example usage:
|
|
|
|
*
|
|
|
|
* class Foo {
|
|
|
|
* // Note that the listHook member variable needs to be visible
|
|
|
|
* // to the code that defines the IntrusiveList instantiation.
|
|
|
|
* // The list hook can be made public, or you can make the other class a
|
|
|
|
* // friend.
|
|
|
|
* IntrusiveListHook listHook;
|
|
|
|
* };
|
|
|
|
*
|
|
|
|
* using FooList = IntrusiveList<Foo, &Foo::listHook>;
|
|
|
|
*
|
|
|
|
* Foo *foo = new Foo();
|
|
|
|
* FooList myList;
|
|
|
|
* myList.push_back(*foo);
|
|
|
|
*
|
|
|
|
* Note that each IntrusiveListHook can only be part of a single list at any
|
|
|
|
* given time. If you need the same object to be stored in two lists at once,
|
|
|
|
* you need to use two different IntrusiveListHook member variables.
|
|
|
|
*
|
|
|
|
* The elements stored in the list must contain an IntrusiveListHook member
|
|
|
|
* variable.
|
|
|
|
*/
|
|
|
|
template <typename T, IntrusiveListHook T::*PtrToMember>
|
|
|
|
using IntrusiveList = boost::intrusive::list<
|
|
|
|
T,
|
|
|
|
boost::intrusive::member_hook<T, IntrusiveListHook, PtrToMember>,
|
|
|
|
boost::intrusive::constant_time_size<false>>;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* A safe-link intrusive list hook.
|
|
|
|
*/
|
|
|
|
using SafeIntrusiveListHook = boost::intrusive::list_member_hook<
|
|
|
|
boost::intrusive::link_mode<boost::intrusive::safe_link>>;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* An intrusive list with const-time size() method.
|
|
|
|
*
|
|
|
|
* A CountedIntrusiveList always uses a safe-link hook.
|
|
|
|
* CountedIntrusiveList::size() is an O(1) operation. Users of this type
|
|
|
|
* of lists need to remove a member from a list by calling one of the
|
|
|
|
* methods on the list (e.g., erase(), pop_front(), etc.), rather than
|
|
|
|
* calling unlink on the member's list hook. Given references to a
|
|
|
|
* list and a member, a constant-time removal operation can be
|
|
|
|
* accomplished by list.erase(list.iterator_to(member)). Also, when a
|
|
|
|
* member is destroyed, it is NOT automatically removed from the list.
|
|
|
|
*
|
|
|
|
* Example usage:
|
|
|
|
*
|
|
|
|
* class Foo {
|
|
|
|
* // Note that the listHook member variable needs to be visible
|
|
|
|
* // to the code that defines the CountedIntrusiveList instantiation.
|
|
|
|
* // The list hook can be made public, or you can make the other class a
|
|
|
|
* // friend.
|
|
|
|
* SafeIntrusiveListHook listHook;
|
|
|
|
* };
|
|
|
|
*
|
|
|
|
* using FooList = CountedIntrusiveList<Foo, &Foo::listHook> FooList;
|
|
|
|
*
|
|
|
|
* Foo *foo = new Foo();
|
|
|
|
* FooList myList;
|
|
|
|
* myList.push_back(*foo);
|
|
|
|
* myList.pop_front();
|
|
|
|
*
|
|
|
|
* Note that each SafeIntrusiveListHook can only be part of a single list at any
|
|
|
|
* given time. If you need the same object to be stored in two lists at once,
|
|
|
|
* you need to use two different SafeIntrusiveListHook member variables.
|
|
|
|
*
|
|
|
|
* The elements stored in the list must contain an SafeIntrusiveListHook member
|
|
|
|
* variable.
|
|
|
|
*/
|
|
|
|
template <typename T, SafeIntrusiveListHook T::*PtrToMember>
|
|
|
|
using CountedIntrusiveList = boost::intrusive::list<
|
|
|
|
T,
|
|
|
|
boost::intrusive::member_hook<T, SafeIntrusiveListHook, PtrToMember>,
|
|
|
|
boost::intrusive::constant_time_size<true>>;
|
|
|
|
|
|
|
|
} // namespace folly
|