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 "mojo/public/cpp/system/macros.h"
9
10namespace mojo {
11namespace internal {
12
13// Used to allocate an instance of T that can be shared via reference counting.
14template <typename T>
15class SharedData {
16 public:
17  ~SharedData() {
18    holder_->Release();
19  }
20
21  SharedData() : holder_(new Holder()) {
22  }
23
24  explicit SharedData(const T& value) : holder_(new Holder(value)) {
25  }
26
27  SharedData(const SharedData<T>& other) : holder_(other.holder_) {
28    holder_->Retain();
29  }
30
31  SharedData<T>& operator=(const SharedData<T>& other) {
32    if (other.holder_ == holder_)
33      return *this;
34    holder_->Release();
35    holder_ = other.holder_;
36    holder_->Retain();
37    return *this;
38  }
39
40  void reset() {
41    holder_->Release();
42    holder_ = new Holder();
43  }
44
45  void reset(const T& value) {
46    holder_->Release();
47    holder_ = new Holder(value);
48  }
49
50  void set_value(const T& value) {
51    holder_->value = value;
52  }
53  T* mutable_value() {
54    return &holder_->value;
55  }
56  const T& value() const {
57    return holder_->value;
58  }
59
60 private:
61  class Holder {
62   public:
63    Holder() : value(), ref_count_(1) {
64    }
65    Holder(const T& value) : value(value), ref_count_(1) {
66    }
67
68    void Retain() { ++ref_count_; }
69    void Release() { if (--ref_count_ == 0) delete this; }
70
71    T value;
72
73   private:
74    int ref_count_;
75    MOJO_DISALLOW_COPY_AND_ASSIGN(Holder);
76  };
77
78  Holder* holder_;
79};
80
81}  // namespace internal
82}  // namespace mojo
83
84#endif  // MOJO_PUBLIC_CPP_BINDINGS_LIB_SHARED_DATA_H_
85