| OLD | NEW |
| (Empty) | |
| 1 // Copyright 2016 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. |
| 4 |
| 5 #ifndef BLIMP_HELIUM_LWW_REGISTER_H_ |
| 6 #define BLIMP_HELIUM_LWW_REGISTER_H_ |
| 7 |
| 8 #include "base/memory/ptr_util.h" |
| 9 #include "blimp/helium/blimp_helium_export.h" |
| 10 #include "blimp/helium/coded_value_serializer.h" |
| 11 #include "blimp/helium/result.h" |
| 12 #include "blimp/helium/syncable.h" |
| 13 #include "blimp/helium/syncable_common.h" |
| 14 #include "blimp/helium/version_vector.h" |
| 15 #include "blimp/helium/version_vector_generator.h" |
| 16 #include "third_party/protobuf/src/google/protobuf/io/coded_stream.h" |
| 17 |
| 18 namespace blimp { |
| 19 namespace helium { |
| 20 |
| 21 // Provides a simple syncable and atomically-writable "register" holding |
| 22 // contents of type |RegisterType|. When there is a write conflict, it is |
| 23 // resolved by assuming the writer indicated by |bias| has the correct value. |
| 24 template <class RegisterType> |
| 25 class BLIMP_HELIUM_EXPORT LwwRegister : public Syncable { |
| 26 public: |
| 27 LwwRegister(VersionVectorGenerator* version_gen, Peer bias, Peer running_as); |
| 28 ~LwwRegister() = default; |
| 29 |
| 30 void Set(const RegisterType& value); |
| 31 |
| 32 const RegisterType& Get() const; |
| 33 |
| 34 // Syncable implementation. |
| 35 void CreateChangesetToCurrent( |
| 36 Revision from, |
| 37 google::protobuf::io::CodedOutputStream* output_stream) override; |
| 38 Result ApplyChangeset( |
| 39 Revision to, |
| 40 google::protobuf::io::CodedInputStream* input_stream) override; |
| 41 void ReleaseBefore(Revision checkpoint) override; |
| 42 VersionVector GetVersionVector() const override; |
| 43 |
| 44 private: |
| 45 VersionVectorGenerator* version_gen_; |
| 46 VersionVector last_modified_; |
| 47 bool locally_owned_; |
| 48 RegisterType value_; |
| 49 bool value_set_ = false; |
| 50 |
| 51 DISALLOW_COPY_AND_ASSIGN(LwwRegister); |
| 52 }; |
| 53 |
| 54 template <class RegisterType> |
| 55 LwwRegister<RegisterType>::LwwRegister(VersionVectorGenerator* version_gen, |
| 56 Peer bias, |
| 57 Peer running_as) |
| 58 : version_gen_(version_gen), |
| 59 last_modified_(version_gen->current()), |
| 60 locally_owned_(bias == running_as) { |
| 61 DCHECK(version_gen_); |
| 62 } |
| 63 |
| 64 template <class RegisterType> |
| 65 void LwwRegister<RegisterType>::Set(const RegisterType& value) { |
| 66 value_ = value; |
| 67 value_set_ = true; |
| 68 version_gen_->Increment(); |
| 69 last_modified_ = last_modified_.MergeWith(version_gen_->current()); |
| 70 } |
| 71 |
| 72 template <class RegisterType> |
| 73 const RegisterType& LwwRegister<RegisterType>::Get() const { |
| 74 DCHECK(value_set_); |
| 75 return value_; |
| 76 } |
| 77 |
| 78 template <class RegisterType> |
| 79 VersionVector LwwRegister<RegisterType>::GetVersionVector() const { |
| 80 return last_modified_; |
| 81 } |
| 82 |
| 83 template <class RegisterType> |
| 84 void LwwRegister<RegisterType>::CreateChangesetToCurrent( |
| 85 Revision from, |
| 86 google::protobuf::io::CodedOutputStream* output_stream) { |
| 87 CodedValueSerializer::Serialize(last_modified_, output_stream); |
| 88 CodedValueSerializer::Serialize(value_, output_stream); |
| 89 } |
| 90 |
| 91 template <class RegisterType> |
| 92 Result LwwRegister<RegisterType>::ApplyChangeset( |
| 93 Revision to, |
| 94 google::protobuf::io::CodedInputStream* input_stream) { |
| 95 VersionVector remote; |
| 96 if (!CodedValueSerializer::Deserialize(input_stream, &remote)) { |
| 97 return Result::ERR_INTERNAL_ERROR; |
| 98 } |
| 99 remote = remote.Invert(); |
| 100 VersionVector::Comparison cmp = last_modified_.CompareTo(remote); |
| 101 if (cmp == VersionVector::Comparison::LessThan || |
| 102 (cmp == VersionVector::Comparison::Conflict && !locally_owned_)) { |
| 103 if (!CodedValueSerializer::Deserialize(input_stream, &value_)) { |
| 104 return Result::ERR_INTERNAL_ERROR; |
| 105 } |
| 106 value_set_ = true; |
| 107 } |
| 108 last_modified_ = last_modified_.MergeWith(remote); |
| 109 return Result::SUCCESS; |
| 110 } |
| 111 |
| 112 template <class RegisterType> |
| 113 void LwwRegister<RegisterType>::ReleaseBefore(Revision checkpoint) { |
| 114 // no-op |
| 115 } |
| 116 |
| 117 } // namespace helium |
| 118 } // namespace blimp |
| 119 |
| 120 #endif // BLIMP_HELIUM_LWW_REGISTER_H_ |
| OLD | NEW |