Fix threaded input not actually running in the created thread. Allow nonthreaded input (by using the gui--i.e. main event loop--thread) according to PREFSMAN->m_bThreadedInput.

This commit is contained in:
Steve Checkoway
2005-12-27 05:55:06 +00:00
parent 7a76b58bd3
commit 2301565b2a
2 changed files with 48 additions and 31 deletions
@@ -13,8 +13,9 @@
#include <Carbon/Carbon.h> #include <Carbon/Carbon.h>
#include "InputHandler_Carbon.h" #include "InputHandler_Carbon.h"
#include "ForEach.h" #include "Foreach.h"
#include "RageUtil.h" #include "RageUtil.h"
#include "PrefsManager.h"
#include "archutils/Darwin/DarwinThreadHelpers.h" #include "archutils/Darwin/DarwinThreadHelpers.h"
using namespace std; using namespace std;
@@ -105,12 +106,8 @@ Device::~Device()
CALL( mQueue, stop ); CALL( mQueue, stop );
if( (runLoopSource = CALL(mQueue, getAsyncEventSource)) ) if( (runLoopSource = CALL(mQueue, getAsyncEventSource)) )
{ {
CFRunLoopRef ref; mach_port_deallocate( mach_task_self(), CALL(mQueue, getAsyncPort) );
CFRunLoopSourceInvalidate( runLoopSource );
ref = CFRunLoopRef( GetCFRunLoopFromEventLoop(GetMainEventLoop()) );
if( CFRunLoopContainsSource(ref, runLoopSource, kCFRunLoopDefaultMode) )
CFRunLoopRemoveSource( ref, runLoopSource, kCFRunLoopDefaultMode );
CFRelease( runLoopSource ); CFRelease( runLoopSource );
} }
@@ -228,6 +225,7 @@ bool Device::Open( io_object_t device )
void Device::StartQueue( CFRunLoopRef loopRef, IOHIDCallbackFunction callback, void *target, int refCon ) void Device::StartQueue( CFRunLoopRef loopRef, IOHIDCallbackFunction callback, void *target, int refCon )
{ {
CFRunLoopSourceRef runLoopSource; CFRunLoopSourceRef runLoopSource;
// This creates a run loop source and a mach port. They are released in the dtor.
IOReturn ret = CALL( mQueue, createAsyncEventSource, &runLoopSource ); IOReturn ret = CALL( mQueue, createAsyncEventSource, &runLoopSource );
if( ret != kIOReturnSuccess ) if( ret != kIOReturnSuccess )
@@ -236,12 +234,8 @@ void Device::StartQueue( CFRunLoopRef loopRef, IOHIDCallbackFunction callback, v
return; return;
} }
CFRunLoopRef runLoop; if( !CFRunLoopContainsSource(loopRef, runLoopSource, kCFRunLoopDefaultMode) )
CFRunLoopAddSource( loopRef, runLoopSource, kCFRunLoopDefaultMode );
runLoop = CFRunLoopRef( GetCFRunLoopFromEventLoop(GetMainEventLoop()) );
if( !CFRunLoopContainsSource(runLoop, runLoopSource, kCFRunLoopDefaultMode) )
CFRunLoopAddSource( runLoop, runLoopSource, kCFRunLoopDefaultMode );
CALL( mQueue, setEventCallout, callback, target, (void *)refCon ); CALL( mQueue, setEventCallout, callback, target, (void *)refCon );
@@ -696,6 +690,7 @@ void InputHandler_Carbon::QueueCallBack( void *target, int result, void *refcon,
static void RunLoopStarted( CFRunLoopObserverRef o, CFRunLoopActivity a, void *sem ) static void RunLoopStarted( CFRunLoopObserverRef o, CFRunLoopActivity a, void *sem )
{ {
CFRunLoopObserverInvalidate( o );
CFRelease( o ); // we don't need this any longer CFRelease( o ); // we don't need this any longer
((RageSemaphore *)sem)->Post(); ((RageSemaphore *)sem)->Post();
} }
@@ -703,14 +698,11 @@ static void RunLoopStarted( CFRunLoopObserverRef o, CFRunLoopActivity a, void *s
int InputHandler_Carbon::Run( void *data ) int InputHandler_Carbon::Run( void *data )
{ {
InputHandler_Carbon *This = (InputHandler_Carbon *)data; InputHandler_Carbon *This = (InputHandler_Carbon *)data;
CFRunLoopRef loopRef = CFRunLoopGetCurrent();
int n = 0;
CFRetain( loopRef ); This->mLoopRef = CFRunLoopGetCurrent();
FOREACH( Device *, This->mDevices, i ) CFRetain( This->mLoopRef );
(*i)->StartQueue( loopRef, InputHandler_Carbon::QueueCallBack, This, n++ );
This->mLoopRef = loopRef;
This->StartDevices();
SetThreadPrecedence( 100 ); SetThreadPrecedence( 100 );
/* /*
@@ -720,17 +712,33 @@ int InputHandler_Carbon::Run( void *data )
CFRunLoopObserverContext context = { 0, &This->mSem, NULL, NULL, NULL }; CFRunLoopObserverContext context = { 0, &This->mSem, NULL, NULL, NULL };
CFRunLoopObserverRef o = CFRunLoopObserverCreate( kCFAllocatorDefault, kCFRunLoopEntry, CFRunLoopObserverRef o = CFRunLoopObserverCreate( kCFAllocatorDefault, kCFRunLoopEntry,
false, 0, RunLoopStarted, &context); false, 0, RunLoopStarted, &context);
CFRunLoopAddObserver( loopRef, o, kCFRunLoopDefaultMode ); CFRunLoopAddObserver( This->mLoopRef, o, kCFRunLoopDefaultMode );
CFRunLoopRun(); CFRunLoopRun();
LOG->Trace( "Shutting down input handler thread..." );
return 0; return 0;
} }
// mLoopRef needs to be set before this is called
void InputHandler_Carbon::StartDevices()
{
int n = 0;
ASSERT( mLoopRef );
FOREACH( Device *, mDevices, i )
(*i)->StartQueue( mLoopRef, InputHandler_Carbon::QueueCallBack, this, n++ );
}
InputHandler_Carbon::~InputHandler_Carbon() InputHandler_Carbon::~InputHandler_Carbon()
{ {
CFRunLoopStop( CFRunLoopRef(mLoopRef) );
mInputThread.Wait();
FOREACH( Device *, mDevices, i ) FOREACH( Device *, mDevices, i )
delete *i; delete *i;
if( PREFSMAN->m_bThreadedInput )
{
CFRunLoopStop( mLoopRef );
CFRelease( mLoopRef );
mInputThread.Wait();
LOG->Trace( "Input handler thread shut down." );
}
if( mMasterPort ) if( mMasterPort )
mach_port_deallocate( mach_task_self(), mMasterPort ); mach_port_deallocate( mach_task_self(), mMasterPort );
} }
@@ -834,10 +842,18 @@ InputHandler_Carbon::InputHandler_Carbon() : mMasterPort( 0 ), mSem( "Input thre
IOObjectRelease( iter ); IOObjectRelease( iter );
} }
if( PREFSMAN->m_bThreadedInput )
{
mInputThread.SetName( "Input thread" ); mInputThread.SetName( "Input thread" );
mInputThread.Create( InputHandler_Carbon::Run, this ); mInputThread.Create( InputHandler_Carbon::Run, this );
// Wait for the run loop to start before returning. // Wait for the run loop to start before returning.
mSem.Wait(); mSem.Wait();
}
else
{
mLoopRef = CFRunLoopRef( GetCFRunLoopFromEventLoop(GetMainEventLoop()) );
StartDevices();
}
} }
void InputHandler_Carbon::GetDevicesAndDescriptions( vector<InputDevice>& dev, vector<CString>& desc ) void InputHandler_Carbon::GetDevicesAndDescriptions( vector<InputDevice>& dev, vector<CString>& desc )
@@ -850,8 +866,7 @@ void InputHandler_Carbon::GetDevicesAndDescriptions( vector<InputDevice>& dev, v
const JoystickDevice *jd = dynamic_cast<const JoystickDevice *>(*i); const JoystickDevice *jd = dynamic_cast<const JoystickDevice *>(*i);
/* This could be break since right now KeyboardDevices follow /* This could be break since right now KeyboardDevices follow
* the JoystickDevices, but that is brittle. * the JoystickDevices, but that is brittle. */
*/
if (!jd) if (!jd)
continue; continue;
@@ -2,6 +2,7 @@
#define JOYSTICK_H #define JOYSTICK_H
#include <vector> #include <vector>
#include <CoreFoundation/CoreFoundation.h>
#include "InputHandler.h" #include "InputHandler.h"
#include "RageThreads.h" #include "RageThreads.h"
@@ -14,9 +15,10 @@ private:
std::vector<Device *> mDevices; std::vector<Device *> mDevices;
RageThread mInputThread; RageThread mInputThread;
RageSemaphore mSem; RageSemaphore mSem;
void *mLoopRef; CFRunLoopRef mLoopRef;
static int Run(void *data); static int Run( void *data );
void StartDevices();
public: public:
InputHandler_Carbon(); InputHandler_Carbon();