xref: /openbmc/sdbusplus/include/sdbusplus/async/stdexec/__detail/__intrusive_slist.hpp (revision 10d0b4b7d1498cfd5c3d37edea271a54d1984e41)
1 /*
2  * Copyright (c) 2024 NVIDIA Corporation
3  *
4  * Licensed under the Apache License Version 2.0 with LLVM Exceptions
5  * (the "License"); you may not use this file except in compliance with
6  * the License. You may obtain a copy of the License at
7  *
8  *   https://llvm.org/LICENSE.txt
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #pragma once
17 
18 #include "__config.hpp"
19 
20 #include <cstddef>
21 #include <cassert>
22 #include <iterator>
23 #include <utility>
24 
25 namespace stdexec {
26   namespace __slist {
27     template <auto _Next>
28     class __intrusive_slist;
29 
30     template <class _Item, _Item* _Item::* _Next>
31     class __intrusive_slist<_Next> {
32      public:
33       __intrusive_slist() noexcept = default;
34 
__intrusive_slist(__intrusive_slist && __other)35       __intrusive_slist(__intrusive_slist&& __other) noexcept
36         : __head_(std::exchange(__other.__head_, nullptr)) {
37       }
38 
__intrusive_slist(_Item * __head)39       __intrusive_slist(_Item* __head) noexcept
40         : __head_(__head) {
41       }
42 
swap(__intrusive_slist & __other)43       auto swap(__intrusive_slist& __other) noexcept -> void {
44         std::swap(__head_, __other.__head_);
45       }
46 
operator =(__intrusive_slist __other)47       auto operator=(__intrusive_slist __other) noexcept -> __intrusive_slist& {
48         swap(__other);
49         return *this;
50       }
51 
52       [[nodiscard]]
empty() const53       auto empty() const noexcept -> bool {
54         return __head_ == nullptr;
55       }
56 
front() const57       auto front() const noexcept -> _Item* {
58         return __head_;
59       }
60 
clear()61       void clear() noexcept {
62         __head_ = nullptr;
63       }
64 
65       [[nodiscard]]
pop_front()66       auto pop_front() noexcept -> _Item* {
67         STDEXEC_ASSERT(!empty());
68         return std::exchange(__head_, __head_->*_Next);
69       }
70 
push_front(_Item * __item)71       void push_front(_Item* __item) noexcept {
72         STDEXEC_ASSERT(__item != nullptr);
73         __item->*_Next = std::exchange(__head_, __item);
74       }
75 
76       [[nodiscard]]
remove(_Item * __item)77       auto remove(_Item* __item) noexcept -> _Item* {
78         STDEXEC_ASSERT(__item != nullptr);
79         if (__head_ == __item) {
80           return pop_front();
81         }
82 
83         for (_Item* __current: *this) {
84           if (__current->*_Next == __item) {
85             __current->*_Next = __item->*_Next;
86             return __item;
87           }
88         }
89 
90         return nullptr;
91       }
92 
93       struct iterator {
94         using iterator_category = std::forward_iterator_tag;
95         using difference_type = std::ptrdiff_t;
96         using value_type = _Item*;
97         using reference = _Item*;
98         using pointer = _Item**;
99 
100         _Item* __item_ = nullptr;
101 
102         iterator() noexcept = default;
103 
iteratorstdexec::__slist::__intrusive_slist::iterator104         explicit iterator(_Item* __item) noexcept
105           : __item_(__item) {
106         }
107 
108         [[nodiscard]]
operator *stdexec::__slist::__intrusive_slist::iterator109         auto operator*() const noexcept -> _Item* {
110           STDEXEC_ASSERT(__item_ != nullptr);
111           return __item_;
112         }
113 
114         [[nodiscard]]
operator ->stdexec::__slist::__intrusive_slist::iterator115         auto operator->() const noexcept -> _Item** {
116           STDEXEC_ASSERT(__item_ != nullptr);
117           return &__item_;
118         }
119 
operator ++stdexec::__slist::__intrusive_slist::iterator120         auto operator++() noexcept -> iterator& {
121           STDEXEC_ASSERT(__item_ != nullptr);
122           __item_ = __item_->*_Next;
123           return *this;
124         }
125 
operator ++stdexec::__slist::__intrusive_slist::iterator126         auto operator++(int) noexcept -> iterator {
127           iterator __result = *this;
128           ++*this;
129           return __result;
130         }
131 
132         auto operator==(const iterator&) const noexcept -> bool = default;
133       };
134 
135       [[nodiscard]]
begin() const136       auto begin() const noexcept -> iterator {
137         return iterator(__head_);
138       }
139 
140       [[nodiscard]]
end() const141       auto end() const noexcept -> iterator {
142         return iterator(nullptr);
143       }
144 
145      private:
146       _Item* __head_ = nullptr;
147     };
148   } // namespace __slist
149 
150   using __slist::__intrusive_slist;
151 
152 } // namespace stdexec
153