2 * nghttp2 - HTTP/2 C Library
4 * Copyright (c) 2014 Tatsuhiro Tsujikawa
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 #include "nghttp2_config.h"
42 template <size_t N> struct Memchunk {
43 Memchunk(std::unique_ptr<Memchunk> next_chunk)
44 : pos(std::begin(buf)), last(pos), knext(std::move(next_chunk)),
45 kprev(nullptr), next(nullptr) {
50 size_t len() const { return last - pos; }
51 size_t left() const { return std::end(buf) - last; }
52 void reset() { pos = last = std::begin(buf); }
53 std::array<uint8_t, N> buf;
55 std::unique_ptr<Memchunk> knext;
58 static const size_t size = N;
61 template <typename T> struct Pool {
62 Pool() : pool(nullptr), freelist(nullptr), poolsize(0) {}
66 freelist = freelist->next;
72 pool = make_unique<T>(std::move(pool));
84 void shrink(size_t max) {
86 for (; m && poolsize > max;) {
91 p->knext = std::move(m->knext);
96 pool = std::move(m->knext);
98 pool->kprev = nullptr;
110 using value_type = T;
111 std::unique_ptr<T> pool;
116 template <typename Memchunk> struct Memchunks {
117 Memchunks(Pool<Memchunk> *pool)
118 : pool(pool), head(nullptr), tail(nullptr), len(0) {}
123 for (auto m = head; m;) {
129 size_t append(const void *src, size_t count) {
134 auto first = static_cast<const uint8_t *>(src);
135 auto last = first + count;
138 head = tail = pool->get();
142 auto n = std::min(static_cast<size_t>(last - first), tail->left());
143 tail->last = std::copy_n(first, n, tail->last);
150 tail->next = pool->get();
156 template <size_t N> size_t append(const char (&s)[N]) {
157 return append(s, N - 1);
159 size_t remove(void *dest, size_t count) {
160 if (!tail || count == 0) {
164 auto first = static_cast<uint8_t *>(dest);
165 auto last = first + count;
171 auto n = std::min(static_cast<size_t>(last - first), m->len());
174 first = std::copy_n(m->pos, n, first);
184 if (head == nullptr) {
188 return first - static_cast<uint8_t *>(dest);
190 size_t drain(size_t count) {
195 auto n = std::min(count, m->len());
207 if (head == nullptr) {
210 return ndata - count;
212 int riovec(struct iovec *iov, int iovcnt) {
218 for (i = 0; i < iovcnt && m; ++i, m = m->next) {
219 iov[i].iov_base = m->pos;
220 iov[i].iov_len = m->len();
224 size_t rleft() const { return len; }
226 Pool<Memchunk> *pool;
227 Memchunk *head, *tail;
231 using Memchunk16K = Memchunk<16384>;
232 using MemchunkPool = Pool<Memchunk16K>;
233 using DefaultMemchunks = Memchunks<Memchunk16K>;
235 #define DEFAULT_WR_IOVCNT 16
237 #if defined(IOV_MAX) && IOV_MAX < DEFAULT_WR_IOVCNT
238 #define MAX_WR_IOVCNT IOV_MAX
239 #else // !defined(IOV_MAX) || IOV_MAX >= DEFAULT_WR_IOVCNT
240 #define MAX_WR_IOVCNT DEFAULT_WR_IOVCNT
241 #endif // !defined(IOV_MAX) || IOV_MAX >= DEFAULT_WR_IOVCNT
243 inline int limit_iovec(struct iovec *iov, int iovcnt, size_t max) {
247 for (int i = 0; i < iovcnt; ++i) {
248 auto d = std::min(max, iov[i].iov_len);
258 } // namespace nghttp2