ledger-core
Deffered.hpp
1 /*
2  *
3  * Deffered
4  * ledger-core
5  *
6  * Created by Pierre Pollastri on 20/01/2017.
7  *
8  * The MIT License (MIT)
9  *
10  * Copyright (c) 2016 Ledger
11  *
12  * Permission is hereby granted, free of charge, to any person obtaining a copy
13  * of this software and associated documentation files (the "Software"), to deal
14  * in the Software without restriction, including without limitation the rights
15  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16  * copies of the Software, and to permit persons to whom the Software is
17  * furnished to do so, subject to the following conditions:
18  *
19  * The above copyright notice and this permission notice shall be included in all
20  * copies or substantial portions of the Software.
21  *
22  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28  * SOFTWARE.
29  *
30  */
31 #ifndef LEDGER_CORE_DEFFERED_HPP
32 #define LEDGER_CORE_DEFFERED_HPP
33 
34 #include <memory>
35 #include <functional>
36 #include "../utils/Option.hpp"
37 #include "../utils/Try.hpp"
38 #include <mutex>
39 #include "../utils/Exception.hpp"
40 #include <queue>
41 #include "../api/ExecutionContext.hpp"
42 #include <tuple>
43 #include "../utils/LambdaRunnable.hpp"
44 
45 namespace ledger {
46  namespace core {
47 
48  template <typename T>
49  class Future;
50 
51  template <typename T>
52  class Promise;
53 
54  template <typename T>
55  class Deffered {
56 
57  public:
58  using Callback = std::function<void (const Try<T>&)>;
59 
60  friend class Future<T>;
61  friend class Promise<T>;
62  Deffered() {
63 
64  };
65  Deffered(const Deffered&) = delete;
66  Deffered(Deffered&&) = delete;
67 
68  void setResult(const Try<T>& result) {
69  {
70  std::lock_guard<std::mutex> lock(_lock);
71  ensureNotCompleted();
72  _value = result;
73  }
74  trigger();
75  }
76 
77  void setValue(const T& value) {
78  std::lock_guard<std::mutex> lock(_lock);
79  ensureNotCompleted();
80  _value = Try<T>(value);
81  _trigger();
82  };
83 
84  void setError(const Exception& exception) {
85  std::lock_guard<std::mutex> lock(_lock);
86  ensureNotCompleted();
87  Try<T> ex;
88  ex.fail(exception);
89  _value = ex;
90  _trigger();
91  }
92 
93  void addCallback(Callback callback, std::shared_ptr<api::ExecutionContext> context) {
94  // Add to the queue
95  std::lock_guard<std::mutex> lock(_lock);
96  _callbacks.push(std::make_tuple(callback, context));
97  _trigger();
98  }
99 
100  Option<Try<T>> getValue() const {
101  Option<Try<T>> cpy = _value;
102  return cpy;
103  }
104 
105  bool hasValue() const {
106  std::lock_guard<std::mutex> lock(_lock);
107  return _value.hasValue();
108  }
109 
110  void trigger() {
111  std::lock_guard<std::mutex> lock(_lock);
112  _trigger();
113  }
114 
115  private:
116  inline void ensureNotCompleted() {
117  if (_value.hasValue())
118  throw Exception(api::ErrorCode::ALREADY_COMPLETED, "This promise is already completed");
119  };
120 
121  inline void _trigger() {
122  if (_value.isEmpty() || _callbacks.empty()) {
123  return ;
124  }
125  while (!_callbacks.empty()) {
126  std::tuple<Callback, std::shared_ptr<api::ExecutionContext>> callback = _callbacks.front();
127  Callback cb = std::get<0>(callback);
128  auto value = _value.getValue();
129  std::get<1>(callback)->execute(make_runnable([cb, value] () {
130  cb(value);
131  }));
132  _callbacks.pop();
133  }
134  }
135 
136  private:
137  mutable std::mutex _lock;
138  Option<Try<T>> _value;
139  std::queue<std::tuple<Callback, std::shared_ptr<api::ExecutionContext>>> _callbacks;
140  };
141 
142 
143 
144  }
145 }
146 
147 
148 #endif //LEDGER_CORE_DEFFERED_HPP
Definition: Try.hpp:49
Definition: Option.hpp:49
Definition: Deffered.hpp:49
Definition: Deffered.hpp:55
Definition: Deffered.hpp:52
Definition: Account.cpp:8
Definition: Exception.hpp:45