Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / sync / syncable / proto_value_ptr.h
blob8036ff5c4971d8377ef6b51389be21c2c9aceab4
1 // Copyright 2015 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.
5 #ifndef SYNC_SYNCABLE_ENTRY_PROTO_FIELD_PTR_H_
6 #define SYNC_SYNCABLE_ENTRY_PROTO_FIELD_PTR_H_
8 #include "base/gtest_prod_util.h"
9 #include "base/memory/ref_counted.h"
10 #include "sync/protocol/attachments.pb.h"
11 #include "sync/protocol/sync.pb.h"
13 namespace syncer {
14 namespace syncable {
16 // Default traits struct for ProtoValuePtr - adapts a
17 // ::google::protobuf::MessageLite derived type to be used with ProtoValuePtr.
18 template <typename T>
19 struct DefaultProtoValuePtrTraits {
20 // Deep copy the value from |src| to |dest|.
21 static void CopyValue(T* dest, const T& src) { dest->CopyFrom(src); }
22 // True if the |value| is a non-default value.
23 static bool HasValue(const T& value) { return value.ByteSize() > 0; }
24 // Default value for the type.
25 static const T& DefaultValue() { return T::default_instance(); }
28 // This is a smart pointer to a ::google::protobuf::MessageLite derived type
29 // that implements immutable, shareable, copy-on-write semantics.
31 // Additionally this class helps to avoid storing multiple copies of default
32 // instances of the wrapped type.
34 // Copying ProtoValuePtr results in ref-counted sharing of the
35 // underlying wrapper and the value contained in the wrapper.
37 // The public interface includes only immutable access to the wrapped value.
38 // The only way to assign a value to ProtoValuePtr is through a
39 // private SetValue function which is called from EntryKernel. That results
40 // in stopping sharing the previous value and creating a wrapper to the new
41 // value.
42 template <typename T, typename Traits = DefaultProtoValuePtrTraits<T>>
43 class ProtoValuePtr {
44 private:
45 // Immutable shareable ref-counted wrapper that embeds the value.
46 class Wrapper : public base::RefCountedThreadSafe<Wrapper> {
47 public:
48 Wrapper(const T& value) { Traits::CopyValue(&value_, value); }
49 const T& value() const { return value_; }
51 private:
52 friend class base::RefCountedThreadSafe<Wrapper>;
53 ~Wrapper() {}
55 T value_;
58 ProtoValuePtr() {}
59 ~ProtoValuePtr() {}
61 public:
62 const T& value() const {
63 return wrapper_ ? wrapper_->value() : Traits::DefaultValue();
66 const T* operator->() const {
67 const T& wrapped_instance = value();
68 return &wrapped_instance;
71 private:
72 friend struct EntryKernel;
73 FRIEND_TEST_ALL_PREFIXES(ProtoValuePtrTest, BasicTest);
74 FRIEND_TEST_ALL_PREFIXES(ProtoValuePtrTest, SharingTest);
76 void set_value(const T& new_value) {
77 if (Traits::HasValue(new_value)) {
78 wrapper_ = new Wrapper(new_value);
79 } else {
80 // Don't store default value.
81 wrapper_ = nullptr;
85 scoped_refptr<Wrapper> wrapper_;
88 typedef ProtoValuePtr<sync_pb::EntitySpecifics> EntitySpecificsPtr;
89 typedef ProtoValuePtr<sync_pb::AttachmentMetadata> AttachmentMetadataPtr;
91 } // namespace syncable
92 } // namespace syncer
94 #endif // SYNC_SYNCABLE_ENTRY_PROTO_FIELD_PTR_H_