コード例 #1
0
ファイル: dlThread.cpp プロジェクト: AlbertR/cgru170
/*
	SleepSelf

	Just like the sleep() but with some hacks for thread cancellation.
	Initially tested in the netcache and moved here later.
	Later reworked to use the DlThread cancellation mechanisms.
*/
void DlThread::SleepSelf(unsigned i_seconds)
{
	TestCancel();

#if defined(_WIN32)
	/* This waits for cancellation, up to i_seconds seconds. */
	WaitForSingleObject( m_data->m_cancellation_event, i_seconds * 1000u );

#else

	/* Enable cancellation while sleeping. */
	
	pthread_cleanup_push(SleepCancel, this);

	pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, 0x0);

#ifdef DARWIN
	/* the cancellation point in sleep isn't implemented in OS X, see:

	http://lists.apple.com/archives/darwin-userlevel/2004/Mar/msg00016.html
	http://lists.apple.com/archives/darwin-kernel/2004/Jan/msg00032.html

	or google for 'pthread_cancel sleep OS X'. This means we have to check
	for cancellation explicitely. This will make the cancellation 'hang' a
	bit but there's no workaround until the OS X guys get their ass moving
	and implement decent threads.
	
	Update: It looks like the OS X people behind this are complete morons:
	http://lists.apple.com/archives/darwin-kernel/2007/Nov/msg00104.html

	Update(2): This got fixed at last in 10.6:
	http://lists.apple.com/archives/darwin-kernel/2009/Dec/msg00038.html
	We could remove this patch when we start targetting 10.6 and up.
	*/

	for (unsigned s = 0; s < i_seconds; ++s)
	{
		sleep(1);
		pthread_testcancel();
	}
#else
	sleep( i_seconds );

	/* It seems redhat 7 (libc 2.2.5) will not cancel properly when in the
	   sleep call. It will however get out of that call (probably due to
	   receiving a signal) so this simple test keeps us from hanging. */

	pthread_testcancel();
#endif

	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, 0x0);

	pthread_cleanup_pop(0);
#endif

	TestCancel();
}
コード例 #2
0
ファイル: SysThreadBase.cpp プロジェクト: AmbientMalice/pcsx2
// Tests for Pause and Suspend/Close requests.  If the thread is trying to be paused or
// closed, it will enter a wait/holding pattern here in this method until the managing
// thread releases it.  Use the return value to detect if changes to the thread's state
// may have been changed (based on the rule that other threads are not allowed to modify
// this thread's state without pausing or closing it first, to prevent race conditions).
//
// Return value:
//   TRUE if the thread was paused or closed; FALSE if the thread
//   continued execution unimpeded.
bool SysThreadBase::StateCheckInThread()
{
	switch( m_ExecMode )
	{

	#ifdef PCSX2_DEVBUILD		// optimize out handlers for these cases in release builds.
		case ExecMode_NoThreadYet:
			// threads should never have this state set while the thread is in any way
			// active or alive. (for obvious reasons!!)
			pxFailDev( "Invalid execution state detected." );
		return false;
	#endif

		case ExecMode_Opened:
			// Other cases don't need TestCancel() because its built into the various
			// threading wait/signal actions.
			TestCancel();
		return false;

		// -------------------------------------
		case ExecMode_Pausing:
		{
			OnPauseInThread();
			m_ExecMode = ExecMode_Paused;
			m_RunningLock.Release();
		}
		// fallthrough...

		case ExecMode_Paused:
			while( m_ExecMode == ExecMode_Paused )
				m_sem_Resume.WaitWithoutYield();
		
			m_RunningLock.Acquire();
			if( m_ExecMode != ExecMode_Closing )
			{
				OnResumeInThread( false );
				break;
			}
			m_sem_ChangingExecMode.Post();
			
		// fallthrough if we're switching to closing state...

		// -------------------------------------
		case ExecMode_Closing:
		{
			OnSuspendInThread();
			m_ExecMode = ExecMode_Closed;
			m_RunningLock.Release();
		}
		// fallthrough...

		case ExecMode_Closed:
			while( m_ExecMode == ExecMode_Closed )
				m_sem_Resume.WaitWithoutYield();

			m_RunningLock.Acquire();
			OnResumeInThread( true );
		break;

		jNO_DEFAULT;
	}
	
	return true;
}