Lunchbox  1.17.0
Multi-threaded C++ toolbox library for all application developers creating high-performance multi-threaded programs.
request.h
1 
2 /* Copyright (c) 2013-2015, Stefan.Eilemann@epfl.ch
3  *
4  * This library is free software; you can redistribute it and/or modify it under
5  * the terms of the GNU Lesser General Public License version 2.1 as published
6  * by the Free Software Foundation.
7  *
8  * This library is distributed in the hope that it will be useful, but WITHOUT
9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10  * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
11  * details.
12  *
13  * You should have received a copy of the GNU Lesser General Public License
14  * along with this library; if not, write to the Free Software Foundation, Inc.,
15  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16  */
17 
18 #ifndef LUNCHBOX_REQUEST_H
19 #define LUNCHBOX_REQUEST_H
20 
21 #include <boost/mpl/if.hpp>
22 #include <boost/type_traits/is_same.hpp>
23 #include <lunchbox/future.h>
24 
25 namespace lunchbox
26 {
27 class UnregisteredRequest : public std::runtime_error
28 {
29 public:
31  : std::runtime_error("wait on an unregistered request")
32  {
33  }
34 };
35 
40 template <class T>
41 class Request : public Future<T>
42 {
43  class Impl;
44 
45 public:
47  Request(RequestHandler& handler, const uint32_t request);
48 
53  virtual ~Request();
54 
56  uint32_t getID() const;
57 
65  void unregister();
66 };
67 } // namespace lunchbox
68 
69 // Implementation: Here be dragons
70 
71 #include <lunchbox/requestHandler.h>
72 namespace lunchbox
73 {
74 template <class T>
75 class Request<T>::Impl : public FutureImpl<T>
76 {
77  typedef typename boost::mpl::if_<boost::is_same<T, void>, void*, T>::type
78  value_t;
79 
80 public:
81  Impl(RequestHandler& handler, const uint32_t req)
82  : request(req)
83  , result(0)
84  , handler_(handler)
85  , state_(UNRESOLVED)
86  {
87  }
88  virtual ~Impl() {}
89  const uint32_t request;
90  value_t result;
91 
92  void unregister()
93  {
94  if (state_ == UNRESOLVED)
95  {
96  state_ = UNREGISTERED;
97  handler_.unregisterRequest(request);
98  }
99  }
100 
101  bool isUnresolved() const { return state_ == UNRESOLVED; }
102 
103 protected:
104  T wait(const uint32_t timeout) final
105  {
106  switch (state_)
107  {
108  case UNREGISTERED:
109  throw UnregisteredRequest();
110  case UNRESOLVED:
111  if (!handler_.waitRequest(request, result, timeout))
112  throw FutureTimeout();
113  state_ = DONE;
114  break;
115  case DONE:
116  default:
117  break;
118  }
119  return result;
120  }
121 
122  bool isReady() const final
123  {
124  switch (state_)
125  {
126  case UNRESOLVED:
127  return handler_.isRequestReady(request);
128  case UNREGISTERED:
129  return false;
130  default: // DONE:
131  return true;
132  }
133  }
134 
135 private:
136  RequestHandler& handler_;
137  enum State
138  {
139  UNRESOLVED,
140  DONE,
141  UNREGISTERED
142  };
143  State state_;
144 };
145 
146 template <>
147 inline void Request<void>::Impl::wait(const uint32_t timeout)
148 {
149  switch (state_)
150  {
151  case UNREGISTERED:
152  throw UnregisteredRequest();
153  case UNRESOLVED:
154  if (!handler_.waitRequest(request, result, timeout))
155  throw FutureTimeout();
156  state_ = DONE;
157  // No break
158  case DONE:;
159  }
160 }
161 
162 template <class T>
163 inline Request<T>::Request(RequestHandler& handler, const uint32_t request)
164  : Future<T>(new Impl(handler, request))
165 {
166 }
167 
168 template <class T>
170 {
171  if (static_cast<const Impl*>(this->impl_.get())->isUnresolved())
172  this->wait();
173 }
174 
175 template <class T>
176 inline uint32_t Request<T>::getID() const
177 {
178  return static_cast<const Impl*>(this->impl_.get())->request;
179 }
180 
181 template <class T>
183 {
184  static_cast<Impl*>(this->impl_.get())->unregister();
185 }
186 } // namespace lunchbox
187 
188 #endif // LUNCHBOX_REQUEST_H
bool isReady() const final
Definition: request.h:122
virtual ~Request()
Destruct and wait for completion of the request, unless relinquished.
Definition: request.h:169
uint32_t getID() const
Definition: request.h:176
Request(RequestHandler &handler, const uint32_t request)
Construct a new request.
Definition: request.h:163
T wait(const uint32_t timeout_=LB_TIMEOUT_INDEFINITE)
Wait for the promise to be fullfilled.
Definition: future.h:85
A Future implementation for a RequestHandler request.
Definition: request.h:41
void unregister()
Unregister this request from the request handler.
Definition: request.h:182
Base class to implement the wait method fulfilling the future.
Definition: future.h:39
A future represents a asynchronous operation.
Definition: future.h:62
Abstraction layer and common utilities for multi-threaded programming.
Definition: algorithm.h:29
A thread-safe request handler.
T wait(const uint32_t timeout) final
Wait for the promise to be fullfilled.
Definition: request.h:104