1a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
2a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// found in the LICENSE file.
4a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
5e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_SHARED_DATA_H_
6e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#define MOJO_PUBLIC_CPP_BINDINGS_LIB_SHARED_DATA_H_
7a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
8cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "mojo/public/cpp/system/macros.h"
9cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
10a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace mojo {
11a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace internal {
12a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
13a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Used to allocate an instance of T that can be shared via reference counting.
14a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)template <typename T>
15a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)class SharedData {
16a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) public:
17a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ~SharedData() {
18a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    holder_->Release();
19a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
20a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
21a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  SharedData() : holder_(new Holder()) {
22a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
23a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
24a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  explicit SharedData(const T& value) : holder_(new Holder(value)) {
25a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
26a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
27a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  SharedData(const SharedData<T>& other) : holder_(other.holder_) {
28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    holder_->Retain();
29a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
30a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
31a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  SharedData<T>& operator=(const SharedData<T>& other) {
32a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (other.holder_ == holder_)
33a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return *this;
34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    holder_->Release();
35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    holder_ = other.holder_;
36a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    holder_->Retain();
370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return *this;
38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
39a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
40a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  void reset() {
41a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    holder_->Release();
42a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    holder_ = new Holder();
43a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
44a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  void reset(const T& value) {
46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    holder_->Release();
47a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    holder_ = new Holder(value);
48a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  void set_value(const T& value) {
51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    holder_->value = value;
52a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  T* mutable_value() {
54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return &holder_->value;
55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  const T& value() const {
57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return holder_->value;
58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) private:
61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  class Holder {
62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)   public:
63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    Holder() : value(), ref_count_(1) {
64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
65a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    Holder(const T& value) : value(value), ref_count_(1) {
66a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
67a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
68a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    void Retain() { ++ref_count_; }
69a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    void Release() { if (--ref_count_ == 0) delete this; }
70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    T value;
72a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
73a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)   private:
74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    int ref_count_;
75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    MOJO_DISALLOW_COPY_AND_ASSIGN(Holder);
76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  };
77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
78a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  Holder* holder_;
79a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)};
80a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
81a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}  // namespace internal
82a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}  // namespace mojo
83a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
84e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#endif  // MOJO_PUBLIC_CPP_BINDINGS_LIB_SHARED_DATA_H_
85