Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
14 pmbaty 1
//===- llvm/ADT/AllocatorList.h - Custom allocator list ---------*- C++ -*-===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
 
9
#ifndef LLVM_ADT_ALLOCATORLIST_H
10
#define LLVM_ADT_ALLOCATORLIST_H
11
 
12
#include "llvm/ADT/ilist_node.h"
13
#include "llvm/ADT/iterator.h"
14
#include "llvm/ADT/simple_ilist.h"
15
#include "llvm/Support/Allocator.h"
16
#include <cassert>
17
#include <cstddef>
18
#include <iterator>
19
#include <type_traits>
20
#include <utility>
21
 
22
namespace llvm {
23
 
24
/// A linked-list with a custom, local allocator.
25
///
26
/// Expose a std::list-like interface that owns and uses a custom LLVM-style
27
/// allocator (e.g., BumpPtrAllocator), leveraging \a simple_ilist for the
28
/// implementation details.
29
///
30
/// Because this list owns the allocator, calling \a splice() with a different
31
/// list isn't generally safe.  As such, \a splice has been left out of the
32
/// interface entirely.
33
template <class T, class AllocatorT> class AllocatorList : AllocatorT {
34
  struct Node : ilist_node<Node> {
35
    Node(Node &&) = delete;
36
    Node(const Node &) = delete;
37
    Node &operator=(Node &&) = delete;
38
    Node &operator=(const Node &) = delete;
39
 
40
    Node(T &&V) : V(std::move(V)) {}
41
    Node(const T &V) : V(V) {}
42
    template <class... Ts> Node(Ts &&... Vs) : V(std::forward<Ts>(Vs)...) {}
43
    T V;
44
  };
45
 
46
  using list_type = simple_ilist<Node>;
47
 
48
  list_type List;
49
 
50
  AllocatorT &getAlloc() { return *this; }
51
  const AllocatorT &getAlloc() const { return *this; }
52
 
53
  template <class... ArgTs> Node *create(ArgTs &&... Args) {
54
    return new (getAlloc()) Node(std::forward<ArgTs>(Args)...);
55
  }
56
 
57
  struct Cloner {
58
    AllocatorList &AL;
59
 
60
    Cloner(AllocatorList &AL) : AL(AL) {}
61
 
62
    Node *operator()(const Node &N) const { return AL.create(N.V); }
63
  };
64
 
65
  struct Disposer {
66
    AllocatorList &AL;
67
 
68
    Disposer(AllocatorList &AL) : AL(AL) {}
69
 
70
    void operator()(Node *N) const {
71
      N->~Node();
72
      AL.getAlloc().Deallocate(N);
73
    }
74
  };
75
 
76
public:
77
  using value_type = T;
78
  using pointer = T *;
79
  using reference = T &;
80
  using const_pointer = const T *;
81
  using const_reference = const T &;
82
  using size_type = typename list_type::size_type;
83
  using difference_type = typename list_type::difference_type;
84
 
85
private:
86
  template <class ValueT, class IteratorBase>
87
  class IteratorImpl
88
      : public iterator_adaptor_base<IteratorImpl<ValueT, IteratorBase>,
89
                                     IteratorBase,
90
                                     std::bidirectional_iterator_tag, ValueT> {
91
    template <class OtherValueT, class OtherIteratorBase>
92
    friend class IteratorImpl;
93
    friend AllocatorList;
94
 
95
    using base_type =
96
        iterator_adaptor_base<IteratorImpl<ValueT, IteratorBase>, IteratorBase,
97
                              std::bidirectional_iterator_tag, ValueT>;
98
 
99
  public:
100
    using value_type = ValueT;
101
    using pointer = ValueT *;
102
    using reference = ValueT &;
103
 
104
    IteratorImpl() = default;
105
    IteratorImpl(const IteratorImpl &) = default;
106
    IteratorImpl &operator=(const IteratorImpl &) = default;
107
 
108
    explicit IteratorImpl(const IteratorBase &I) : base_type(I) {}
109
 
110
    template <class OtherValueT, class OtherIteratorBase>
111
    IteratorImpl(const IteratorImpl<OtherValueT, OtherIteratorBase> &X,
112
                 std::enable_if_t<std::is_convertible<
113
                     OtherIteratorBase, IteratorBase>::value> * = nullptr)
114
        : base_type(X.wrapped()) {}
115
 
116
    ~IteratorImpl() = default;
117
 
118
    reference operator*() const { return base_type::wrapped()->V; }
119
    pointer operator->() const { return &operator*(); }
120
  };
121
 
122
public:
123
  using iterator = IteratorImpl<T, typename list_type::iterator>;
124
  using reverse_iterator =
125
      IteratorImpl<T, typename list_type::reverse_iterator>;
126
  using const_iterator =
127
      IteratorImpl<const T, typename list_type::const_iterator>;
128
  using const_reverse_iterator =
129
      IteratorImpl<const T, typename list_type::const_reverse_iterator>;
130
 
131
  AllocatorList() = default;
132
  AllocatorList(AllocatorList &&X)
133
      : AllocatorT(std::move(X.getAlloc())), List(std::move(X.List)) {}
134
 
135
  AllocatorList(const AllocatorList &X) {
136
    List.cloneFrom(X.List, Cloner(*this), Disposer(*this));
137
  }
138
 
139
  AllocatorList &operator=(AllocatorList &&X) {
140
    clear(); // Dispose of current nodes explicitly.
141
    List = std::move(X.List);
142
    getAlloc() = std::move(X.getAlloc());
143
    return *this;
144
  }
145
 
146
  AllocatorList &operator=(const AllocatorList &X) {
147
    List.cloneFrom(X.List, Cloner(*this), Disposer(*this));
148
    return *this;
149
  }
150
 
151
  ~AllocatorList() { clear(); }
152
 
153
  void swap(AllocatorList &RHS) {
154
    List.swap(RHS.List);
155
    std::swap(getAlloc(), RHS.getAlloc());
156
  }
157
 
158
  bool empty() { return List.empty(); }
159
  size_t size() { return List.size(); }
160
 
161
  iterator begin() { return iterator(List.begin()); }
162
  iterator end() { return iterator(List.end()); }
163
  const_iterator begin() const { return const_iterator(List.begin()); }
164
  const_iterator end() const { return const_iterator(List.end()); }
165
  reverse_iterator rbegin() { return reverse_iterator(List.rbegin()); }
166
  reverse_iterator rend() { return reverse_iterator(List.rend()); }
167
  const_reverse_iterator rbegin() const {
168
    return const_reverse_iterator(List.rbegin());
169
  }
170
  const_reverse_iterator rend() const {
171
    return const_reverse_iterator(List.rend());
172
  }
173
 
174
  T &back() { return List.back().V; }
175
  T &front() { return List.front().V; }
176
  const T &back() const { return List.back().V; }
177
  const T &front() const { return List.front().V; }
178
 
179
  template <class... Ts> iterator emplace(iterator I, Ts &&... Vs) {
180
    return iterator(List.insert(I.wrapped(), *create(std::forward<Ts>(Vs)...)));
181
  }
182
 
183
  iterator insert(iterator I, T &&V) {
184
    return iterator(List.insert(I.wrapped(), *create(std::move(V))));
185
  }
186
  iterator insert(iterator I, const T &V) {
187
    return iterator(List.insert(I.wrapped(), *create(V)));
188
  }
189
 
190
  template <class Iterator>
191
  void insert(iterator I, Iterator First, Iterator Last) {
192
    for (; First != Last; ++First)
193
      List.insert(I.wrapped(), *create(*First));
194
  }
195
 
196
  iterator erase(iterator I) {
197
    return iterator(List.eraseAndDispose(I.wrapped(), Disposer(*this)));
198
  }
199
 
200
  iterator erase(iterator First, iterator Last) {
201
    return iterator(
202
        List.eraseAndDispose(First.wrapped(), Last.wrapped(), Disposer(*this)));
203
  }
204
 
205
  void clear() { List.clearAndDispose(Disposer(*this)); }
206
  void pop_back() { List.eraseAndDispose(--List.end(), Disposer(*this)); }
207
  void pop_front() { List.eraseAndDispose(List.begin(), Disposer(*this)); }
208
  void push_back(T &&V) { insert(end(), std::move(V)); }
209
  void push_front(T &&V) { insert(begin(), std::move(V)); }
210
  void push_back(const T &V) { insert(end(), V); }
211
  void push_front(const T &V) { insert(begin(), V); }
212
  template <class... Ts> void emplace_back(Ts &&... Vs) {
213
    emplace(end(), std::forward<Ts>(Vs)...);
214
  }
215
  template <class... Ts> void emplace_front(Ts &&... Vs) {
216
    emplace(begin(), std::forward<Ts>(Vs)...);
217
  }
218
 
219
  /// Reset the underlying allocator.
220
  ///
221
  /// \pre \c empty()
222
  void resetAlloc() {
223
    assert(empty() && "Cannot reset allocator if not empty");
224
    getAlloc().Reset();
225
  }
226
};
227
 
228
template <class T> using BumpPtrList = AllocatorList<T, BumpPtrAllocator>;
229
 
230
} // end namespace llvm
231
 
232
#endif // LLVM_ADT_ALLOCATORLIST_H