LCOV - code coverage report
Current view: top level - lunchbox - request.h (source / functions) Hit Total Coverage
Test: Lunchbox Lines: 43 47 91.5 %
Date: 2018-10-03 05:33:11 Functions: 29 35 82.9 %

          Line data    Source code
       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           1 : class UnregisteredRequest : public std::runtime_error
      28             : {
      29             : public:
      30           1 :     UnregisteredRequest()
      31           1 :         : std::runtime_error("wait on an unregistered request")
      32             :     {
      33           1 :     }
      34             : };
      35             : 
      36             : /**
      37             :  * A Future implementation for a RequestHandler request.
      38             :  * @version 1.9.1
      39             :  */
      40             : template <class T>
      41             : class Request : public Future<T>
      42             : {
      43             :     class Impl;
      44             : 
      45             : public:
      46             :     /** Construct a new request. */
      47             :     Request(RequestHandler& handler, const uint32_t request);
      48             : 
      49             :     /**
      50             :      * Destruct and wait for completion of the request, unless relinquished.
      51             :      * @version 1.9.1
      52             :      */
      53             :     virtual ~Request();
      54             : 
      55             :     /** @return the identifier of the request. @version 1.9.1 */
      56             :     uint32_t getID() const;
      57             : 
      58             :     /**
      59             :      * Unregister this request from the request handler.
      60             :      *
      61             :      * If called, wait will not be called at destruction and wait() will throw.
      62             :      * If the future has already been resolved this function has no effect.
      63             :      * @version 1.13
      64             :      */
      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           5 :     Impl(RequestHandler& handler, const uint32_t req)
      82             :         : request(req)
      83             :         , result(0)
      84             :         , handler_(handler)
      85           5 :         , state_(UNRESOLVED)
      86             :     {
      87           5 :     }
      88          10 :     virtual ~Impl() {}
      89             :     const uint32_t request;
      90             :     value_t result;
      91             : 
      92           1 :     void unregister()
      93             :     {
      94           1 :         if (state_ == UNRESOLVED)
      95             :         {
      96           1 :             state_ = UNREGISTERED;
      97           1 :             handler_.unregisterRequest(request);
      98             :         }
      99           1 :     }
     100             : 
     101           5 :     bool isUnresolved() const { return state_ == UNRESOLVED; }
     102             : 
     103             : protected:
     104           3 :     T wait(const uint32_t timeout) final
     105             :     {
     106           3 :         switch (state_)
     107             :         {
     108             :         case UNREGISTERED:
     109           0 :             throw UnregisteredRequest();
     110             :         case UNRESOLVED:
     111           2 :             if (!handler_.waitRequest(request, result, timeout))
     112           0 :                 throw FutureTimeout();
     113           2 :             state_ = DONE;
     114           2 :             break;
     115             :         case DONE:
     116             :         default:
     117           1 :             break;
     118             :         }
     119           3 :         return result;
     120             :     }
     121             : 
     122           1 :     bool isReady() const final
     123             :     {
     124           1 :         switch (state_)
     125             :         {
     126             :         case UNRESOLVED:
     127           1 :             return handler_.isRequestReady(request);
     128             :         case UNREGISTERED:
     129           0 :             return false;
     130             :         default: // DONE:
     131           0 :             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           4 : inline void Request<void>::Impl::wait(const uint32_t timeout)
     148             : {
     149           4 :     switch (state_)
     150             :     {
     151             :     case UNREGISTERED:
     152           1 :         throw UnregisteredRequest();
     153             :     case UNRESOLVED:
     154           3 :         if (!handler_.waitRequest(request, result, timeout))
     155           1 :             throw FutureTimeout();
     156           2 :         state_ = DONE;
     157             :     // No break
     158             :     case DONE:;
     159             :     }
     160           2 : }
     161             : 
     162             : template <class T>
     163           5 : inline Request<T>::Request(RequestHandler& handler, const uint32_t request)
     164           5 :     : Future<T>(new Impl(handler, request))
     165             : {
     166           5 : }
     167             : 
     168             : template <class T>
     169           5 : inline Request<T>::~Request()
     170             : {
     171           5 :     if (static_cast<const Impl*>(this->impl_.get())->isUnresolved())
     172           1 :         this->wait();
     173          10 : }
     174             : 
     175             : template <class T>
     176           4 : inline uint32_t Request<T>::getID() const
     177             : {
     178           4 :     return static_cast<const Impl*>(this->impl_.get())->request;
     179             : }
     180             : 
     181             : template <class T>
     182           1 : inline void Request<T>::unregister()
     183             : {
     184           1 :     static_cast<Impl*>(this->impl_.get())->unregister();
     185           1 : }
     186             : } // namespace lunchbox
     187             : 
     188             : #endif // LUNCHBOX_REQUEST_H

Generated by: LCOV version 1.11