aglMessagePump.cpp

00001 
00002 /* Copyright (c) 2007-2009, Stefan Eilemann <eile@equalizergraphics.com> 
00003  *
00004  * This library is free software; you can redistribute it and/or modify it under
00005  * the terms of the GNU Lesser General Public License version 2.1 as published
00006  * by the Free Software Foundation.
00007  *  
00008  * This library is distributed in the hope that it will be useful, but WITHOUT
00009  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00010  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
00011  * details.
00012  * 
00013  * You should have received a copy of the GNU Lesser General Public License
00014  * along with this library; if not, write to the Free Software Foundation, Inc.,
00015  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00016  */
00017 
00018 #include "aglMessagePump.h"
00019 #include "global.h"
00020 
00021 #include <eq/base/debug.h>
00022 #include <eq/base/log.h>
00023 
00024 namespace eq
00025 {
00026 AGLMessagePump::AGLMessagePump()
00027         : _receiverQueue( 0 )
00028         , _needGlobalLock( true )
00029 {
00030     const OSStatus status = CreateEvent( 0, 0, 0, 0, kEventAttributeNone, 
00031                                          &_wakeupEvent );
00032     if( status != noErr )
00033     {
00034         EQWARN << "CreateEvent failed: " << status << std::endl;
00035         EQUNREACHABLE;
00036     }
00037 }
00038 
00039 AGLMessagePump::~AGLMessagePump()
00040 {
00041     ReleaseEvent( _wakeupEvent );
00042 }
00043 
00044 void AGLMessagePump::postWakeup()
00045 {
00046     if( !_receiverQueue )
00047     {
00048         EQWARN << "Receiver thread not waiting?" << std::endl;
00049         return;
00050     }
00051 
00052     PostEventToQueue( _receiverQueue, _wakeupEvent, kEventPriorityStandard );
00053 }
00054 
00055 void AGLMessagePump::_initReceiverQueue()
00056 {
00057     if( !_receiverQueue )
00058     {
00059         _receiverQueue = GetCurrentEventQueue();
00060         _needGlobalLock = ( _receiverQueue == GetMainEventQueue( ));
00061     }
00062 
00063     EQASSERTINFO( _receiverQueue == GetCurrentEventQueue(),
00064                   "MessagePump::pop() called from two different threads" );
00065 }
00066 
00067 void AGLMessagePump::dispatchOne()
00068 {
00069     _initReceiverQueue();
00070 
00071     while( true )
00072     {
00073         EventRef             event;
00074 
00075         if( _needGlobalLock )
00076             Global::enterCarbon();
00077             
00078         const OSStatus       status = ReceiveNextEvent( 0, 0, .05 /* 50ms */,
00079                                                         true, &event );
00080         if( status == noErr )
00081         {
00082             EQVERB << "Dispatch Carbon event " << event << std::endl;
00083 
00084             if( !_needGlobalLock )
00085                 Global::enterCarbon();
00086             const EventTargetRef target = GetEventDispatcherTarget();
00087             SendEventToEventTarget( event, target );
00088             Global::leaveCarbon();
00089 
00090             ReleaseEvent( event );
00091             return;
00092         }
00093         
00094         if( _needGlobalLock )
00095             Global::leaveCarbon();
00096 
00097         if( status != eventLoopTimedOutErr )
00098         {
00099             EQWARN << "ReceiveNextEvent failed: " << status << std::endl;
00100             return;
00101         }
00102     }
00103 }
00104 
00105 void AGLMessagePump::dispatchAll()
00106 {
00107     while( true )
00108     {
00109         EventRef       event;
00110 
00111         if( _needGlobalLock )
00112             Global::enterCarbon(); 
00113         const OSStatus status = ReceiveNextEvent( 0, 0, 0.0, true, &event );
00114 
00115         if( status == eventLoopTimedOutErr )
00116             break;
00117 
00118         if( status != noErr )
00119         {
00120             EQWARN << "ReceiveNextEvent failed: " << status << std::endl;
00121             break;
00122         }
00123 
00124         EQVERB << "Dispatch Carbon event " << event << std::endl;
00125 
00126         if( !_needGlobalLock )
00127             Global::enterCarbon();
00128         const EventTargetRef target = GetEventDispatcherTarget();
00129         SendEventToEventTarget( event, target );
00130         Global::leaveCarbon();
00131 
00132         ReleaseEvent( event );
00133     }
00134 
00135     if( _needGlobalLock )
00136         Global::leaveCarbon();
00137 
00138     // Init the receiver queue (and disable _needGlobalLock) after the first
00139     // batch (first ReceiveNextEvent is not thread safe)
00140     _initReceiverQueue();
00141 }
00142 }
Generated on Mon Aug 10 18:58:31 2009 for Equalizer 0.9 by  doxygen 1.5.8