• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 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 #include "quiche/spdy/core/spdy_simple_arena.h"
6 
7 #include <algorithm>
8 #include <cstring>
9 
10 #include "quiche/common/platform/api/quiche_logging.h"
11 
12 namespace spdy {
13 
SpdySimpleArena(size_t block_size)14 SpdySimpleArena::SpdySimpleArena(size_t block_size) : block_size_(block_size) {}
15 
16 SpdySimpleArena::~SpdySimpleArena() = default;
17 
18 SpdySimpleArena::SpdySimpleArena(SpdySimpleArena&& other) = default;
19 SpdySimpleArena& SpdySimpleArena::operator=(SpdySimpleArena&& other) = default;
20 
Alloc(size_t size)21 char* SpdySimpleArena::Alloc(size_t size) {
22   Reserve(size);
23   Block& b = blocks_.back();
24   QUICHE_DCHECK_GE(b.size, b.used + size);
25   char* out = b.data.get() + b.used;
26   b.used += size;
27   return out;
28 }
29 
Realloc(char * original,size_t oldsize,size_t newsize)30 char* SpdySimpleArena::Realloc(char* original, size_t oldsize, size_t newsize) {
31   QUICHE_DCHECK(!blocks_.empty());
32   Block& last = blocks_.back();
33   if (last.data.get() <= original && original < last.data.get() + last.size) {
34     // (original, oldsize) is in the last Block.
35     QUICHE_DCHECK_GE(last.data.get() + last.used, original + oldsize);
36     if (original + oldsize == last.data.get() + last.used) {
37       // (original, oldsize) was the most recent allocation,
38       if (original + newsize < last.data.get() + last.size) {
39         // (original, newsize) fits in the same Block.
40         last.used += newsize - oldsize;
41         return original;
42       }
43     }
44   }
45   char* out = Alloc(newsize);
46   memcpy(out, original, oldsize);
47   return out;
48 }
49 
Memdup(const char * data,size_t size)50 char* SpdySimpleArena::Memdup(const char* data, size_t size) {
51   char* out = Alloc(size);
52   memcpy(out, data, size);
53   return out;
54 }
55 
Free(char * data,size_t size)56 void SpdySimpleArena::Free(char* data, size_t size) {
57   if (blocks_.empty()) {
58     return;
59   }
60   Block& b = blocks_.back();
61   if (size <= b.used && data + size == b.data.get() + b.used) {
62     // The memory region passed by the caller was the most recent allocation
63     // from the final block in this arena.
64     b.used -= size;
65   }
66 }
67 
Reset()68 void SpdySimpleArena::Reset() {
69   blocks_.clear();
70   status_.bytes_allocated_ = 0;
71 }
72 
Reserve(size_t additional_space)73 void SpdySimpleArena::Reserve(size_t additional_space) {
74   if (blocks_.empty()) {
75     AllocBlock(std::max(additional_space, block_size_));
76   } else {
77     const Block& last = blocks_.back();
78     if (last.size < last.used + additional_space) {
79       AllocBlock(std::max(additional_space, block_size_));
80     }
81   }
82 }
83 
AllocBlock(size_t size)84 void SpdySimpleArena::AllocBlock(size_t size) {
85   blocks_.push_back(Block(size));
86   status_.bytes_allocated_ += size;
87 }
88 
Block(size_t s)89 SpdySimpleArena::Block::Block(size_t s) : data(new char[s]), size(s), used(0) {}
90 
91 SpdySimpleArena::Block::~Block() = default;
92 
Block(SpdySimpleArena::Block && other)93 SpdySimpleArena::Block::Block(SpdySimpleArena::Block&& other)
94     : size(other.size), used(other.used) {
95   data = std::move(other.data);
96 }
97 
operator =(SpdySimpleArena::Block && other)98 SpdySimpleArena::Block& SpdySimpleArena::Block::operator=(
99     SpdySimpleArena::Block&& other) {
100   size = other.size;
101   used = other.used;
102   data = std::move(other.data);
103   return *this;
104 }
105 
106 }  // namespace spdy
107