| 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 <memory> | |
| 9 | |
| 10 #include "base/memory/ptr_util.h" | |
| 11 #include "blimp/helium/blimp_helium_export.h" | |
| 12 #include "blimp/helium/result.h" | |
| 13 #include "blimp/helium/revision_generator.h" | |
| 14 #include "blimp/helium/serializable_struct.h" | |
| 15 #include "blimp/helium/stream_helpers.h" | |
| 16 #include "blimp/helium/syncable.h" | |
| 17 #include "blimp/helium/syncable_common.h" | |
| 18 #include "blimp/helium/version_vector.h" | |
| 19 #include "third_party/protobuf/src/google/protobuf/io/coded_stream.h" | |
| 20 | |
| 21 namespace blimp { | |
| 22 namespace helium { | |
| 23 | |
| 24 template <class RegisterType> | |
| 25 struct LwwRegisterChangeset; | |
| 26 | |
| 27 // Defines a register that obeys last-writer-wins semantics. | |
| 28 // In the event of a write conflict, the state of the locally-biased LwwRegister | |
| 29 // "wins". | |
| 30 template <class RegisterType> | |
| 31 class LwwRegister : public Syncable<LwwRegisterChangeset<RegisterType>> { | |
| 32 public: | |
| 33 using Changeset = | |
| 34 typename Syncable<LwwRegisterChangeset<RegisterType>>::Changeset; | |
| 35 | |
| 36 LwwRegister(Peer owner, Peer running_as); | |
| 37 ~LwwRegister() = default; | |
| 38 | |
| 39 void Set(const RegisterType& value); | |
| 40 const RegisterType& Get() const; | |
| 41 | |
| 42 // Syncable implementation. | |
| 43 std::unique_ptr<Changeset> CreateChangeset(Revision from) const override; | |
| 44 void ApplyChangeset(const Changeset& changeset) override; | |
| 45 void ReleaseBefore(Revision checkpoint) override; | |
| 46 Revision GetRevision() const override; | |
| 47 void SetLocalUpdateCallback( | |
| 48 const base::Closure& local_update_callback) override; | |
| 49 | |
| 50 private: | |
| 51 base::Closure local_update_callback_; | |
| 52 VersionVector last_modified_; | |
| 53 Bias bias_; | |
| 54 RegisterType value_; | |
| 55 | |
| 56 DISALLOW_COPY_AND_ASSIGN(LwwRegister); | |
| 57 }; | |
| 58 | |
| 59 template <class RegisterType> | |
| 60 LwwRegister<RegisterType>::LwwRegister(Peer owner, Peer running_as) | |
| 61 : bias_(ComputeBias(owner, running_as)) {} | |
| 62 | |
| 63 template <class RegisterType> | |
| 64 void LwwRegister<RegisterType>::Set(const RegisterType& value) { | |
| 65 value_ = value; | |
| 66 last_modified_.set_local_revision(GetNextRevision()); | |
| 67 local_update_callback_.Run(); | |
| 68 } | |
| 69 | |
| 70 template <class RegisterType> | |
| 71 const RegisterType& LwwRegister<RegisterType>::Get() const { | |
| 72 return value_; | |
| 73 } | |
| 74 | |
| 75 template <class RegisterType> | |
| 76 Revision LwwRegister<RegisterType>::GetRevision() const { | |
| 77 return last_modified_.local_revision(); | |
| 78 } | |
| 79 | |
| 80 template <class RegisterType> | |
| 81 void LwwRegister<RegisterType>::SetLocalUpdateCallback( | |
| 82 const base::Closure& local_update_callback) { | |
| 83 local_update_callback_ = local_update_callback; | |
| 84 } | |
| 85 | |
| 86 template <class RegisterType> | |
| 87 std::unique_ptr<typename LwwRegister<RegisterType>::Changeset> | |
| 88 LwwRegister<RegisterType>::CreateChangeset(Revision from) const { | |
| 89 std::unique_ptr<Changeset> changeset = base::MakeUnique<Changeset>(); | |
| 90 changeset->last_modified.Set(last_modified_); | |
| 91 changeset->value.Set(value_); | |
| 92 return changeset; | |
| 93 } | |
| 94 | |
| 95 template <class RegisterType> | |
| 96 void LwwRegister<RegisterType>::ApplyChangeset( | |
| 97 const LwwRegister<RegisterType>::Changeset& changeset) { | |
| 98 const VersionVector remote_last_modified = changeset.last_modified().Invert(); | |
| 99 | |
| 100 if (last_modified_.CompareWithBias(remote_last_modified, bias_) == | |
| 101 VersionVector::Comparison::LessThan) { | |
| 102 value_ = changeset.value(); | |
| 103 } | |
| 104 last_modified_ = last_modified_.MergeWith(remote_last_modified); | |
| 105 } | |
| 106 | |
| 107 template <class RegisterType> | |
| 108 void LwwRegister<RegisterType>::ReleaseBefore(Revision checkpoint) { | |
| 109 // no-op | |
| 110 } | |
| 111 | |
| 112 template <class RegisterType> | |
| 113 struct LwwRegisterChangeset : public SerializableStruct { | |
| 114 LwwRegisterChangeset() : last_modified(this), value(this) {} | |
| 115 ~LwwRegisterChangeset() override {} | |
| 116 | |
| 117 Field<VersionVector> last_modified; | |
| 118 Field<RegisterType> value; | |
| 119 }; | |
| 120 | |
| 121 } // namespace helium | |
| 122 } // namespace blimp | |
| 123 | |
| 124 #endif // BLIMP_HELIUM_LWW_REGISTER_H_ | |
| OLD | NEW |