LCOV - code coverage report
Current view: top level - lunchbox - requestHandler.cpp (source / functions) Hit Total Coverage
Test: lcov2.info Lines: 119 139 85.6 %
Date: 2014-10-01 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, uint128_t& rUint128,
     174             :                                   const uint32_t timeout )
     175             : {
     176             :     Record::Result result;
     177           1 :     if( !_impl->waitRequest( requestID, result, timeout ))
     178           0 :         return false;
     179             : 
     180           1 :     rUint128.high() = result.rUint128.high;
     181           1 :     rUint128.low() = result.rUint128.low;
     182           1 :     return true;
     183             : }
     184             : 
     185           1 : bool RequestHandler::waitRequest( const uint32_t requestID, bool& rBool,
     186             :                                   const uint32_t timeout )
     187             : {
     188             :     Record::Result result;
     189           1 :     if( !_impl->waitRequest( requestID, result, timeout ))
     190           0 :         return false;
     191             : 
     192           1 :     rBool = result.rBool;
     193           1 :     return true;
     194             : }
     195           1 : bool RequestHandler::waitRequest( const uint32_t requestID )
     196             : {
     197             :     Record::Result result;
     198           1 :     return _impl->waitRequest( requestID, result, LB_TIMEOUT_INDEFINITE );
     199             : }
     200             : 
     201           5 : void* RequestHandler::getRequestData( const uint32_t requestID )
     202             : {
     203           5 :     ScopedFastWrite mutex( _impl->lock );
     204           5 :     RecordHashCIter i = _impl->requests.find( requestID );
     205           5 :     if( i == _impl->requests.end( ))
     206           0 :         return 0;
     207             : 
     208           5 :     return i->second->data;
     209             : }
     210             : 
     211           2 : void RequestHandler::serveRequest( const uint32_t requestID, void* result )
     212             : {
     213           2 :     Record* request = 0;
     214             :     {
     215           2 :         ScopedFastWrite mutex( _impl->lock );
     216           2 :         RecordHashCIter i = _impl->requests.find( requestID );
     217             : 
     218           2 :         if( i != _impl->requests.end( ))
     219           2 :             request = i->second;
     220             :     }
     221           2 :     if( request )
     222             :     {
     223           2 :         request->result.rPointer = result;
     224           2 :         request->lock.unset();
     225             :     }
     226           2 : }
     227             : 
     228           1 : void RequestHandler::serveRequest( const uint32_t requestID, uint32_t result )
     229             : {
     230           1 :     Record* request = 0;
     231             :     {
     232           1 :         ScopedFastWrite mutex( _impl->lock );
     233           1 :         RecordHashCIter i = _impl->requests.find( requestID );
     234             : 
     235           1 :         if( i != _impl->requests.end( ))
     236           1 :             request = i->second;
     237             :     }
     238           1 :     if( request )
     239             :     {
     240           1 :         request->result.rUint32 = result;
     241           1 :         request->lock.unset();
     242             :     }
     243           1 : }
     244             : 
     245           1 : void RequestHandler::serveRequest( const uint32_t requestID, bool result )
     246             : {
     247           1 :     Record* request = 0;
     248             :     {
     249           1 :         ScopedFastWrite mutex( _impl->lock );
     250           1 :         RecordHashCIter i = _impl->requests.find( requestID );
     251             : 
     252           1 :         if( i != _impl->requests.end( ))
     253           1 :             request = i->second;
     254             :     }
     255           1 :     if( request )
     256             :     {
     257           1 :         request->result.rBool = result;
     258           1 :         request->lock.unset();
     259             :     }
     260           1 : }
     261             : 
     262           1 : void RequestHandler::serveRequest( const uint32_t requestID,
     263             :                                    const uint128_t& result )
     264             : {
     265           1 :     Record* request = 0;
     266             :     {
     267           1 :         ScopedFastWrite mutex( _impl->lock );
     268           1 :         RecordHashCIter i = _impl->requests.find( requestID );
     269             : 
     270           1 :         if( i != _impl->requests.end( ))
     271           1 :             request = i->second;
     272             :     }
     273             : 
     274           1 :     if( request )
     275             :     {
     276           1 :         request->result.rUint128.low = result.low();
     277           1 :         request->result.rUint128.high = result.high();
     278           1 :         request->lock.unset();
     279             :     }
     280           1 : }
     281             : 
     282           1 : bool RequestHandler::isRequestReady( const uint32_t requestID ) const
     283             : {
     284           1 :     ScopedFastWrite mutex( _impl->lock );
     285           1 :     RecordHashCIter i = _impl->requests.find( requestID );
     286           1 :     if( i == _impl->requests.end( ))
     287           0 :         return false;
     288             : 
     289           1 :     Record* request = i->second;
     290           1 :     return !request->lock.isSet();
     291             : }
     292             : 
     293           0 : bool RequestHandler::hasPendingRequests() const
     294             : {
     295           0 :     return !_impl->requests.empty();
     296             : }
     297             : 
     298           0 : std::ostream& operator << ( std::ostream& os, const detail::RequestHandler& rh )
     299             : {
     300           0 :     ScopedFastWrite mutex( rh.lock );
     301           0 :     for( RecordHashCIter i = rh.requests.begin(); i != rh.requests.end(); ++i )
     302             :     {
     303           0 :         os << "request " << i->first << " served " << i->second->lock.isSet()
     304           0 :            << std::endl;
     305             :     }
     306             : 
     307           0 :     return os;
     308             : }
     309             : 
     310           0 : std::ostream& operator << ( std::ostream& os, const RequestHandler& rh )
     311             : {
     312           0 :     return os << *rh._impl;
     313             : }
     314             : 
     315          90 : }

Generated by: LCOV version 1.10