Line data Source code
1 :
2 : /* Copyright (c) 2013-2014, 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 : /**
29 : * A Future implementation for a RequestHandler request.
30 : * @version 1.9.1
31 : */
32 : template< class T > class Request : public Future< T >
33 : {
34 : class Impl;
35 :
36 : public:
37 : /** Construct a new request. */
38 : Request( RequestHandler& handler, const uint32_t request );
39 :
40 : /**
41 : * Destruct and wait for completion of the request, unless relinquished.
42 : * @version 1.9.1
43 : */
44 : virtual ~Request();
45 :
46 : /** @return the identifier of the request. @version 1.9.1 */
47 : uint32_t getID() const;
48 :
49 : /**
50 : * Abandon the request.
51 : *
52 : * If called, wait will not be called at destruction and wait() will throw.
53 : * If the future has already been resolved this function has no effect.
54 : * @version 1.9.1
55 : */
56 : void relinquish();
57 : };
58 :
59 : }
60 :
61 : // Implementation: Here be dragons
62 :
63 : #include <lunchbox/requestHandler.h>
64 : namespace lunchbox
65 : {
66 : template< class T > class Request< T >::Impl : public FutureImpl< T >
67 : {
68 : typedef typename
69 : boost::mpl::if_< boost::is_same< T, void >, void*, T >::type value_t;
70 :
71 : public:
72 3 : Impl( RequestHandler& handler, const uint32_t req )
73 : : request( req )
74 : , result( 0 )
75 : , handler_( handler )
76 : , done_( false )
77 3 : , relinquished_( false )
78 3 : {}
79 6 : virtual ~Impl() {}
80 :
81 : const uint32_t request;
82 : value_t result;
83 :
84 : void relinquish() { relinquished_ = true; }
85 3 : bool isRelinquished() const { return relinquished_; }
86 :
87 : protected:
88 5 : T wait( const uint32_t timeout ) final
89 : {
90 5 : if( !done_ )
91 : {
92 2 : if( relinquished_ )
93 0 : LBUNREACHABLE;
94 :
95 2 : if ( !handler_.waitRequest( request, result, timeout ))
96 0 : throw FutureTimeout();
97 2 : done_ = true;
98 : }
99 5 : return result;
100 : }
101 :
102 0 : bool isReady() const final
103 : {
104 0 : return done_ || ( !relinquished_ && handler_.isRequestReady( request ));
105 : }
106 :
107 : private:
108 : RequestHandler& handler_;
109 : bool done_; //!< waitRequest finished
110 : bool relinquished_;
111 : };
112 :
113 1 : template<> inline void Request< void >::Impl::wait( const uint32_t timeout )
114 : {
115 1 : if( !done_ )
116 : {
117 1 : if( relinquished_ )
118 0 : LBUNREACHABLE;
119 :
120 1 : if ( !handler_.waitRequest( request, result, timeout ))
121 0 : throw FutureTimeout();
122 1 : done_ = true;
123 : }
124 1 : }
125 :
126 : template< class T > inline
127 3 : Request< T >::Request( RequestHandler& handler, const uint32_t request )
128 3 : : Future< T >( new Impl( handler, request ))
129 3 : {}
130 :
131 3 : template< class T > inline Request< T >::~Request()
132 : {
133 3 : if( !static_cast< const Impl* >( this->impl_.get( ))->isRelinquished( ))
134 3 : this->wait();
135 6 : }
136 :
137 4 : template< class T > inline uint32_t Request< T >::getID() const
138 : {
139 4 : return static_cast< const Impl* >( this->impl_.get( ))->request;
140 : }
141 :
142 : template< class T > inline void Request< T >::relinquish()
143 : {
144 : static_cast< Impl* >( this->impl_.get( ))->relinquish();
145 : }
146 :
147 : }
148 :
149 : #endif //LUNCHBOX_REQUEST_H
|