LCOV - code coverage report
Current view: top level - lunchbox - requestHandler.cpp (source / functions) Hit Total Coverage
Test: Lunchbox Lines: 124 139 89.2 %
Date: 2016-11-11 05:21:33 Functions: 25 27 92.6 %

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

Generated by: LCOV version 1.11