From fe0298a2905121a02ee64f429e9f88148d17c6ee Mon Sep 17 00:00:00 2001 From: Frediano Ziglio Date: Fri, 6 Mar 2020 04:03:24 +0000 Subject: [PATCH] safe-list: Add a class to implement a list with safe iterators The reason to not using STL is that our code from how was designed requires the iterator to be safe to the delete of the element pointed by the iterator. Signed-off-by: Frediano Ziglio --- server/Makefile.am | 1 + server/meson.build | 1 + server/safe-list.hpp | 115 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 117 insertions(+) create mode 100644 server/safe-list.hpp diff --git a/server/Makefile.am b/server/Makefile.am index edecf6c5..ab5ba8e1 100644 --- a/server/Makefile.am +++ b/server/Makefile.am @@ -97,6 +97,7 @@ libserver_la_SOURCES = \ cursor-channel-client.h \ cursor-channel.h \ utils.hpp \ + safe-list.hpp \ dcc.cpp \ dcc.h \ dcc-private.h \ diff --git a/server/meson.build b/server/meson.build index 458d6f31..aaa173ae 100644 --- a/server/meson.build +++ b/server/meson.build @@ -57,6 +57,7 @@ spice_server_sources = [ 'cursor-channel-client.h', 'cursor-channel.h', 'utils.hpp', + 'safe-list.hpp', 'dcc.cpp', 'dcc.h', 'dcc-private.h', diff --git a/server/safe-list.hpp b/server/safe-list.hpp new file mode 100644 index 00000000..1edbe532 --- /dev/null +++ b/server/safe-list.hpp @@ -0,0 +1,115 @@ +/* + Copyright (C) 2020 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ + +/* Implementation of a list with more "safe" iterators. + * Specifically the item under an iterator can be removed while scanning + * the list. This to allow objects in the list to delete themselves from + * the list. + */ +#pragma once + +#include +#include +#include + +#include "push-visibility.h" + +namespace red { + +template +class safe_list +{ + typedef typename std::forward_list wrapped; + typename std::forward_list list; + class iterator; +public: + void push_front(const T& v) + { + list.push_front(v); + } + void remove(const T& v) + { + list.remove(v); + } + void clear() + { + list.clear(); + } + void pop_front() + { + list.pop_front(); + } + iterator begin() noexcept + { + return iterator(list.begin()); + } + iterator end() noexcept + { + return iterator(list.end()); + } + size_t size() + { + return std::distance(begin(), end()); + } + bool empty() const + { + return list.empty(); + } +}; + +template +class safe_list::iterator: public std::iterator +{ + typedef typename std::forward_list::iterator wrapped; + wrapped curr, next; +public: + iterator(wrapped curr) : + curr(curr), + next(curr != wrapped() ? ++curr : wrapped()) + { + } + iterator& operator++() + { + curr = next; + if (next != wrapped()) { + ++next; + } + return *this; + } + iterator operator++(int) + { + iterator tmp(*this); + operator++(); + return tmp; + } + bool operator==(const iterator& rhs) const + { + return curr == rhs.curr; + } + bool operator!=(const iterator& rhs) const + { + return curr != rhs.curr; + } + T& operator*() + { + return *curr; + } +}; + +} // namespace red + +#include "pop-visibility.h"