blob: 31a79bdf055bc384a4c93259bc87b51550b97a87 [file] [log] [blame]
// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#pragma once
#include "lib/fxl/logging.h"
namespace fbl {
namespace internal {
// ContainerPtrTraits specialization for std::unique_ptr. This allows fbl
// intrusive containers (fbl::DoublyLinkedList and fbl::SinglyLinkedList) to be
// used with std::unique_ptr.
//
// See:
// https://fuchsia.googlesource.com/zircon/+/master/system/ulib/fbl/include/fbl/intrusive_pointer_traits.h
template <typename T>
struct ContainerPtrTraits<::std::unique_ptr<T>> {
using ValueType = T;
using RefType = T&;
using ConstRefType = const T&;
using PtrType = ::std::unique_ptr<T>;
using ConstPtrType = ::std::unique_ptr<const T>;
using RawPtrType = T*;
using ConstRawPtrType = const T*;
static constexpr bool IsManaged = true;
static inline T* GetRaw(const PtrType& ptr) { return ptr.get(); }
static inline const T* GetRaw(const ConstPtrType& ptr) { return ptr.get(); }
static inline PtrType Take(PtrType& ptr) { return PtrType(fbl::move(ptr)); }
static inline void Swap(PtrType& first, PtrType& second) {
first.swap(second);
}
static constexpr PtrType MakeSentinel(void* sentinel) {
return PtrType(reinterpret_cast<RawPtrType>(
reinterpret_cast<uintptr_t>(sentinel) | kContainerSentinelBit));
}
static inline void DetachSentinel(PtrType& ptr) {
__UNUSED RawPtrType detached = ptr.release();
FXL_DCHECK((detached == nullptr) || IsSentinel(detached));
}
static constexpr bool IsSentinel(const PtrType& ptr) {
return IsSentinel(ptr.get());
}
static constexpr bool IsSentinel(RawPtrType ptr) {
return (reinterpret_cast<uintptr_t>(ptr) & kContainerSentinelBit) != 0;
}
static constexpr bool IsValid(const PtrType& ptr) {
return IsValid(ptr.get());
}
static constexpr bool IsValid(RawPtrType ptr) {
return ptr && !IsSentinel(ptr);
}
};
} // namespace internal
} // namespace fbl