Lunchbox  1.12.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 <lunchbox/future.h>
22 #include <boost/mpl/if.hpp>
23 #include <boost/type_traits/is_same.hpp>
24 
25 namespace lunchbox
26 {
27 
28 class UnregisteredRequest : public std::runtime_error
29 {
30 public:
32  std::runtime_error( "wait on an unregistered request" ) {}
33 };
34 
39 template< class T > class Request : public Future< T >
40 {
41  class Impl;
42 
43 public:
45  Request( RequestHandler& handler, const uint32_t request );
46 
51  virtual ~Request();
52 
54  uint32_t getID() const;
55 
63  void unregister();
64 };
65 
66 }
67 
68 // Implementation: Here be dragons
69 
70 #include <lunchbox/requestHandler.h>
71 namespace lunchbox
72 {
73 template< class T > class Request< T >::Impl : public FutureImpl< T >
74 {
75  typedef typename
76  boost::mpl::if_< boost::is_same< T, void >, void*, T >::type value_t;
77 
78 public:
79  Impl( RequestHandler& handler, const uint32_t req )
80  : request( req )
81  , result( 0 )
82  , handler_( handler )
83  , state_( UNRESOLVED )
84  {}
85  virtual ~Impl() {}
86 
87  const uint32_t request;
88  value_t result;
89 
90  void unregister()
91  {
92  if( state_ == UNRESOLVED )
93  {
94  state_ = UNREGISTERED;
95  handler_.unregisterRequest( request );
96  }
97  }
98 
99  bool isUnresolved() const { return state_ == UNRESOLVED; }
100 
101 protected:
102  T wait( const uint32_t timeout ) final
103  {
104  switch( state_ )
105  {
106  case UNREGISTERED:
107  throw UnregisteredRequest();
108  case UNRESOLVED:
109  if ( !handler_.waitRequest( request, result, timeout ))
110  throw FutureTimeout();
111  state_ = DONE;
112  // No break
113  default: // DONE
114  return result;
115  }
116  }
117 
118  bool isReady() const final
119  {
120  switch( state_ )
121  {
122  case UNRESOLVED:
123  return handler_.isRequestReady( request );
124  case UNREGISTERED:
125  return false;
126  default: // DONE:
127  return true;
128  }
129  }
130 
131 private:
132  RequestHandler& handler_;
133  enum State { UNRESOLVED, DONE, UNREGISTERED };
134  State state_;
135 };
136 
137 template<> inline void Request< void >::Impl::wait( const uint32_t timeout )
138 {
139  switch( state_ )
140  {
141  case UNREGISTERED:
142  throw UnregisteredRequest();
143  case UNRESOLVED:
144  if ( !handler_.waitRequest( request, result, timeout ))
145  throw FutureTimeout();
146  state_ = DONE;
147  // No break
148  case DONE:
149  ;
150  }
151 }
152 
153 template< class T > inline
154 Request< T >::Request( RequestHandler& handler, const uint32_t request )
155  : Future< T >( new Impl( handler, request ))
156 {}
157 
158 template< class T > inline Request< T >::~Request()
159 {
160  if( static_cast< const Impl* >( this->impl_.get( ))->isUnresolved( ))
161  this->wait();
162 }
163 
164 template< class T > inline uint32_t Request< T >::getID() const
165 {
166  return static_cast< const Impl* >( this->impl_.get( ))->request;
167 }
168 
169 template< class T > inline void Request< T >::unregister()
170 {
171  static_cast< Impl* >( this->impl_.get( ))->unregister();
172 }
173 
174 }
175 
176 #endif //LUNCHBOX_REQUEST_H
virtual ~Request()
Destruct and wait for completion of the request, unless relinquished.
Definition: request.h:158
uint32_t getID() const
Definition: request.h:164
Request(RequestHandler &handler, const uint32_t request)
Construct a new request.
Definition: request.h:154
LUNCHBOX_API bool waitRequest(const uint32_t requestID, void *&result, const uint32_t timeout=LB_TIMEOUT_INDEFINITE)
Wait a given time for the completion of a request.
A Future implementation for a RequestHandler request.
Definition: request.h:39
RefPtr< FutureImpl< T > > Impl
The wait implementation.
Definition: future.h:67
void unregister()
Unregister this request from the request handler.
Definition: request.h:169
Base class to implement the wait method fulfilling the future.
Definition: future.h:37
bool isReady() const final
Definition: request.h:118
A future represents a asynchronous operation.
Definition: future.h:60
Abstraction layer and common utilities for multi-threaded programming.
Definition: algorithm.h:32
A thread-safe request handler.
T wait(const uint32_t timeout) final
Wait for the promise to be fullfilled.
Definition: request.h:102