1 // Copyright 2021 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef COMPONENTS_METRICS_STRUCTURED_LIB_PERSISTENT_PROTO_H_ 6 #define COMPONENTS_METRICS_STRUCTURED_LIB_PERSISTENT_PROTO_H_ 7 8 #include <concepts> 9 #include <memory> 10 #include <type_traits> 11 12 #include "components/metrics/structured/lib/persistent_proto_internal.h" 13 #include "third_party/protobuf/src/google/protobuf/message_lite.h" 14 15 namespace metrics::structured { 16 17 // PersistentProto wraps a proto class and persists it to disk. Usage summary. 18 // - Init is asynchronous, usage before |on_read| is called will crash. 19 // - pproto->Method() will call Method on the underlying proto. 20 // - Call QueueWrite() to write to disk. 21 // 22 // Reading. The backing file is read asynchronously from disk once at 23 // initialization, and the |on_read| callback is run once this is done. Until 24 // |on_read| is called, has_value is false and get() will always return nullptr. 25 // If no proto file exists on disk, or it is invalid, a blank proto is 26 // constructed and immediately written to disk. 27 // 28 // Writing. Writes must be triggered manually. QueueWrite() delays writing to 29 // disk for |write_delay| time, in order to batch successive writes. 30 // The |on_write| callback is run each time a write has completed. QueueWrite() 31 // should not be called until OnReadComplete() is finished, which can be 32 // checked with the callback |on_read_|. Calling QueueWrite() before 33 // OnReadComplete() has finished will result in a crash. 34 // 35 // The |on_write| callback is run each time a write has completed. 36 template <class T> requires(std::derived_from<T,google::protobuf::MessageLite>)37 requires(std::derived_from<T, google::protobuf::MessageLite>) 38 class PersistentProto : public internal::PersistentProtoInternal { 39 public: 40 using internal::PersistentProtoInternal::PersistentProtoInternal; 41 42 PersistentProto(const base::FilePath& path, 43 base::TimeDelta write_delay, 44 PersistentProtoInternal::ReadCallback on_read, 45 PersistentProtoInternal::WriteCallback on_write) 46 : internal::PersistentProtoInternal(path, 47 write_delay, 48 std::move(on_read), 49 std::move(on_write)), 50 handle_(std::make_unique<T>()) {} 51 52 ~PersistentProto() override { DeallocProto(); } 53 54 T* get() { return static_cast<T*>(internal::PersistentProtoInternal::get()); } 55 const T* get() const { 56 return static_cast<T*>(internal::PersistentProtoInternal::get()); 57 } 58 59 T* operator->() { return get(); } 60 const T* operator->() const { return get(); } 61 62 T& operator*() { return *get(); } 63 const T& operator*() const { return *get(); } 64 65 private: 66 google::protobuf::MessageLite* GetProto() override { return handle_.get(); } 67 68 std::unique_ptr<T> handle_; 69 }; 70 71 } // namespace metrics::structured 72 73 #endif // COMPONENTS_METRICS_STRUCTURED_LIB_PERSISTENT_PROTO_H_ 74