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"
16 // Default traits struct for ProtoValuePtr - adapts a
17 // ::google::protobuf::MessageLite derived type to be used with ProtoValuePtr.
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
42 template <typename T
, typename Traits
= DefaultProtoValuePtrTraits
<T
>>
45 // Immutable shareable ref-counted wrapper that embeds the value.
46 class Wrapper
: public base::RefCountedThreadSafe
<Wrapper
> {
48 Wrapper(const T
& value
) { Traits::CopyValue(&value_
, value
); }
49 const T
& value() const { return value_
; }
52 friend class base::RefCountedThreadSafe
<Wrapper
>;
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
;
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
);
80 // Don't store default value.
85 scoped_refptr
<Wrapper
> wrapper_
;
88 typedef ProtoValuePtr
<sync_pb::EntitySpecifics
> EntitySpecificsPtr
;
89 typedef ProtoValuePtr
<sync_pb::AttachmentMetadata
> AttachmentMetadataPtr
;
91 } // namespace syncable
94 #endif // SYNC_SYNCABLE_ENTRY_PROTO_FIELD_PTR_H_