xref: /aosp_15_r20/external/perfetto/src/protozero/message_arena.cc (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1*6dbdd20aSAndroid Build Coastguard Worker /*
2*6dbdd20aSAndroid Build Coastguard Worker  * Copyright (C) 2020 The Android Open Source Project
3*6dbdd20aSAndroid Build Coastguard Worker  *
4*6dbdd20aSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*6dbdd20aSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*6dbdd20aSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*6dbdd20aSAndroid Build Coastguard Worker  *
8*6dbdd20aSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*6dbdd20aSAndroid Build Coastguard Worker  *
10*6dbdd20aSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*6dbdd20aSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*6dbdd20aSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*6dbdd20aSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*6dbdd20aSAndroid Build Coastguard Worker  * limitations under the License.
15*6dbdd20aSAndroid Build Coastguard Worker  */
16*6dbdd20aSAndroid Build Coastguard Worker 
17*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/protozero/message_arena.h"
18*6dbdd20aSAndroid Build Coastguard Worker 
19*6dbdd20aSAndroid Build Coastguard Worker #include <atomic>
20*6dbdd20aSAndroid Build Coastguard Worker #include <type_traits>
21*6dbdd20aSAndroid Build Coastguard Worker 
22*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/base/logging.h"
23*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/protozero/message_handle.h"
24*6dbdd20aSAndroid Build Coastguard Worker 
25*6dbdd20aSAndroid Build Coastguard Worker namespace protozero {
26*6dbdd20aSAndroid Build Coastguard Worker 
MessageArena()27*6dbdd20aSAndroid Build Coastguard Worker MessageArena::MessageArena() {
28*6dbdd20aSAndroid Build Coastguard Worker   // The code below assumes that there is always at least one block.
29*6dbdd20aSAndroid Build Coastguard Worker   blocks_.emplace_front();
30*6dbdd20aSAndroid Build Coastguard Worker   static_assert(
31*6dbdd20aSAndroid Build Coastguard Worker       std::alignment_of<decltype(blocks_.front().storage[0])>::value >=
32*6dbdd20aSAndroid Build Coastguard Worker           alignof(Message),
33*6dbdd20aSAndroid Build Coastguard Worker       "MessageArea's storage is not properly aligned");
34*6dbdd20aSAndroid Build Coastguard Worker }
35*6dbdd20aSAndroid Build Coastguard Worker 
36*6dbdd20aSAndroid Build Coastguard Worker MessageArena::~MessageArena() = default;
37*6dbdd20aSAndroid Build Coastguard Worker 
NewMessage()38*6dbdd20aSAndroid Build Coastguard Worker Message* MessageArena::NewMessage() {
39*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_DCHECK(!blocks_.empty());  // Should never become empty.
40*6dbdd20aSAndroid Build Coastguard Worker 
41*6dbdd20aSAndroid Build Coastguard Worker   Block* block = &blocks_.front();
42*6dbdd20aSAndroid Build Coastguard Worker   if (PERFETTO_UNLIKELY(block->entries >= Block::kCapacity)) {
43*6dbdd20aSAndroid Build Coastguard Worker     blocks_.emplace_front();
44*6dbdd20aSAndroid Build Coastguard Worker     block = &blocks_.front();
45*6dbdd20aSAndroid Build Coastguard Worker   }
46*6dbdd20aSAndroid Build Coastguard Worker   const auto idx = block->entries++;
47*6dbdd20aSAndroid Build Coastguard Worker   void* storage = &block->storage[idx];
48*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_ASAN_UNPOISON(storage, sizeof(Message));
49*6dbdd20aSAndroid Build Coastguard Worker   return new (storage) Message();
50*6dbdd20aSAndroid Build Coastguard Worker }
51*6dbdd20aSAndroid Build Coastguard Worker 
DeleteLastMessageInternal()52*6dbdd20aSAndroid Build Coastguard Worker void MessageArena::DeleteLastMessageInternal() {
53*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_DCHECK(!blocks_.empty());  // Should never be empty, see below.
54*6dbdd20aSAndroid Build Coastguard Worker   Block* block = &blocks_.front();
55*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_DCHECK(block->entries > 0);
56*6dbdd20aSAndroid Build Coastguard Worker 
57*6dbdd20aSAndroid Build Coastguard Worker   // This is the reason why there is no ~Message() call here.
58*6dbdd20aSAndroid Build Coastguard Worker   // MessageArea::Reset() (see header) also relies on dtor being trivial.
59*6dbdd20aSAndroid Build Coastguard Worker   static_assert(std::is_trivially_destructible<Message>::value,
60*6dbdd20aSAndroid Build Coastguard Worker                 "Message must be trivially destructible");
61*6dbdd20aSAndroid Build Coastguard Worker 
62*6dbdd20aSAndroid Build Coastguard Worker   --block->entries;
63*6dbdd20aSAndroid Build Coastguard Worker   PERFETTO_ASAN_POISON(&block->storage[block->entries], sizeof(Message));
64*6dbdd20aSAndroid Build Coastguard Worker 
65*6dbdd20aSAndroid Build Coastguard Worker   // Don't remove the first block to avoid malloc/free calls when the root
66*6dbdd20aSAndroid Build Coastguard Worker   // message is reset. Hitting the allocator all the times is a waste of time.
67*6dbdd20aSAndroid Build Coastguard Worker   if (block->entries == 0 && std::next(blocks_.cbegin()) != blocks_.cend()) {
68*6dbdd20aSAndroid Build Coastguard Worker     blocks_.pop_front();
69*6dbdd20aSAndroid Build Coastguard Worker   }
70*6dbdd20aSAndroid Build Coastguard Worker }
71*6dbdd20aSAndroid Build Coastguard Worker 
72*6dbdd20aSAndroid Build Coastguard Worker }  // namespace protozero
73