// Copyright (c) 2016 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // An arena that consists of a single inlined block of |ArenaSize|. Useful to // avoid repeated calls to malloc/new and to improve memory locality. DCHECK's // if an allocation out of the arena ever fails in debug builds; falls back to // heap allocation in release builds. #ifndef NET_QUIC_QUIC_ONE_BLOCK_ARENA_H_ #define NET_QUIC_QUIC_ONE_BLOCK_ARENA_H_ #include "net/quic/quic_arena_scoped_ptr.h" #include "net/quic/quic_flags.h" #include "net/quic/quic_utils.h" #define PREDICT_FALSE(x) x namespace net { template class QuicOneBlockArena { static const uint32_t kMaxAlign = 8; public: QuicOneBlockArena(); // Instantiates an object of type |T| with |args|. |args| are perfectly // forwarded to |T|'s constructor. The returned pointer's lifetime is // controlled by QuicArenaScopedPtr. template QuicArenaScopedPtr New(Args&&... args); private: // Returns the size of |T| aligned up to |kMaxAlign|. template static inline uint32_t AlignedSize() { return ((sizeof(T) + (kMaxAlign - 1)) / kMaxAlign) * kMaxAlign; } // Actual storage. // Subtle/annoying: the value '8' must be coded explicitly into the alignment // declaration for MSVC. QUIC_ALIGNED(8) char storage_[ArenaSize]; // Current offset into the storage. uint32_t offset_; DISALLOW_COPY_AND_ASSIGN(QuicOneBlockArena); }; template QuicOneBlockArena::QuicOneBlockArena() : offset_(0) {} template template QuicArenaScopedPtr QuicOneBlockArena::New(Args&&... args) { DCHECK_LT(AlignedSize(), ArenaSize) << "Object is too large for the arena."; static_assert(QUIC_ALIGN_OF(T) > 1, "Objects added to the arena must be at least 2B aligned."); if (PREDICT_FALSE(offset_ > ArenaSize - AlignedSize())) { LOG(DFATAL) << "Ran out of space in QuicOneBlockArena at " << this << ", max size was " << ArenaSize << ", failing request was " << AlignedSize() << ", end of arena was " << offset_; return QuicArenaScopedPtr(new T(std::forward(args)...)); } void* buf = &storage_[offset_]; new (buf) T(std::forward(args)...); offset_ += AlignedSize(); return QuicArenaScopedPtr(buf, QuicArenaScopedPtr::ConstructFrom::kArena); } } // namespace net #endif // NET_QUIC_QUIC_ONE_BLOCK_ARENA_H_