[bt][common] Remove bt::LinkedList
Remove bt::LinkedList (aka fbl::DoublyLinkedList). Replace
remaining uses of LinkedList with std::list or std::queue.
While this does introduce allocations compared to intrusively
linked lists, it is necessary to move off of fbl.
Bug: 100658, 652
Test: fx test //src/connectivity/bluetooth/core/bt-host
Change-Id: I0a12c4ec12aa83fb8b37f7da54003407acfb50d0
Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/700073
Reviewed-by: Ali Saeed <saeedali@google.com>
Commit-Queue: Ben Lawson <benlawson@google.com>
diff --git a/pw_bluetooth_sapphire/host/att/bearer.h b/pw_bluetooth_sapphire/host/att/bearer.h
index 6969862..4847769 100644
--- a/pw_bluetooth_sapphire/host/att/bearer.h
+++ b/pw_bluetooth_sapphire/host/att/bearer.h
@@ -19,7 +19,6 @@
#include "src/connectivity/bluetooth/core/bt-host/att/error.h"
#include "src/connectivity/bluetooth/core/bt-host/att/packet.h"
#include "src/connectivity/bluetooth/core/bt-host/common/byte_buffer.h"
-#include "src/connectivity/bluetooth/core/bt-host/common/linked_list.h"
#include "src/connectivity/bluetooth/core/bt-host/common/packet_view.h"
#include "src/connectivity/bluetooth/core/bt-host/l2cap/channel.h"
#include "src/connectivity/bluetooth/core/bt-host/l2cap/scoped_channel.h"
diff --git a/pw_bluetooth_sapphire/host/att/database.h b/pw_bluetooth_sapphire/host/att/database.h
index b36c364..9e4bb2f 100644
--- a/pw_bluetooth_sapphire/host/att/database.h
+++ b/pw_bluetooth_sapphire/host/att/database.h
@@ -154,10 +154,6 @@
// The list of groupings is sorted by handle where each grouping maps to a
// non-overlapping handle range. Successive groupings don't necessarily
// represent contiguous handle ranges as any grouping can be removed.
- //
- // Note: This uses a std::list because std::lower_bound doesn't work with a
- // LinkedList (aka fbl::DoublyLinkedList). This is only marginally
- // less space efficient.
GroupingList groupings_;
fxl::WeakPtrFactory<Database> weak_ptr_factory_;
diff --git a/pw_bluetooth_sapphire/host/common/BUILD.gn b/pw_bluetooth_sapphire/host/common/BUILD.gn
index 5a7b953..742761c 100644
--- a/pw_bluetooth_sapphire/host/common/BUILD.gn
+++ b/pw_bluetooth_sapphire/host/common/BUILD.gn
@@ -24,7 +24,6 @@
"identifier.cc",
"identifier.h",
"inspectable.h",
- "linked_list.h",
"log.cc",
"log.h",
"manufacturer_names.cc",
diff --git a/pw_bluetooth_sapphire/host/common/linked_list.h b/pw_bluetooth_sapphire/host/common/linked_list.h
deleted file mode 100644
index 575a76f..0000000
--- a/pw_bluetooth_sapphire/host/common/linked_list.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// 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.
-
-#ifndef SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_COMMON_LINKED_LIST_H_
-#define SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_COMMON_LINKED_LIST_H_
-
-#include <memory>
-
-#include <fbl/intrusive_double_list.h>
-
-namespace bt {
-
-// TODO(armansito): Use this in more places where it makes sense (see fxbug.dev/652).
-
-// Convenience template aliases for an fbl intrusive container backed
-// LinkedList.
-//
-// * Elements need to be dynamically allocated and entries MUST be managed
-// pointers.
-//
-// * This is currently implemented as a doubly linked-list. This adds extra
-// storage overhead but makes it suitable for FIFO queues.
-
-template <typename T>
-using LinkedList = fbl::DoublyLinkedList<std::unique_ptr<T>>;
-
-template <typename T>
-using LinkedListable = fbl::DoublyLinkedListable<std::unique_ptr<T>>;
-
-} // namespace bt
-
-#endif // SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_COMMON_LINKED_LIST_H_
diff --git a/pw_bluetooth_sapphire/host/l2cap/channel_manager.cc b/pw_bluetooth_sapphire/host/l2cap/channel_manager.cc
index 52bedc2..5a2ac73 100644
--- a/pw_bluetooth_sapphire/host/l2cap/channel_manager.cc
+++ b/pw_bluetooth_sapphire/host/l2cap/channel_manager.cc
@@ -98,7 +98,7 @@
// Stores packets received on a connection handle before a link for it has
// been created.
using PendingPacketMap =
- std::unordered_map<hci_spec::ConnectionHandle, LinkedList<hci::ACLDataPacket>>;
+ std::unordered_map<hci_spec::ConnectionHandle, std::queue<hci::ACLDataPacketPtr>>;
PendingPacketMap pending_packets_;
// Store information required to create and forward channels for locally-
@@ -305,7 +305,7 @@
// If a LogicalLink does not exist, we set up a queue for its packets to be
// delivered when the LogicalLink gets created.
if (iter == ll_map_.end()) {
- pp_iter = pending_packets_.emplace(handle, LinkedList<hci::ACLDataPacket>()).first;
+ pp_iter = pending_packets_.emplace(handle, std::queue<hci::ACLDataPacketPtr>()).first;
} else {
// A logical link exists. |pp_iter| will be valid only if the drain task has
// not run yet (see ChannelManagerImpl::RegisterInternal()).
@@ -315,7 +315,7 @@
if (pp_iter != pending_packets_.end()) {
packet->set_trace_id(TRACE_NONCE());
TRACE_FLOW_BEGIN("bluetooth", "ChannelMaager::OnDataReceived queued", packet->trace_id());
- pp_iter->second.push_back(std::move(packet));
+ pp_iter->second.push(std::move(packet));
bt_log(TRACE, "l2cap", "queued rx packet on handle: %#.4x", handle);
return;
}
@@ -346,8 +346,9 @@
auto pp_iter = pending_packets_.find(handle);
if (pp_iter != pending_packets_.end()) {
auto& packets = pp_iter->second;
- while (!packets.is_empty()) {
- auto packet = packets.pop_front();
+ while (!packets.empty()) {
+ auto packet = std::move(packets.front());
+ packets.pop();
TRACE_FLOW_END("bluetooth", "ChannelManagerImpl::OnDataReceived queued", packet->trace_id());
ll->HandleRxPacket(std::move(packet));
}
diff --git a/pw_bluetooth_sapphire/host/l2cap/channel_manager_unittest.cc b/pw_bluetooth_sapphire/host/l2cap/channel_manager_unittest.cc
index a4e4fa8..f445191 100644
--- a/pw_bluetooth_sapphire/host/l2cap/channel_manager_unittest.cc
+++ b/pw_bluetooth_sapphire/host/l2cap/channel_manager_unittest.cc
@@ -451,10 +451,10 @@
CommandId NextCommandId() { return next_command_id_++; }
private:
- bool SendPackets(LinkedList<hci::ACLDataPacket> packets, ChannelId channel_id,
+ bool SendPackets(std::list<hci::ACLDataPacketPtr> packets, ChannelId channel_id,
hci::AclDataChannel::PacketPriority priority) {
for (const auto& packet : packets) {
- const ByteBuffer& data = packet.view().data();
+ const ByteBuffer& data = packet->view().data();
if (expected_packets_.empty()) {
ADD_FAILURE() << "Unexpected outbound ACL data";
std::cout << "{ ";
@@ -484,7 +484,7 @@
expected_packets_.pop();
}
}
- return !packets.is_empty();
+ return !packets.empty();
}
std::unique_ptr<ChannelManager> chanmgr_;
diff --git a/pw_bluetooth_sapphire/host/l2cap/fragmenter_unittest.cc b/pw_bluetooth_sapphire/host/l2cap/fragmenter_unittest.cc
index 2ac19fc..b1faf8a 100644
--- a/pw_bluetooth_sapphire/host/l2cap/fragmenter_unittest.cc
+++ b/pw_bluetooth_sapphire/host/l2cap/fragmenter_unittest.cc
@@ -187,7 +187,7 @@
auto fragments = pdu.ReleaseFragments();
- EXPECT_TRUE(ContainersEqual(expected_fragment, fragments.begin()->view().data()));
+ EXPECT_TRUE(ContainersEqual(expected_fragment, (*fragments.begin())->view().data()));
}
TEST(FragmenterTest, SingleFragment) {
@@ -208,7 +208,7 @@
auto fragments = pdu.ReleaseFragments();
- EXPECT_TRUE(ContainersEqual(expected_fragment, fragments.begin()->view().data()));
+ EXPECT_TRUE(ContainersEqual(expected_fragment, (*fragments.begin())->view().data()));
}
TEST(FragmenterTest, SingleFragmentExactFit) {
@@ -230,7 +230,7 @@
auto fragments = pdu.ReleaseFragments();
- EXPECT_TRUE(ContainersEqual(expected_fragment, fragments.begin()->view().data()));
+ EXPECT_TRUE(ContainersEqual(expected_fragment, (*fragments.begin())->view().data()));
}
TEST(FragmenterTest, TwoFragmentsOffByOne) {
@@ -260,8 +260,8 @@
auto fragments = pdu.ReleaseFragments();
- EXPECT_TRUE(ContainersEqual(expected_fragment0, fragments.begin()->view().data()));
- EXPECT_TRUE(ContainersEqual(expected_fragment1, (++fragments.begin())->view().data()));
+ EXPECT_TRUE(ContainersEqual(expected_fragment0, (*fragments.begin())->view().data()));
+ EXPECT_TRUE(ContainersEqual(expected_fragment1, (*++fragments.begin())->view().data()));
}
TEST(FragmenterTest, TwoFragmentsExact) {
@@ -292,8 +292,8 @@
auto fragments = pdu.ReleaseFragments();
- EXPECT_TRUE(ContainersEqual(expected_fragment0, fragments.begin()->view().data()));
- EXPECT_TRUE(ContainersEqual(expected_fragment1, (++fragments.begin())->view().data()));
+ EXPECT_TRUE(ContainersEqual(expected_fragment0, (*fragments.begin())->view().data()));
+ EXPECT_TRUE(ContainersEqual(expected_fragment1, (*++fragments.begin())->view().data()));
}
TEST(FragmenterTest, ManyFragmentsOffByOne) {
@@ -339,10 +339,10 @@
auto fragments = pdu.ReleaseFragments();
auto iter = fragments.begin();
- EXPECT_TRUE(ContainersEqual(expected_fragment0, (iter++)->view().data()));
- EXPECT_TRUE(ContainersEqual(expected_fragment1, (iter++)->view().data()));
- EXPECT_TRUE(ContainersEqual(expected_fragment2, (iter++)->view().data()));
- EXPECT_TRUE(ContainersEqual(expected_fragment3, iter->view().data()));
+ EXPECT_TRUE(ContainersEqual(expected_fragment0, (*iter++)->view().data()));
+ EXPECT_TRUE(ContainersEqual(expected_fragment1, (*iter++)->view().data()));
+ EXPECT_TRUE(ContainersEqual(expected_fragment2, (*iter++)->view().data()));
+ EXPECT_TRUE(ContainersEqual(expected_fragment3, (*iter)->view().data()));
}
TEST(FragmenterTest, MaximalSizedPayload) {
@@ -389,9 +389,9 @@
auto fragments = pdu.ReleaseFragments();
auto iter = fragments.begin();
- EXPECT_TRUE(ContainersEqual(expected_fragment0, (iter++)->view().data()));
- EXPECT_TRUE(ContainersEqual(expected_fragment1, (iter++)->view().data()));
- EXPECT_TRUE(ContainersEqual(expected_fragment2, (iter++)->view().data()));
+ EXPECT_TRUE(ContainersEqual(expected_fragment0, (*iter++)->view().data()));
+ EXPECT_TRUE(ContainersEqual(expected_fragment1, (*iter++)->view().data()));
+ EXPECT_TRUE(ContainersEqual(expected_fragment2, (*iter++)->view().data()));
}
} // namespace
diff --git a/pw_bluetooth_sapphire/host/l2cap/logical_link.cc b/pw_bluetooth_sapphire/host/l2cap/logical_link.cc
index e5ef687..ad73daa 100644
--- a/pw_bluetooth_sapphire/host/l2cap/logical_link.cc
+++ b/pw_bluetooth_sapphire/host/l2cap/logical_link.cc
@@ -254,7 +254,7 @@
PDU pdu = fragmenter_.BuildFrame(id, payload, fcs_option, flushable);
auto fragments = pdu.ReleaseFragments();
- ZX_ASSERT(!fragments.is_empty());
+ ZX_ASSERT(!fragments.empty());
acl_data_channel_->SendPackets(std::move(fragments), id, ChannelPriority(id));
}
diff --git a/pw_bluetooth_sapphire/host/l2cap/pdu.cc b/pw_bluetooth_sapphire/host/l2cap/pdu.cc
index 15f40c1..f4174c7 100644
--- a/pw_bluetooth_sapphire/host/l2cap/pdu.cc
+++ b/pw_bluetooth_sapphire/host/l2cap/pdu.cc
@@ -9,17 +9,13 @@
namespace bt::l2cap {
-PDU::PDU() : fragment_count_(0u) {}
-
// NOTE: The order in which these are initialized matters, as
// other.ReleaseFragments() resets |other.fragment_count_|.
-PDU::PDU(PDU&& other)
- : fragment_count_(other.fragment_count_), fragments_(other.ReleaseFragments()) {}
+PDU::PDU(PDU&& other) : fragments_(other.ReleaseFragments()) {}
PDU& PDU::operator=(PDU&& other) {
// NOTE: The order in which these are initialized matters, as
// other.ReleaseFragments() resets |other.fragment_count_|.
- fragment_count_ = other.fragment_count_;
fragments_ = other.ReleaseFragments();
return *this;
}
@@ -38,7 +34,7 @@
bool found = false;
size_t offset = 0u;
for (auto iter = fragments_.begin(); iter != fragments_.end() && remaining; ++iter) {
- auto payload = iter->view().payload_data();
+ auto payload = (*iter)->view().payload_data();
// Skip the Basic L2CAP header for the first fragment.
if (iter == fragments_.begin()) {
@@ -77,27 +73,25 @@
PDU::FragmentList PDU::ReleaseFragments() {
auto out_list = std::move(fragments_);
- fragment_count_ = 0u;
ZX_DEBUG_ASSERT(!is_valid());
return out_list;
}
const BasicHeader& PDU::basic_header() const {
- ZX_DEBUG_ASSERT(!fragments_.is_empty());
+ ZX_DEBUG_ASSERT(!fragments_.empty());
const auto& fragment = *fragments_.begin();
- ZX_DEBUG_ASSERT(fragment.packet_boundary_flag() !=
+ ZX_DEBUG_ASSERT(fragment->packet_boundary_flag() !=
hci_spec::ACLPacketBoundaryFlag::kContinuingFragment);
- return fragment.view().payload<BasicHeader>();
+ return fragment->view().payload<BasicHeader>();
}
void PDU::AppendFragment(hci::ACLDataPacketPtr fragment) {
ZX_DEBUG_ASSERT(fragment);
ZX_DEBUG_ASSERT(!is_valid() ||
- fragments_.begin()->connection_handle() == fragment->connection_handle());
+ (*fragments_.begin())->connection_handle() == fragment->connection_handle());
fragments_.push_back(std::move(fragment));
- fragment_count_++;
}
} // namespace bt::l2cap
diff --git a/pw_bluetooth_sapphire/host/l2cap/pdu.h b/pw_bluetooth_sapphire/host/l2cap/pdu.h
index 445b375..6e91953 100644
--- a/pw_bluetooth_sapphire/host/l2cap/pdu.h
+++ b/pw_bluetooth_sapphire/host/l2cap/pdu.h
@@ -8,6 +8,8 @@
#include <endian.h>
#include <zircon/assert.h>
+#include <list>
+
#include <fbl/intrusive_double_list.h>
#include <fbl/macros.h>
@@ -24,19 +26,13 @@
// packet. A PDU cannot be populated directly and must be obtained from a
// Recombiner or Fragmenter.
//
-// A PDU instance is light-weight (it consists of a single unique_ptr via
-// LinkedList and a size_t field) and can be passed around by value.
+// A PDU instance is light-weight and can be passed around by value.
// As the PDU uniquely owns its chain of fragments, a PDU is move-only.
-//
-// THREAD-SAFETY:
-//
-// This class is not thread-safe. External locking should be provided if an
-// instance will be accessed on multiple threads.
class PDU final {
public:
- using FragmentList = LinkedList<hci::ACLDataPacket>;
+ using FragmentList = std::list<hci::ACLDataPacketPtr>;
- PDU();
+ PDU() = default;
~PDU() = default;
// Allow move operations.
@@ -45,14 +41,10 @@
// An unpopulated PDU is considered invalid, which is the default-constructed
// state.
- bool is_valid() const {
- ZX_DEBUG_ASSERT(fragments_.is_empty() && !fragment_count_ ||
- !fragments_.is_empty() && fragment_count_);
- return !fragments_.is_empty();
- }
+ bool is_valid() const { return !fragments_.empty(); }
// The number of ACL data fragments that are currently a part of this PDU.
- size_t fragment_count() const { return fragment_count_; }
+ size_t fragment_count() const { return fragments_.size(); }
// Returns the number of bytes that are currently contained in this PDU,
// excluding the Basic L2CAP header.
@@ -65,7 +57,7 @@
// for.
hci_spec::ConnectionHandle connection_handle() const {
ZX_DEBUG_ASSERT(is_valid());
- return fragments_.begin()->connection_handle();
+ return (*fragments_.begin())->connection_handle();
}
// This method will attempt to read |size| bytes of the basic-frame
@@ -104,9 +96,6 @@
// assumes that validity checks on |fragment| have already been performed.
void AppendFragment(hci::ACLDataPacketPtr fragment);
- // The number of fragments currently stored in this PDU.
- size_t fragment_count_;
-
// ACL data fragments that currently form this PDU. In a complete PDU, it is
// expected that the sum of the payload sizes of all elements in |fragments_|
// is equal to the length of the frame (i.e. length() + sizeof(BasicHeader)).
diff --git a/pw_bluetooth_sapphire/host/l2cap/pdu_unittest.cc b/pw_bluetooth_sapphire/host/l2cap/pdu_unittest.cc
index c75655d..6e75f18 100644
--- a/pw_bluetooth_sapphire/host/l2cap/pdu_unittest.cc
+++ b/pw_bluetooth_sapphire/host/l2cap/pdu_unittest.cc
@@ -128,7 +128,7 @@
auto fragments = pdu.ReleaseFragments();
EXPECT_FALSE(pdu.is_valid());
- ASSERT_FALSE(fragments.is_empty());
+ ASSERT_FALSE(fragments.empty());
EXPECT_EQ(0u, pdu.fragment_count());
// Directly count the elements in |fragments| to make sure the count is
@@ -145,7 +145,7 @@
// Basic l2cap header
0x04, 0x00, 0xFF, 0xFF, 'T', 'e', 's', 't'),
- fragments.begin()->view().data()));
+ (*fragments.begin())->view().data()));
}
TEST(PduTest, ReadSingleFragment) {
diff --git a/pw_bluetooth_sapphire/host/l2cap/recombiner_unittest.cc b/pw_bluetooth_sapphire/host/l2cap/recombiner_unittest.cc
index d7e3154..494a7a6 100644
--- a/pw_bluetooth_sapphire/host/l2cap/recombiner_unittest.cc
+++ b/pw_bluetooth_sapphire/host/l2cap/recombiner_unittest.cc
@@ -81,7 +81,7 @@
auto fragments = pdu.ReleaseFragments();
size_t sum = 0;
for (const auto& f : fragments) {
- sum += f.view().payload_size();
+ sum += f->view().payload_size();
}
EXPECT_EQ(expected_payload.length() + sizeof(BasicHeader), sum);
}
diff --git a/pw_bluetooth_sapphire/host/socket/socket_channel_relay.h b/pw_bluetooth_sapphire/host/socket/socket_channel_relay.h
index b4fe30a..094410f 100644
--- a/pw_bluetooth_sapphire/host/socket/socket_channel_relay.h
+++ b/pw_bluetooth_sapphire/host/socket/socket_channel_relay.h
@@ -160,7 +160,6 @@
// SDU). This comes, however, at the cost of higher memory usage when the
// number of SDUs is small. (libc++ uses a minimum of 4KB per deque.)
//
- // TODO(fxbug.dev/670): Switch to LinkedList.
// TODO(fxbug.dev/709): We should set an upper bound on the size of this queue.
std::deque<ByteBufferPtr> socket_write_queue_;
diff --git a/pw_bluetooth_sapphire/host/transport/acl_data_channel.cc b/pw_bluetooth_sapphire/host/transport/acl_data_channel.cc
index c3895af..3c010c1 100644
--- a/pw_bluetooth_sapphire/host/transport/acl_data_channel.cc
+++ b/pw_bluetooth_sapphire/host/transport/acl_data_channel.cc
@@ -40,7 +40,7 @@
void SetDataRxHandler(ACLPacketHandler rx_callback) override;
bool SendPacket(ACLDataPacketPtr data_packet, UniqueChannelId channel_id,
PacketPriority priority) override;
- bool SendPackets(LinkedList<ACLDataPacket> packets, UniqueChannelId channel_id,
+ bool SendPackets(std::list<ACLDataPacketPtr> packets, UniqueChannelId channel_id,
PacketPriority priority) override;
void RegisterLink(hci_spec::ConnectionHandle handle, bt::LinkType ll_type) override;
void UnregisterLink(hci_spec::ConnectionHandle handle) override;
@@ -220,10 +220,6 @@
// TODO(armansito): Use priority_queue based on L2CAP channel priority.
// TODO(fxbug.dev/944): Keep a separate queue for each open connection. Benefits:
// * Helps address the packet-prioritization TODO above.
- // * Also: having separate queues, which know their own
- // bt::LinkType, would let us replace std::list<QueuedDataPacket>
- // with LinkedList<ACLDataPacket> which has a more efficient
- // memory layout.
using InspectableDataPacketQueue = Inspectable<DataPacketQueue, inspect::UintProperty, size_t>;
InspectableDataPacketQueue send_queue_{std::mem_fn(&DataPacketQueue::size)};
@@ -290,7 +286,6 @@
}
AclDataChannelImpl::~AclDataChannelImpl() {
-
bt_log(INFO, "hci", "AclDataChannel shutting down");
transport_->command_channel()->RemoveEventHandler(num_completed_packets_event_handler_id_);
@@ -331,23 +326,23 @@
bool AclDataChannelImpl::SendPacket(ACLDataPacketPtr data_packet, UniqueChannelId channel_id,
PacketPriority priority) {
ZX_ASSERT(data_packet);
- LinkedList<ACLDataPacket> packets;
+ std::list<ACLDataPacketPtr> packets;
packets.push_back(std::move(data_packet));
return SendPackets(std::move(packets), channel_id, priority);
}
-bool AclDataChannelImpl::SendPackets(LinkedList<ACLDataPacket> packets, UniqueChannelId channel_id,
- PacketPriority priority) {
- if (packets.is_empty()) {
+bool AclDataChannelImpl::SendPackets(std::list<ACLDataPacketPtr> packets,
+ UniqueChannelId channel_id, PacketPriority priority) {
+ if (packets.empty()) {
bt_log(DEBUG, "hci", "no packets to send!");
return false;
}
- auto handle = packets.front().connection_handle();
+ auto handle = packets.front()->connection_handle();
if (registered_links_.find(handle) == registered_links_.end()) {
bt_log(TRACE, "hci", "dropping packets for unregistered connection (handle: %#.4x, count: %lu)",
- handle, packets.size_slow());
+ handle, packets.size());
return false;
}
@@ -355,27 +350,28 @@
// continuing fragment at the head. There is no check for whether |packets| have enough data to
// form whole PDUs because queue management doesn't require that and it would break abstraction
// even more.
- ZX_ASSERT_MSG(packets.front().packet_boundary_flag() !=
+ ZX_ASSERT_MSG(packets.front()->packet_boundary_flag() !=
hci_spec::ACLPacketBoundaryFlag::kContinuingFragment,
"expected full PDU");
for (const auto& packet : packets) {
// This call assumes that all packets in each call are for the same connection
- ZX_ASSERT_MSG(packet.connection_handle() == handle,
+ ZX_ASSERT_MSG(packet->connection_handle() == handle,
"expected only fragments for one connection (%#.4x, got %#.4x)", handle,
- packet.connection_handle());
+ packet->connection_handle());
// Make sure that all packets are within the MTU.
- if (packet.view().payload_size() >
- GetBufferMtu(registered_links_[packet.connection_handle()])) {
+ if (packet->view().payload_size() >
+ GetBufferMtu(registered_links_[packet->connection_handle()])) {
bt_log(ERROR, "hci", "ACL data packet too large!");
return false;
}
}
auto insert_iter = SendQueueInsertLocationForPriority(priority);
- for (int i = 0; !packets.is_empty(); i++) {
- auto packet = packets.pop_front();
+ for (int i = 0; !packets.empty(); i++) {
+ auto packet = std::move(packets.front());
+ packets.pop_front();
auto ll_type = registered_links_[packet->connection_handle()];
const size_t payload_size = packet->view().payload_size();
auto queue_packet = QueuedDataPacket(ll_type, channel_id, priority, std::move(packet),
diff --git a/pw_bluetooth_sapphire/host/transport/acl_data_channel.h b/pw_bluetooth_sapphire/host/transport/acl_data_channel.h
index 863b978..f20c568 100644
--- a/pw_bluetooth_sapphire/host/transport/acl_data_channel.h
+++ b/pw_bluetooth_sapphire/host/transport/acl_data_channel.h
@@ -111,7 +111,7 @@
// |priority| indicates the order this packet should be dispatched off of the queue relative to
// packets of other priorities. Note that high priority packets may still wait behind low priority
// packets that have already been sent to the controller.
- virtual bool SendPackets(LinkedList<ACLDataPacket> packets, UniqueChannelId channel_id,
+ virtual bool SendPackets(std::list<ACLDataPacketPtr> packets, UniqueChannelId channel_id,
PacketPriority priority) = 0;
// Allowlist packets destined for the link identified by |handle| (of link type |ll_type|) for
diff --git a/pw_bluetooth_sapphire/host/transport/acl_data_channel_unittest.cc b/pw_bluetooth_sapphire/host/transport/acl_data_channel_unittest.cc
index 08f6de0..3ab3854 100644
--- a/pw_bluetooth_sapphire/host/transport/acl_data_channel_unittest.cc
+++ b/pw_bluetooth_sapphire/host/transport/acl_data_channel_unittest.cc
@@ -375,11 +375,12 @@
acl_data_channel()->RegisterLink(kHandle, bt::LinkType::kACL);
// Empty packet list.
- EXPECT_FALSE(acl_data_channel()->SendPackets(
- LinkedList<ACLDataPacket>(), l2cap::kInvalidChannelId, AclDataChannel::PacketPriority::kLow));
+ EXPECT_FALSE(acl_data_channel()->SendPackets(std::list<ACLDataPacketPtr>(),
+ l2cap::kInvalidChannelId,
+ AclDataChannel::PacketPriority::kLow));
// Packet exceeds MTU
- LinkedList<ACLDataPacket> packets;
+ std::list<ACLDataPacketPtr> packets;
packets.push_back(ACLDataPacket::New(kHandle, hci_spec::ACLPacketBoundaryFlag::kFirstNonFlushable,
hci_spec::ACLBroadcastFlag::kPointToPoint, kMaxMTU + 1));
EXPECT_FALSE(acl_data_channel()->SendPackets(std::move(packets), l2cap::kInvalidChannelId,
@@ -396,7 +397,7 @@
acl_data_channel()->RegisterLink(kHandle, bt::LinkType::kACL);
- LinkedList<ACLDataPacket> packets;
+ std::list<ACLDataPacketPtr> packets;
packets.push_back(ACLDataPacket::New(kHandle,
hci_spec::ACLPacketBoundaryFlag::kContinuingFragment,
hci_spec::ACLBroadcastFlag::kPointToPoint, kMaxMTU));
@@ -416,7 +417,7 @@
acl_data_channel()->RegisterLink(kHandle1, bt::LinkType::kACL);
// Packet exceeds MTU
- LinkedList<ACLDataPacket> packets;
+ std::list<ACLDataPacketPtr> packets;
packets.push_back(ACLDataPacket::New(kHandle0,
hci_spec::ACLPacketBoundaryFlag::kFirstNonFlushable,
hci_spec::ACLBroadcastFlag::kPointToPoint, kMaxMTU));
@@ -456,7 +457,7 @@
};
test_device()->SetDataCallback(data_cb, dispatcher());
- LinkedList<ACLDataPacket> packets;
+ std::list<ACLDataPacketPtr> packets;
for (int i = 1; i <= kExpectedPacketCount; ++i) {
auto packet = ACLDataPacket::New(kHandle, hci_spec::ACLPacketBoundaryFlag::kFirstNonFlushable,
hci_spec::ACLBroadcastFlag::kPointToPoint, 1);
@@ -1318,7 +1319,7 @@
// Send enough data that the first PDU sent in this loop gets dropped
for (size_t i = 0; i < AclDataChannel::kMaxAclPacketsPerChannel + 1; ++i) {
// Send two fragments per PDU
- LinkedList<ACLDataPacket> packets;
+ std::list<ACLDataPacketPtr> packets;
for (auto pbf : {hci_spec::ACLPacketBoundaryFlag::kFirstNonFlushable,
hci_spec::ACLPacketBoundaryFlag::kContinuingFragment}) {
auto packet =
diff --git a/pw_bluetooth_sapphire/host/transport/mock_acl_data_channel.h b/pw_bluetooth_sapphire/host/transport/mock_acl_data_channel.h
index 438b929..fc3f919 100644
--- a/pw_bluetooth_sapphire/host/transport/mock_acl_data_channel.h
+++ b/pw_bluetooth_sapphire/host/transport/mock_acl_data_channel.h
@@ -19,7 +19,7 @@
void set_le_buffer_info(DataBufferInfo info) { le_buffer_info_ = info; }
using SendPacketsCallback = fit::function<bool(
- LinkedList<ACLDataPacket> packets, UniqueChannelId channel_id, PacketPriority priority)>;
+ std::list<ACLDataPacketPtr> packets, UniqueChannelId channel_id, PacketPriority priority)>;
void set_send_packets_cb(SendPacketsCallback cb) { send_packets_cb_ = std::move(cb); }
using DropQueuedPacketsCallback = fit::function<void(AclPacketPredicate predicate)>;
@@ -55,7 +55,7 @@
PacketPriority priority) override {
return false;
}
- bool SendPackets(LinkedList<ACLDataPacket> packets, UniqueChannelId channel_id,
+ bool SendPackets(std::list<ACLDataPacketPtr> packets, UniqueChannelId channel_id,
PacketPriority priority) override {
if (send_packets_cb_) {
return send_packets_cb_(std::move(packets), channel_id, priority);
diff --git a/pw_bluetooth_sapphire/host/transport/packet.h b/pw_bluetooth_sapphire/host/transport/packet.h
index e93a8f9..084ae11 100644
--- a/pw_bluetooth_sapphire/host/transport/packet.h
+++ b/pw_bluetooth_sapphire/host/transport/packet.h
@@ -12,7 +12,6 @@
#include <fbl/macros.h>
#include "src/connectivity/bluetooth/core/bt-host/common/byte_buffer.h"
-#include "src/connectivity/bluetooth/core/bt-host/common/linked_list.h"
#include "src/connectivity/bluetooth/core/bt-host/common/packet_view.h"
namespace bt::hci {
@@ -88,11 +87,10 @@
//
// Packet is NOT thread-safe without external locking.
-// PacketBase provides basic view functionality and intrusively
-// linked-listability. Intended to be inherited by the Packet template and all
-// of its specializations.
+// PacketBase provides basic view functionality. Intended to be inherited by the Packet template and
+// all of its specializations.
template <typename HeaderType, typename T>
-class PacketBase : public LinkedListable<T> {
+class PacketBase {
public:
virtual ~PacketBase() = default;
diff --git a/pw_bluetooth_sapphire/host/transport/slab_allocators_unittest.cc b/pw_bluetooth_sapphire/host/transport/slab_allocators_unittest.cc
index 9dc0f61..a57ada6 100644
--- a/pw_bluetooth_sapphire/host/transport/slab_allocators_unittest.cc
+++ b/pw_bluetooth_sapphire/host/transport/slab_allocators_unittest.cc
@@ -5,6 +5,7 @@
#include "slab_allocators.h"
#include <forward_list>
+#include <list>
#include <gtest/gtest.h>
@@ -32,7 +33,7 @@
TEST(SlabAllocatorsTest, CommandPacketFallBack) {
size_t num_packets = 0;
- LinkedList<Packet<hci_spec::CommandHeader>> packets;
+ std::list<std::unique_ptr<hci::CommandPacket>> packets;
// Allocate a lot of small packets. We should be able to allocate two
// allocators' worth of packets until we fail.
@@ -68,7 +69,7 @@
kMaxNumSlabs * kNumMediumACLDataPackets +
kMaxNumSlabs * kNumLargeACLDataPackets;
const size_t kPayloadSize = 5;
- LinkedList<Packet<hci_spec::ACLDataHeader>> packets;
+ std::list<hci::ACLDataPacketPtr> packets;
for (size_t num_packets = 0; num_packets < kMaxSlabPackets; num_packets++) {
auto packet = ACLDataPacket::New(kPayloadSize);
@@ -91,7 +92,7 @@
// Maximum number of packets we can expect to obtain from the large slab allocator.
const size_t kMaxSlabPackets = kMaxNumSlabs * kNumLargeACLDataPackets;
const size_t kPayloadSize = kLargeACLDataPayloadSize;
- LinkedList<Packet<hci_spec::ACLDataHeader>> packets;
+ std::list<hci::ACLDataPacketPtr> packets;
for (size_t num_packets = 0; num_packets < kMaxSlabPackets; num_packets++) {
auto packet = ACLDataPacket::New(kPayloadSize);