OLD | NEW |
| (Empty) |
1 // Copyright 2014 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 MOJO_PUBLIC_CPP_BINDINGS_LIB_SHARED_DATA_H_ | |
6 #define MOJO_PUBLIC_CPP_BINDINGS_LIB_SHARED_DATA_H_ | |
7 | |
8 #include "base/logging.h" | |
9 #include "base/macros.h" | |
10 #include "base/threading/thread_checker.h" | |
11 | |
12 namespace mojo { | |
13 namespace internal { | |
14 | |
15 // Used to allocate an instance of T that can be shared via reference counting. | |
16 // | |
17 // A default constructed SharedData does not have a Holder until it is set, | |
18 // either by assignment, or by accessing the value. As a result, it is not tied | |
19 // to any thread. The Holder is lazily allocated on first access. The complexity | |
20 // is due to the behaviour around copying. If a default constructed SharedData | |
21 // is copied into another, the two share the same empty state, and changing the | |
22 // value of one will affect the other. | |
23 template <typename T> | |
24 class SharedData { | |
25 public: | |
26 ~SharedData() { | |
27 if (holder_) | |
28 holder_->Release(); | |
29 } | |
30 | |
31 SharedData() : holder_(nullptr) {} | |
32 | |
33 explicit SharedData(const T& value) : holder_(new Holder(value)) {} | |
34 | |
35 SharedData(const SharedData<T>& other) { | |
36 other.LazyInit(); | |
37 holder_ = other.holder_; | |
38 holder_->Retain(); | |
39 } | |
40 | |
41 SharedData<T>& operator=(const SharedData<T>& other) { | |
42 other.LazyInit(); | |
43 if (other.holder_ == holder_) | |
44 return *this; | |
45 if (holder_) | |
46 holder_->Release(); | |
47 holder_ = other.holder_; | |
48 holder_->Retain(); | |
49 return *this; | |
50 } | |
51 | |
52 void reset() { | |
53 if (holder_) | |
54 holder_->Release(); | |
55 holder_ = nullptr; | |
56 } | |
57 | |
58 void reset(const T& value) { | |
59 if (holder_) | |
60 holder_->Release(); | |
61 holder_ = new Holder(value); | |
62 } | |
63 | |
64 void set_value(const T& value) { | |
65 LazyInit(); | |
66 holder_->value = value; | |
67 } | |
68 T* mutable_value() { | |
69 LazyInit(); | |
70 return &holder_->value; | |
71 } | |
72 const T& value() const { | |
73 LazyInit(); | |
74 return holder_->value; | |
75 } | |
76 | |
77 private: | |
78 class Holder { | |
79 public: | |
80 Holder() : value(), ref_count_(1) {} | |
81 Holder(const T& value) : value(value), ref_count_(1) {} | |
82 | |
83 void Retain() { | |
84 DCHECK(thread_checker_.CalledOnValidThread()); | |
85 ++ref_count_; | |
86 } | |
87 void Release() { | |
88 DCHECK(thread_checker_.CalledOnValidThread()); | |
89 if (--ref_count_ == 0) | |
90 delete this; | |
91 } | |
92 | |
93 T value; | |
94 | |
95 private: | |
96 int ref_count_; | |
97 base::ThreadChecker thread_checker_; | |
98 DISALLOW_COPY_AND_ASSIGN(Holder); | |
99 }; | |
100 | |
101 void LazyInit() const { | |
102 if (!holder_) | |
103 holder_ = new Holder(); | |
104 } | |
105 | |
106 mutable Holder* holder_; | |
107 }; | |
108 | |
109 } // namespace internal | |
110 } // namespace mojo | |
111 | |
112 #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_SHARED_DATA_H_ | |
OLD | NEW |