LCOV - code coverage report
Current view: top level - lunchbox - requestHandler.cpp (source / functions) Hit Total Coverage
Test: Lunchbox Lines: 119 139 85.6 %
Date: 2015-07-07 14:54:45 Functions: 23 27 85.2 %

          Line data    Source code
       1             : 
       2             : /* Copyright (c) 2005-2014, Stefan Eilemann <eile@equalizergraphics.com>
       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             : #include "requestHandler.h"
      19             : 
      20             : #include "scopedMutex.h"
      21             : 
      22             : #include <lunchbox/debug.h>
      23             : #include <lunchbox/stdExt.h>
      24             : #include <lunchbox/spinLock.h>
      25             : #include <lunchbox/timedLock.h>
      26             : 
      27             : #include <list>
      28             : 
      29             : namespace lunchbox
      30             : {
      31             : //! @cond IGNORE
      32             : namespace
      33             : {
      34             : struct Record
      35             : {
      36           3 :     Record() { lock.set(); }
      37           3 :     ~Record(){}
      38             : 
      39             :     TimedLock lock;
      40             :     void*     data;
      41             : 
      42             :     union Result
      43             :     {
      44             :         void*    rPointer;
      45             :         uint32_t rUint32;
      46             :         bool     rBool;
      47             :         struct
      48             :         {
      49             :             uint64_t low;
      50             :             uint64_t high;
      51             :         } rUint128;
      52             :     } result;
      53             : };
      54             : typedef stde::hash_map< uint32_t, Record* > RecordHash;
      55             : typedef RecordHash::const_iterator RecordHashCIter;
      56             : }
      57             : 
      58             : namespace detail
      59             : {
      60           1 : class RequestHandler
      61             : {
      62             : public:
      63           1 :     RequestHandler() : requestID( 1 ) {}
      64             : 
      65           5 :     uint32_t registerRequest( void* data )
      66             :     {
      67           5 :         ScopedFastWrite mutex( lock );
      68             : 
      69             :         Record* request;
      70           5 :         if( freeRecords.empty( ))
      71           3 :             request = new Record;
      72             :         else
      73             :         {
      74           2 :             request = freeRecords.front();
      75           2 :             freeRecords.pop_front();
      76             :         }
      77             : 
      78           5 :         request->data = data;
      79           5 :         requestID = ( requestID + 1 ) % LB_MAX_UINT32;
      80           5 :         requests[ requestID ] = request;
      81           5 :         return requestID;
      82             :     }
      83             : 
      84           5 :     bool waitRequest( const uint32_t requestID_, Record::Result& result,
      85             :                       const uint32_t timeout )
      86             :     {
      87           5 :         result.rUint128.low = 0;
      88           5 :         result.rUint128.high = 0;
      89           5 :         Record* request = 0;
      90             :         {
      91           5 :             ScopedFastWrite mutex( lock );
      92           5 :             RecordHashCIter i = requests.find( requestID_ );
      93           5 :             if( i == requests.end( ))
      94           0 :                 return false;
      95             : 
      96           5 :             request = i->second;
      97             :         }
      98             : 
      99           5 :         const bool requestServed = request->lock.set( timeout );
     100           5 :         if( requestServed )
     101           5 :             result = request->result;
     102             : 
     103           5 :         unregisterRequest( requestID_ );
     104           5 :         return requestServed;
     105             :     }
     106             : 
     107           5 :     void unregisterRequest( const uint32_t requestID_ )
     108             :     {
     109           5 :         ScopedFastWrite mutex( lock );
     110           5 :         RecordHash::iterator i = requests.find( requestID_ );
     111           5 :         if( i == requests.end( ))
     112           5 :             return;
     113             : 
     114           5 :         Record* request = i->second;
     115           5 :         requests.erase( i );
     116           5 :         freeRecords.push_front( request );
     117             :     }
     118             : 
     119             :     mutable lunchbox::SpinLock lock;
     120             :     uint32_t requestID;
     121             :     RecordHash requests;
     122             :     std::list<Record*> freeRecords;
     123             : };
     124             : }
     125             : // @endcond
     126             : 
     127           1 : RequestHandler::RequestHandler()
     128           1 :         : _impl( new detail::RequestHandler )
     129           1 : {}
     130             : 
     131           2 : RequestHandler::~RequestHandler()
     132             : {
     133           5 :     while( !_impl->freeRecords.empty( ))
     134             :     {
     135           3 :         Record* request = _impl->freeRecords.front();
     136           3 :         _impl->freeRecords.pop_front();
     137           3 :         delete request;
     138             :     }
     139           1 :     delete _impl;
     140           1 : }
     141             : 
     142           5 : uint32_t RequestHandler::_register( void* data )
     143             : {
     144           5 :     return _impl->registerRequest( data );
     145             : }
     146             : 
     147           0 : void RequestHandler::unregisterRequest( const uint32_t requestID )
     148             : {
     149           0 :     _impl->unregisterRequest( requestID );
     150           0 : }
     151             : 
     152           1 : bool RequestHandler::waitRequest( const uint32_t requestID, void*& rPointer,
     153             :                                   const uint32_t timeout )
     154             : {
     155             :     Record::Result result;
     156           1 :     if( !_impl->waitRequest( requestID, result, timeout ))
     157           0 :         return false;
     158             : 
     159           1 :     rPointer = result.rPointer;
     160           1 :     return true;
     161             : }
     162           1 : bool RequestHandler::waitRequest( const uint32_t requestID, uint32_t& rUint32,
     163             :                                   const uint32_t timeout )
     164             : {
     165             :     Record::Result result;
     166           1 :     if( !_impl->waitRequest( requestID, result, timeout ))
     167           0 :         return false;
     168             : 
     169           1 :     rUint32 = result.rUint32;
     170           1 :     return true;
     171             : }
     172             : 
     173           1 : bool RequestHandler::waitRequest( const uint32_t requestID,
     174             :                                   servus::uint128_t& rUint128,
     175             :                                   const uint32_t timeout )
     176             : {
     177             :     Record::Result result;
     178           1 :     if( !_impl->waitRequest( requestID, result, timeout ))
     179           0 :         return false;
     180             : 
     181           1 :     rUint128.high() = result.rUint128.high;
     182           1 :     rUint128.low() = result.rUint128.low;
     183           1 :     return true;
     184             : }
     185             : 
     186           1 : bool RequestHandler::waitRequest( const uint32_t requestID, bool& rBool,
     187             :                                   const uint32_t timeout )
     188             : {
     189             :     Record::Result result;
     190           1 :     if( !_impl->waitRequest( requestID, result, timeout ))
     191           0 :         return false;
     192             : 
     193           1 :     rBool = result.rBool;
     194           1 :     return true;
     195             : }
     196           1 : bool RequestHandler::waitRequest( const uint32_t requestID )
     197             : {
     198             :     Record::Result result;
     199           1 :     return _impl->waitRequest( requestID, result, LB_TIMEOUT_INDEFINITE );
     200             : }
     201             : 
     202           5 : void* RequestHandler::getRequestData( const uint32_t requestID )
     203             : {
     204           5 :     ScopedFastWrite mutex( _impl->lock );
     205           5 :     RecordHashCIter i = _impl->requests.find( requestID );
     206           5 :     if( i == _impl->requests.end( ))
     207           0 :         return 0;
     208             : 
     209           5 :     return i->second->data;
     210             : }
     211             : 
     212           2 : void RequestHandler::serveRequest( const uint32_t requestID, void* result )
     213             : {
     214           2 :     Record* request = 0;
     215             :     {
     216           2 :         ScopedFastWrite mutex( _impl->lock );
     217           2 :         RecordHashCIter i = _impl->requests.find( requestID );
     218             : 
     219           2 :         if( i != _impl->requests.end( ))
     220           2 :             request = i->second;
     221             :     }
     222           2 :     if( request )
     223             :     {
     224           2 :         request->result.rPointer = result;
     225           2 :         request->lock.unset();
     226             :     }
     227           2 : }
     228             : 
     229           1 : void RequestHandler::serveRequest( const uint32_t requestID, uint32_t result )
     230             : {
     231           1 :     Record* request = 0;
     232             :     {
     233           1 :         ScopedFastWrite mutex( _impl->lock );
     234           1 :         RecordHashCIter i = _impl->requests.find( requestID );
     235             : 
     236           1 :         if( i != _impl->requests.end( ))
     237           1 :             request = i->second;
     238             :     }
     239           1 :     if( request )
     240             :     {
     241           1 :         request->result.rUint32 = result;
     242           1 :         request->lock.unset();
     243             :     }
     244           1 : }
     245             : 
     246           1 : void RequestHandler::serveRequest( const uint32_t requestID, bool result )
     247             : {
     248           1 :     Record* request = 0;
     249             :     {
     250           1 :         ScopedFastWrite mutex( _impl->lock );
     251           1 :         RecordHashCIter i = _impl->requests.find( requestID );
     252             : 
     253           1 :         if( i != _impl->requests.end( ))
     254           1 :             request = i->second;
     255             :     }
     256           1 :     if( request )
     257             :     {
     258           1 :         request->result.rBool = result;
     259           1 :         request->lock.unset();
     260             :     }
     261           1 : }
     262             : 
     263           1 : void RequestHandler::serveRequest( const uint32_t requestID,
     264             :                                    const servus::uint128_t& result )
     265             : {
     266           1 :     Record* request = 0;
     267             :     {
     268           1 :         ScopedFastWrite mutex( _impl->lock );
     269           1 :         RecordHashCIter i = _impl->requests.find( requestID );
     270             : 
     271           1 :         if( i != _impl->requests.end( ))
     272           1 :             request = i->second;
     273             :     }
     274             : 
     275           1 :     if( request )
     276             :     {
     277           1 :         request->result.rUint128.low = result.low();
     278           1 :         request->result.rUint128.high = result.high();
     279           1 :         request->lock.unset();
     280             :     }
     281           1 : }
     282             : 
     283           1 : bool RequestHandler::isRequestReady( const uint32_t requestID ) const
     284             : {
     285           1 :     ScopedFastWrite mutex( _impl->lock );
     286           1 :     RecordHashCIter i = _impl->requests.find( requestID );
     287           1 :     if( i == _impl->requests.end( ))
     288           0 :         return false;
     289             : 
     290           1 :     Record* request = i->second;
     291           1 :     return !request->lock.isSet();
     292             : }
     293             : 
     294           0 : bool RequestHandler::hasPendingRequests() const
     295             : {
     296           0 :     return !_impl->requests.empty();
     297             : }
     298             : 
     299           0 : std::ostream& operator << ( std::ostream& os, const detail::RequestHandler& rh )
     300             : {
     301           0 :     ScopedFastWrite mutex( rh.lock );
     302           0 :     for( RecordHashCIter i = rh.requests.begin(); i != rh.requests.end(); ++i )
     303             :     {
     304           0 :         os << "request " << i->first << " served " << i->second->lock.isSet()
     305           0 :            << std::endl;
     306             :     }
     307             : 
     308           0 :     return os;
     309             : }
     310             : 
     311           0 : std::ostream& operator << ( std::ostream& os, const RequestHandler& rh )
     312             : {
     313           0 :     return os << *rh._impl;
     314             : }
     315             : 
     316          81 : }

Generated by: LCOV version 1.11