blob: 5fbe05b7fa060975ffd45e616e5342049bab5fef [file] [log] [blame]
Primiano Tucci4f9b6d72017-12-05 20:59:16 +00001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Hector Dearmane1e56b62018-02-21 19:11:58 +000017#ifndef INCLUDE_PERFETTO_PROTOZERO_MESSAGE_HANDLE_H_
18#define INCLUDE_PERFETTO_PROTOZERO_MESSAGE_HANDLE_H_
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000019
20#include <functional>
21
Oystein Eftevaaga812a942018-03-23 11:52:32 -070022#include "perfetto/base/export.h"
Hector Dearmane1e56b62018-02-21 19:11:58 +000023#include "perfetto/protozero/message.h"
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000024
25namespace protozero {
26
Hector Dearmanaaa4c192018-02-19 11:57:35 +000027class Message;
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000028
Hector Dearmanaaa4c192018-02-19 11:57:35 +000029// MessageHandle allows to decouple the lifetime of a proto message
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000030// from the underlying storage. It gives the following guarantees:
31// - The underlying message is finalized (if still alive) if the handle goes
32// out of scope.
33// - In Debug / DCHECK_ALWAYS_ON builds, the handle becomes null once the
34// message is finalized. This is to enforce the append-only API. For instance
35// when adding two repeated messages, the addition of the 2nd one forces
36// the finalization of the first.
Hector Dearmanaaa4c192018-02-19 11:57:35 +000037// Think about this as a WeakPtr<Message> which calls
38// Message::Finalize() when going out of scope.
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000039
Oystein Eftevaaga812a942018-03-23 11:52:32 -070040class PERFETTO_EXPORT MessageHandleBase {
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000041 public:
Hector Dearmanaaa4c192018-02-19 11:57:35 +000042 ~MessageHandleBase();
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000043
44 // Move-only type.
Hector Dearmanaaa4c192018-02-19 11:57:35 +000045 MessageHandleBase(MessageHandleBase&&) noexcept;
46 MessageHandleBase& operator=(MessageHandleBase&&);
Primiano Tuccid52e6272018-04-06 19:06:53 +020047 explicit operator bool() const {
Florian Mayer8a8044f2018-01-11 16:03:09 +000048#if PERFETTO_DCHECK_IS_ON()
49 PERFETTO_DCHECK(!message_ || generation_ == message_->generation_);
50#endif
Primiano Tuccid52e6272018-04-06 19:06:53 +020051 return !!message_;
Florian Mayer8a8044f2018-01-11 16:03:09 +000052 }
Primiano Tuccid52e6272018-04-06 19:06:53 +020053
54 protected:
55 explicit MessageHandleBase(Message* = nullptr);
Hector Dearmanaaa4c192018-02-19 11:57:35 +000056 Message* operator->() const {
Florian Mayer8a8044f2018-01-11 16:03:09 +000057#if PERFETTO_DCHECK_IS_ON()
58 PERFETTO_DCHECK(!message_ || generation_ == message_->generation_);
59#endif
60 return message_;
61 }
Primiano Tuccid52e6272018-04-06 19:06:53 +020062 Message& operator*() const { return *(operator->()); }
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000063
64 private:
Hector Dearmanaaa4c192018-02-19 11:57:35 +000065 friend class Message;
66 MessageHandleBase(const MessageHandleBase&) = delete;
67 MessageHandleBase& operator=(const MessageHandleBase&) = delete;
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000068
69 void reset_message() { message_ = nullptr; }
Hector Dearmanaaa4c192018-02-19 11:57:35 +000070 void Move(MessageHandleBase&&);
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000071
Hector Dearmanaaa4c192018-02-19 11:57:35 +000072 Message* message_;
Florian Mayer8a8044f2018-01-11 16:03:09 +000073#if PERFETTO_DCHECK_IS_ON()
74 uint32_t generation_;
75#endif
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000076};
77
78template <typename T>
Hector Dearmanaaa4c192018-02-19 11:57:35 +000079class MessageHandle : public MessageHandleBase {
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000080 public:
Hector Dearmanaaa4c192018-02-19 11:57:35 +000081 MessageHandle() : MessageHandle(nullptr) {}
82 explicit MessageHandle(T* message) : MessageHandleBase(message) {}
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000083
84 T& operator*() const {
Hector Dearmanaaa4c192018-02-19 11:57:35 +000085 return static_cast<T&>(MessageHandleBase::operator*());
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000086 }
87
88 T* operator->() const {
Hector Dearmanaaa4c192018-02-19 11:57:35 +000089 return static_cast<T*>(MessageHandleBase::operator->());
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000090 }
91};
92
93} // namespace protozero
94
Hector Dearmane1e56b62018-02-21 19:11:58 +000095#endif // INCLUDE_PERFETTO_PROTOZERO_MESSAGE_HANDLE_H_