LCOV - code coverage report
Current view: top level - lunchbox - request.h (source / functions) Hit Total Coverage
Test: Lunchbox Lines: 41 45 91.1 %
Date: 2017-08-03 05:21:41 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             : }
      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             : protected:
     103           3 :     T wait(const uint32_t timeout) final
     104             :     {
     105           3 :         switch (state_)
     106             :         {
     107             :         case UNREGISTERED:
     108           0 :             throw UnregisteredRequest();
     109             :         case UNRESOLVED:
     110           2 :             if (!handler_.waitRequest(request, result, timeout))
     111           0 :                 throw FutureTimeout();
     112           2 :             state_ = DONE;
     113             :         // No break
     114             :         default: // DONE
     115           3 :             return result;
     116             :         }
     117             :     }
     118             : 
     119           1 :     bool isReady() const final
     120             :     {
     121           1 :         switch (state_)
     122             :         {
     123             :         case UNRESOLVED:
     124           1 :             return handler_.isRequestReady(request);
     125             :         case UNREGISTERED:
     126           0 :             return false;
     127             :         default: // DONE:
     128           0 :             return true;
     129             :         }
     130             :     }
     131             : 
     132             : private:
     133             :     RequestHandler& handler_;
     134             :     enum State
     135             :     {
     136             :         UNRESOLVED,
     137             :         DONE,
     138             :         UNREGISTERED
     139             :     };
     140             :     State state_;
     141             : };
     142             : 
     143             : template <>
     144           4 : inline void Request<void>::Impl::wait(const uint32_t timeout)
     145             : {
     146           4 :     switch (state_)
     147             :     {
     148             :     case UNREGISTERED:
     149           1 :         throw UnregisteredRequest();
     150             :     case UNRESOLVED:
     151           3 :         if (!handler_.waitRequest(request, result, timeout))
     152           1 :             throw FutureTimeout();
     153           2 :         state_ = DONE;
     154             :     // No break
     155             :     case DONE:;
     156             :     }
     157           2 : }
     158             : 
     159             : template <class T>
     160           5 : inline Request<T>::Request(RequestHandler& handler, const uint32_t request)
     161           5 :     : Future<T>(new Impl(handler, request))
     162             : {
     163           5 : }
     164             : 
     165             : template <class T>
     166           5 : inline Request<T>::~Request()
     167             : {
     168           5 :     if (static_cast<const Impl*>(this->impl_.get())->isUnresolved())
     169           1 :         this->wait();
     170          10 : }
     171             : 
     172             : template <class T>
     173           4 : inline uint32_t Request<T>::getID() const
     174             : {
     175           4 :     return static_cast<const Impl*>(this->impl_.get())->request;
     176             : }
     177             : 
     178             : template <class T>
     179           1 : inline void Request<T>::unregister()
     180             : {
     181           1 :     static_cast<Impl*>(this->impl_.get())->unregister();
     182           1 : }
     183             : }
     184             : 
     185             : #endif // LUNCHBOX_REQUEST_H

Generated by: LCOV version 1.11