MT Showcase SDK
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Pages
BackendComponents.hpp
1 #pragma once
2 
3 #include <folly/futures/Future.h>
4 #include <folly/Executor.h>
5 
6 #include <mutex>
7 
8 namespace Showcase
9 {
10 
14 
16 
18  template <typename T>
19  class Generator :
20  public std::enable_shared_from_this<Generator<T>>
21  {
22  public:
23  typedef T ValueType;
24 
25  virtual ~Generator() {}
30  virtual folly::Future<T> next(folly::Executor* executor = nullptr) = 0;
31  };
32 
33 
34  // --------------------------------------------------------------------
35 
36  template <typename T>
37  struct HasValueType
38  {
39  template <typename C> static char test(typename C::ValueType*);
40  template <typename C> static long test(...);
41  static const bool value = sizeof(test<T>(0)) == sizeof(char);
42  };
43 
44  template <typename T, bool = HasValueType<T>::value>
45  struct IsGenerator
46  {
47  static const bool value = false;
48  };
49 
50  template <typename T>
51  struct IsGenerator<T, true>
52  {
53  typedef typename T::ValueType type;
54  static const bool value = std::is_base_of<Generator<type>, T>::value;
55  };
56 
57  // --------------------------------------------------------------------
58 
61  template <typename GeneratorType>
62  class SynchronousGenerator : public GeneratorType
63  {
64  public:
65  static_assert(IsGenerator<GeneratorType>::value,
66  "Need to use Generator or its subclass as a type "
67  "parameter for SynchronousGenerator.");
68  typedef typename GeneratorType::ValueType ValueType;
69 
70  virtual folly::Future<ValueType> next(folly::Executor* executor = nullptr) override;
71 
72  protected:
75  virtual ValueType generateNextItem() = 0;
76 
77  private:
78  std::mutex m_mutex;
79  };
80 
81  // --------------------------------------------------------------------
82 
83 
84  template <typename GeneratorType>
85  folly::Future<typename SynchronousGenerator<GeneratorType>::ValueType>
86  SynchronousGenerator<GeneratorType>::next(folly::Executor* executor)
87  {
89 
90  auto ptr = this->shared_from_this();
91 
92  std::shared_ptr<Me> me = std::dynamic_pointer_cast<Me>(ptr);
93  if(!me)
94  return folly::makeFuture<ValueType>(ValueType());
95 
96  std::weak_ptr<Me> weak = me;
97 
98  auto func = [weak]() -> ValueType {
99  std::shared_ptr<Me> me = weak.lock();
100  if(me) {
101  std::lock_guard<std::mutex> g(me->m_mutex);
102  return me->generateNextItem();
103  } else {
104  return ValueType();
105  }
106  };
107 
108  if(executor)
109  return folly::via(executor, func);
110  else
111  return folly::makeFutureWith(func);
112  }
113 
114 
117 
118 }