Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(687)

Side by Side Diff: base/containers/vector_buffer.h

Issue 2898213003: Add skeleton circular queue file.
Patch Set: Fix merge 2 Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/containers/queue.h ('k') | base/containers/vector_buffer_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef BASE_CONTAINERS_VECTOR_BUFFERS_H_
6 #define BASE_CONTAINERS_VECTOR_BUFFERS_H_
7
8 #include <stdlib.h>
9 #include <string.h>
10
11 #include <type_traits>
12 #include <utility>
13
14 #include "base/logging.h"
15 #include "base/macros.h"
16
17 namespace base {
18 namespace internal {
19
20 // Internal implementation detail of base/containers.
21 //
22 // Implements a vector-like buffer that holds a certain capacity of T. Unlike
23 // std::vector, VectorBuffer never constructs or destructs its arguments, and
24 // can't change sizes. But it does implement templates to assist in efficient
25 // moving and destruction of those items manually.
26 //
27 // In particular, te destructor function does not iterate over the items if
28 // there is no destructor. Moves should be implemented as a memcpy/memmove for
29 // trivially copyable objects (POD) otherwise, it should be a std::move if
30 // possible, and as a last resort it falls back to a copy. This behavior is
31 // similar to std::vector.
32 //
33 // No special consideration is done for noexcept move constructors since
34 // we compile without exceptions.
35 //
36 // The current API does not support moving overlapping ranges.
37 template <typename T>
38 class VectorBuffer {
39 public:
40 VectorBuffer() {}
41 VectorBuffer(size_t count)
42 : buffer_(reinterpret_cast<T*>(malloc(sizeof(T) * count))),
43 capacity_(count) {}
44 VectorBuffer(VectorBuffer&& other) noexcept
45 : buffer_(other.buffer_), capacity_(other.capacity_) {
46 other.buffer_ = nullptr;
47 other.capacity_ = 0;
48 }
49
50 ~VectorBuffer() { free(buffer_); }
51
52 VectorBuffer& operator=(VectorBuffer&& other) {
53 free(buffer_);
54 buffer_ = other.buffer_;
55 capacity_ = other.capacity_;
56
57 other.buffer_ = nullptr;
58 other.capacity_ = 0;
59 return *this;
60 }
61
62 size_t capacity() const { return capacity_; }
63
64 T& operator[](size_t i) { return buffer_[i]; }
65 const T& operator[](size_t i) const { return buffer_[i]; }
66 T* begin() { return buffer_; }
67 T* end() { return &buffer_[capacity_]; }
68
69 // DestructRange ------------------------------------------------------------
70
71 // Trivially destructible objects need not have their destructors called.
72 template <typename T2 = T,
73 typename std::enable_if<std::is_trivially_destructible<T2>::value,
74 int>::type = 0>
75 void DestructRange(T* begin, T* end) {}
76
77 // Non-trivially destructible objects must have their destructors called
78 // individually.
79 template <typename T2 = T,
80 typename std::enable_if<!std::is_trivially_destructible<T2>::value,
81 int>::type = 0>
82 void DestructRange(T* begin, T* end) {
83 while (begin != end) {
84 begin->~T();
85 begin++;
86 }
87 }
88
89 // MoveRange ----------------------------------------------------------------
90 //
91 // The destructor will be called (as necessary) for all moved types. The
92 // ranges must not overlap.
93
94 // Trivially copyable types can use memcpy. trivially copyable implies
95 // that there is a trivial destructor as we don't have to call it.
96 template <typename T2 = T,
97 typename std::enable_if<base::is_trivially_copyable<T2>::value,
98 int>::type = 0>
99 static void MoveRange(T* from_begin, T* from_end, T* to) {
100 DCHECK(!RangesOverlap(from_begin, from_end, to));
101 memcpy(to, from_begin, (from_end - from_begin) * sizeof(T));
102 }
103
104 // Not trivially copyable, but movable: call the move constructor and
105 // destruct the original.
106 template <typename T2 = T,
107 typename std::enable_if<std::is_move_constructible<T2>::value &&
108 !base::is_trivially_copyable<T2>::value,
109 int>::type = 0>
110 static void MoveRange(T* from_begin, T* from_end, T* to) {
111 DCHECK(!RangesOverlap(from_begin, from_end, to));
112 while (from_begin != from_end) {
113 new (to) T(std::move(*from_begin));
114 from_begin->~T();
115 from_begin++;
116 to++;
117 }
118 }
119
120 // Not movable, not trivially copyable: call the copy constructor and
121 // destruct the original.
122 template <typename T2 = T,
123 typename std::enable_if<!std::is_move_constructible<T2>::value &&
124 !base::is_trivially_copyable<T2>::value,
125 int>::type = 0>
126 static void MoveRange(T* from_begin, T* from_end, T* to) {
127 DCHECK(!RangesOverlap(from_begin, from_end, to));
128 while (from_begin != from_end) {
129 new (to) T(*from_begin);
130 from_begin->~T();
131 from_begin++;
132 to++;
133 }
134 }
135
136 private:
137 static bool RangesOverlap(const T* from_begin,
138 const T* from_end,
139 const T* to) {
140 return !(to >= from_end || to + (from_end - from_begin) <= from_begin);
141 }
142
143 T* buffer_ = nullptr;
144 size_t capacity_ = 0;
145
146 DISALLOW_COPY_AND_ASSIGN(VectorBuffer);
147 };
148
149 } // namespace internal
150 } // namespace base
151
152 #endif // BASE_CONTAINERS_VECTOR_BUFFERS_H_
OLDNEW
« no previous file with comments | « base/containers/queue.h ('k') | base/containers/vector_buffer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698