gdbsupport/intrusive-list: sprinkle noexcept

Some methods of intrusive_list are marked noexcept.  But really,
everything in that file could be noexcept.  Add it everywhere.

The only one I had a doubt about is clear_and_dispose: what if the
disposer throws?  The boost equivalent [1] is noexcept and requires the
disposer not to throw.  The rationale is probably the same as for
destructors.  What if the disposer throws for an element in the middle
of the list?  Do you skip the remaining elements?  Do you swallow the
exception and keep calling the disposer for the remaining elements?
It's simpler to say no exceptions allowed.

[1] https://www.boost.org/doc/libs/1_79_0/doc/html/boost/intrusive/list.html#idm33710-bb

Change-Id: I402646cb12c6b7906f4bdc2ad85203d8c8cdf2cc
Reviewed-by: Keith Seitz <keiths@redhat.com>
This commit is contained in:
Simon Marchi 2024-08-12 13:09:02 -04:00
parent a1371f3288
commit 96917d0541

View File

@ -27,7 +27,7 @@ template<typename T>
class intrusive_list_node
{
public:
bool is_linked () const
bool is_linked () const noexcept
{
return next != INTRUSIVE_LIST_UNLINKED_VALUE;
}
@ -56,7 +56,7 @@ class intrusive_list_node
template<typename T>
struct intrusive_base_node
{
static intrusive_list_node<T> *as_node (T *elem)
static intrusive_list_node<T> *as_node (T *elem) noexcept
{ return elem; }
};
@ -65,7 +65,7 @@ struct intrusive_base_node
template<typename T, intrusive_list_node<T> T::*MemberNode>
struct intrusive_member_node
{
static intrusive_list_node<T> *as_node (T *elem)
static intrusive_list_node<T> *as_node (T *elem) noexcept
{ return &(elem->*MemberNode); }
};
@ -86,29 +86,29 @@ struct intrusive_list_base_iterator
using node_type = intrusive_list_node<T>;
/* Create an iterator pointing to ELEM. */
explicit intrusive_list_base_iterator (pointer elem)
explicit intrusive_list_base_iterator (pointer elem) noexcept
: m_elem (elem)
{}
/* Create a past-the-end iterator. */
intrusive_list_base_iterator ()
intrusive_list_base_iterator () noexcept
: m_elem (nullptr)
{}
reference operator* () const
reference operator* () const noexcept
{ return *m_elem; }
pointer operator-> () const
pointer operator-> () const noexcept
{ return m_elem; }
bool operator== (const self_type &other) const
bool operator== (const self_type &other) const noexcept
{ return m_elem == other.m_elem; }
bool operator!= (const self_type &other) const
bool operator!= (const self_type &other) const noexcept
{ return m_elem != other.m_elem; }
protected:
static node_type *as_node (pointer elem)
static node_type *as_node (pointer elem) noexcept
{ return AsNode::as_node (elem); }
/* A past-end-the iterator points to the list's head. */
@ -131,14 +131,14 @@ struct intrusive_list_iterator
using base::base;
using base::m_elem;
self_type &operator++ ()
self_type &operator++ () noexcept
{
node_type *node = this->as_node (m_elem);
m_elem = node->next;
return *this;
}
self_type operator++ (int)
self_type operator++ (int) noexcept
{
self_type temp = *this;
node_type *node = this->as_node (m_elem);
@ -146,14 +146,14 @@ struct intrusive_list_iterator
return temp;
}
self_type &operator-- ()
self_type &operator-- () noexcept
{
node_type *node = this->as_node (m_elem);
m_elem = node->prev;
return *this;
}
self_type operator-- (int)
self_type operator-- (int) noexcept
{
self_type temp = *this;
node_type *node = this->as_node (m_elem);
@ -178,14 +178,14 @@ struct intrusive_list_reverse_iterator
using base::m_elem;
using node_type = typename base::node_type;
self_type &operator++ ()
self_type &operator++ () noexcept
{
node_type *node = this->as_node (m_elem);
m_elem = node->prev;
return *this;
}
self_type operator++ (int)
self_type operator++ (int) noexcept
{
self_type temp = *this;
node_type *node = this->as_node (m_elem);
@ -193,14 +193,14 @@ struct intrusive_list_reverse_iterator
return temp;
}
self_type &operator-- ()
self_type &operator-- () noexcept
{
node_type *node = this->as_node (m_elem);
m_elem = node->next;
return *this;
}
self_type operator-- (int)
self_type operator-- (int) noexcept
{
self_type temp = *this;
node_type *node = this->as_node (m_elem);
@ -243,14 +243,14 @@ class intrusive_list
= const intrusive_list_reverse_iterator<T, AsNode>;
using node_type = intrusive_list_node<T>;
intrusive_list () = default;
intrusive_list () noexcept = default;
~intrusive_list ()
{
clear ();
}
intrusive_list (intrusive_list &&other)
intrusive_list (intrusive_list &&other) noexcept
: m_front (other.m_front),
m_back (other.m_back)
{
@ -258,7 +258,7 @@ class intrusive_list
other.m_back = nullptr;
}
intrusive_list &operator= (intrusive_list &&other)
intrusive_list &operator= (intrusive_list &&other) noexcept
{
m_front = other.m_front;
m_back = other.m_back;
@ -268,47 +268,47 @@ class intrusive_list
return *this;
}
void swap (intrusive_list &other)
void swap (intrusive_list &other) noexcept
{
std::swap (m_front, other.m_front);
std::swap (m_back, other.m_back);
}
iterator iterator_to (reference value)
iterator iterator_to (reference value) noexcept
{
return iterator (&value);
}
const_iterator iterator_to (const_reference value)
const_iterator iterator_to (const_reference value) noexcept
{
return const_iterator (&value);
}
reference front ()
reference front () noexcept
{
gdb_assert (!this->empty ());
return *m_front;
}
const_reference front () const
const_reference front () const noexcept
{
gdb_assert (!this->empty ());
return *m_front;
}
reference back ()
reference back () noexcept
{
gdb_assert (!this->empty ());
return *m_back;
}
const_reference back () const
const_reference back () const noexcept
{
gdb_assert (!this->empty ());
return *m_back;
}
void push_front (reference elem)
void push_front (reference elem) noexcept
{
intrusive_list_node<T> *elem_node = as_node (&elem);
@ -321,7 +321,7 @@ class intrusive_list
this->push_front_non_empty (elem);
}
void push_back (reference elem)
void push_back (reference elem) noexcept
{
intrusive_list_node<T> *elem_node = as_node (&elem);
@ -335,7 +335,7 @@ class intrusive_list
}
/* Inserts ELEM before POS. */
void insert (const_iterator pos, reference elem)
void insert (const_iterator pos, reference elem) noexcept
{
if (this->empty ())
return this->push_empty (elem);
@ -362,7 +362,7 @@ class intrusive_list
}
/* Move elements from LIST at the end of the current list. */
void splice (intrusive_list &&other)
void splice (intrusive_list &&other) noexcept
{
if (other.empty ())
return;
@ -388,13 +388,13 @@ class intrusive_list
other.m_back = nullptr;
}
void pop_front ()
void pop_front () noexcept
{
gdb_assert (!this->empty ());
erase_element (*m_front);
}
void pop_back ()
void pop_back () noexcept
{
gdb_assert (!this->empty ());
erase_element (*m_back);
@ -402,7 +402,7 @@ class intrusive_list
private:
/* Push ELEM in the list, knowing the list is empty. */
void push_empty (reference elem)
void push_empty (reference elem) noexcept
{
gdb_assert (this->empty ());
@ -418,7 +418,7 @@ class intrusive_list
}
/* Push ELEM at the front of the list, knowing the list is not empty. */
void push_front_non_empty (reference elem)
void push_front_non_empty (reference elem) noexcept
{
gdb_assert (!this->empty ());
@ -435,7 +435,7 @@ class intrusive_list
}
/* Push ELEM at the back of the list, knowing the list is not empty. */
void push_back_non_empty (reference elem)
void push_back_non_empty (reference elem) noexcept
{
gdb_assert (!this->empty ());
@ -451,7 +451,7 @@ class intrusive_list
m_back = &elem;
}
void erase_element (reference elem)
void erase_element (reference elem) noexcept
{
intrusive_list_node<T> *elem_node = as_node (&elem);
@ -489,7 +489,7 @@ class intrusive_list
public:
/* Remove the element pointed by I from the list. The element
pointed by I is not destroyed. */
iterator erase (const_iterator i)
iterator erase (const_iterator i) noexcept
{
iterator ret = i;
++ret;
@ -500,7 +500,7 @@ class intrusive_list
}
/* Erase all the elements. The elements are not destroyed. */
void clear ()
void clear () noexcept
{
while (!this->empty ())
pop_front ();
@ -509,7 +509,7 @@ class intrusive_list
/* Erase all the elements. Disposer::operator()(pointer) is called
for each of the removed elements. */
template<typename Disposer>
void clear_and_dispose (Disposer disposer)
void clear_and_dispose (Disposer disposer) noexcept
{
while (!this->empty ())
{
@ -519,7 +519,7 @@ class intrusive_list
}
}
bool empty () const
bool empty () const noexcept
{
return m_front == nullptr;
}
@ -585,7 +585,7 @@ class intrusive_list
}
private:
static node_type *as_node (pointer elem)
static node_type *as_node (pointer elem) noexcept
{
return AsNode::as_node (elem);
}