⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usersync.cpp

📁 mini http server,可以集成嵌入到程序中,实现简单的web功能
💻 CPP
📖 第 1 页 / 共 5 页
字号:
				- PI_STACKDISPLACEMENT;	// down
#elif defined(CONFIG_ASM_HP)
			aContext[0] = ((size_t)pStack) + ((size_t)iStackSize)
				- PI_STACKDISPLACEMENT;	// down
#else
#			error Unsupported Machine Architecure

			/* ---
			If the stack grew up this would be
			--- */
			aContext[0] = ((size_t)pStack);				// up
#endif
			___pNewThread = this;
			StackContextSwitch();		/* switch context to new thread */
			}
		else
			{
			/* --- this is the main thread --- */
			BeginThread();	
			};
		return true;
		};

	virtual ~UserThread()
		{
#if DEBUG>=20
		CERR << "User Thread destructor: " << (void *)this << endl;
#endif
		if(  !pStack )
			{
			/* --- verify this is the running thread, because this destructor
			must have been invoked from the thread cleanup routine
			--- */
			PIMUSTBETRUE( ___pTheCurrentThread == this );
			return;
			};
		if ( !bIsTerminated )
			{ InternalTerminate( (unsigned long)-1 ); };
		WaitForThread( this );
#if !defined(CONFIG_OS_WIN16)
		bool bRet = Platform::FreeMemory( pStack );
		assert( bRet );
#endif
		};

	virtual bool Suspend()
		{
		if ( bSuspended )
			{ return true; };
		bSuspended = true;
	
		/* --- if some this is not the current thread just mark it --- */
		if ( this != ___pTheCurrentThread )
			{ return true; };

		/* --- this is the current thread, yield into suspension --- */
		int iRet = PutToSleep();
		if ( iRet )
			{ PIERROR(iRet); return false; }; 
		return true;
		};

	virtual bool Resume()
		{
		if ( !bSuspended )
			{ return true; };
		assert( this != ___pTheCurrentThread );	/* 'coz that would be wierd */
		MakeRunnable();
		return true;
		};

	virtual int GetPriority()
		{ return iPriority; };

	virtual bool SetPriority( int iThePriority );

	virtual bool SetData( int iKey, void *pData )
		{
		if ( iKey<0 || iKey>=PI_MAXTHREADKEYS || 
			!aUsedKeys[ iKey ] )
			{ PIERROR( PIAPI_EINVAL ); return false; };
		aKeys[iKey] = pData;
		return true;
		};

	virtual bool GetData( int iKey, void **ppData )
		{
		if ( iKey<0 || iKey>=PI_MAXTHREADKEYS ||
			!aUsedKeys[ iKey ] || !ppData )
			{ PIERROR( PIAPI_EINVAL ); return false; };
		*ppData = aKeys[iKey];
		return true;
		};
	
	virtual bool Terminate( unsigned long ulTheStatus )
		{
		if ( bIsTerminated )
			{ PIERROR( PIAPI_EINVAL ); return false; };
		return InternalTerminate( ulTheStatus );
		};

	virtual void *GetSystemHandle()
		{ return (void *)iThreadId; };

	/* --- new functions --- */
	inline size_t *GetContext()		{ return aContext; };
	inline bool IsRunnable()
		{ return !pSemaphore && !bSuspended && !pThread && !pPoll; };

	/* --- utility member functions --- */
	void StackUnwind()
		{
#if defined(CONFIG_CPP_EXCEPTIONS)
		throw PI_NEW( StackUnwindException() );
#else
		longjmp( tJmpBuf, 73 );
#endif
		};

	void BeginThread()
		{
#if defined(CONFIG_CPP_EXCEPTIONS)	
		try {
			/* ---
			This StackContextSwitch() is not just important for
			assuming correct priority, its also important to let
			the thread adopt the behaviour defined by its run
			state.
			--- */
			StackContextSwitch();	/* now assume correct priority */
			ulStatus = ( fnEntry )( ulData );
			Cleanup();
			}
		catch( StackUnwindException *pE )
			{
			PI_DELETE( pE );
			Cleanup();
			}
		catch(...)
			{
			Cleanup();
			};
#else
		if ( setjmp( tJmpBuf )==0 )
			{
			StackContextSwitch();	/* now assume correct priority */
#if DEBUG>=20
			DbgWrite( CERR );
			CERR << endl;
#endif
			ulStatus = ( fnEntry )( ulData );
#if DEBUG>=20
			DbgWrite( CERR );
			CERR << endl;
#endif
			};
		Cleanup();
#endif
		};

	int WaitForThread( UserThread *pTheThread )
		{
		if ( !pTheThread->bIsTerminated )
			{ return PutToSleep( pTheThread ); };
		return 0;
		};

	inline bool IsSuspended()		{ return bSuspended; };
	
	void DbgWrite( ostream &os )
		{
		os.width( 4 );
		os << iThreadId << ":" << iPriority << " ";
		os.width( 10 );
#if defined(CONFIG_OS_WIN16)
		os << (void *)this << " SP: ";
		os.width( 12 );
		os << (void *)aContext[0];
		os << " BP: ";
		os.width( 12 );
		os << (void *)aContext[2];
#else
		os << (void *)this << " STACK: ";
		os.width( 12 );
		os << (void *)aContext[0];
#endif
		os << " T(" << tWaiting.Size() << ")\t";
		if ( bIsTerminated )
			{ os << "DEAD"; }
		else if ( IsRunnable() )
			{ os << "CAN RUN"; }
		else
			{
			if ( pSemaphore )
				{ os << "BLOCKED S(" << (void *)pSemaphore << ")"; }
			else if ( pThread )
				{ os << "BLOCKED T(" << (void *)pThread << ")"; }
			else if ( pPoll )
				{ os << "BLOCKED P(" << (void *)pPoll << ")"; }
			else if ( bSuspended )
				{ os << "SUSPENDED"; }
			else
				{ os << "** UNKNOWN **"; };
			};
		};			

	/* --- friends --- */
	friend class UserLocalSemaphore;
	friend class ThreadScheduler;
	friend class PollInfo;
	friend class Poller;
};

/*___________________________________________________________________________*\
 *
 Function:
 Synopsis:
 Description:
\*___________________________________________________________________________*/
void ThreadScheduler::AddThread( UserThread *pThread )
{
	assert( pThread );
	assert( pThread->iPriority <= PITHREAD_PRIORITY_HIGHEST );
	assert( pThread->iPriority < PITHREAD_PRIORITY_SIZE );
	lThreads[pThread->iPriority].Append( (DblList::type)pThread );	
	iNumThreads++;
}

/*___________________________________________________________________________*\
 *
 Function:
 Synopsis:
 Description:
\*___________________________________________________________________________*/
UserThread *ThreadScheduler::SelectNextThread()
{
	for( int i=PITHREAD_PRIORITY_SIZE-1; i>=0; i--)
		{
		DblList &tList = lThreads[i];
		for( DblListIterator j( tList ); !j.BadIndex(); j++)
			{
			UserThread *pThread = (UserThread *)j.Current();
			assert( pThread );
			tList.Detach( j );
			iNumThreads--;
			return pThread;
			};
		};
	return 0;
}

/*___________________________________________________________________________*\
 *
 Function:
 Synopsis:
 Description:
\*___________________________________________________________________________*/
UserThread *ThreadScheduler::SelectNextRunnableThread( int iMandatory )
{
	/* ---
	Get the lowest priority thread to run. If this is not a mandatory
	switch don't select a thread with lower priority that the current
	thread
	--- */
	int iLowestPriority = iMandatory ? 0 : ___pTheCurrentThread->GetPriority();
	for( int i=PITHREAD_PRIORITY_SIZE-1; i>=iLowestPriority; i--)
		{
		DblList &tList = lThreads[i];
		for( DblListIterator j( tList ); !j.BadIndex(); j++)
			{
			UserThread *pThread = (UserThread *)j.Current();
			assert( pThread );
			if ( pThread->IsRunnable() )
				{
				tList.Detach( j );
				iNumThreads--;
				return pThread;
				};
			};
		};

	if ( !iMandatory )
		{
		/* ---
		It isn't mandatory to find another thread, return 0 to indicate
		that the current thread would not be scheduled out.
		--- */
		return 0;
		};

	/* --- OK debug time, the thread scheduling has deadlocked --- */
#	if DEBUG>=20
		CERR << " ** DEADLOCK **" << endl;
#	endif
#	if DEBUG>=20
		DbgWriteAllThreads( CERR );
#	endif
	
	/* ---
	Force the last running thread (___pTheCurrentThread still points
	to it) to run. Do this by aborting its wait state. The blocking function	
	will return back to the callee with a 'DEADLOCK' error code.
	--- */
	PIMUSTBETRUE(___pTheCurrentThread);
	PIMUSTBETRUE(RemoveThread(___pTheCurrentThread));
	___pTheCurrentThread->AbortBlocks( PIAPI_DEADLOCK );
	return ___pTheCurrentThread;
}

/*___________________________________________________________________________*\
 *
 Function:
 Synopsis:
 Description:
\*___________________________________________________________________________*/
bool ThreadScheduler::ChangeThreadPriority(
	UserThread *pThread, int iOld, int iNew )
{
	assert( pThread != ___pTheCurrentThread );
	assert(	iOld <= PITHREAD_PRIORITY_HIGHEST &&
		iOld < PITHREAD_PRIORITY_SIZE &&
		iNew <= PITHREAD_PRIORITY_HIGHEST &&
		iNew < PITHREAD_PRIORITY_SIZE );

	/* --- remove thread from old priority list --- */
	for( DblListIterator i( lThreads[iOld] ); !i.BadIndex(); i++)
		{
		if ( i.Current() == pThread )
			{ lThreads[iOld].Detach( i ); break; };
		};
	/* ---
	If the thread has been promoted then place it as the next available
	thread to run in its new priority.
	If the thread has been demoted then put it at the end of the run list
	in its new priority.
	--- */
	if ( iNew > iOld )
		{ lThreads[iNew].PushBack( (DblList::type)pThread ); }
	else
		{ lThreads[iNew].Append( (DblList::type)pThread ); }
	return true;
}

/*___________________________________________________________________________*\
 *
 Function:
 Synopsis:
 Description:
\*___________________________________________________________________________*/
void ThreadScheduler::DbgWrite( ostream &os )
{
	for( int i=0; i<PITHREAD_PRIORITY_SIZE; i++ )
		{
		for( DblListIterator j( lThreads[i] ); !j.BadIndex(); j++)
			{
			UserThread *pThread = (UserThread *)j.Current();
			assert( pThread );
			os << Platform::GetProcess() << "\t";
			os << "S ";
			pThread->DbgWrite( os );
			os << endl;
			};
		};
}

/*___________________________________________________________________________*\
 *
 Function:
 Synopsis:
 Description:
\*___________________________________________________________________________*/
void DbgWriteAllThreads( ostream &os )
{
	os << Platform::GetProcess() << "\t";
	os << "R ";
	___pTheCurrentThread->DbgWrite( os );	
	os << endl;
	___pLatentThreads->DbgWrite( os );
}

/*___________________________________________________________________________*\
 *
 Class:
 Description:
\*___________________________________________________________________________*/
class UserLocalSemaphore : public Semaphore
{
private:
	bool bError;
	int iCurrentCount;
	int iMaxCount;
	ThreadScheduler tWaiting; /* threads which are waiting on this semaphore */

	/* ---
	Queue the current thread on this semaphore, returns 0 on OK.
	--- */
	int InternalSleepThread()
		{
		UserThread *pThread = ___pTheCurrentThread; 
		tWaiting.AddThread( pThread );
#if DEBUG>=20
		CERR << "Sync: " << (void *)this << " putting thread to sleep: ";
		pThread->DbgWrite( CERR );
		CERR << endl;
#endif
		return pThread->PutToSleep( this );
		};

	/* ---
	Free the next thread waiting on this semaphore.
	--- */
	void InternalWakeUpThread()
		{
		/* ---
		this doesn't necessarily wake up the thread, it grants it a
		semaphore lock and marks it runnable
		--- */
		PIMUSTBETRUE( tWaiting.Size() );
		UserThread *pThread = tWaiting.SelectNextThread();
		assert( !pThread->bIsTerminated );
#if DEBUG>=20
		CERR << "Sync: " << (void *)this << " waking up thread: ";
		pThread->DbgWrite( CERR );
		CERR << endl;
#endif
		pThread->MakeRunnable( this );
		};

	/* ---
	notification to this semaphore that a waiting thread is no longer
	waiting
	--- */
	void GaveUpWaiting( UserThread *pTheThread )
		{
#if DEBUG>=20
		CERR << "Sync: " << (void *)this << " waiting thread is exiting: ";
		pTheThread->DbgWrite( CERR );
		CERR << endl;
#endif
		if ( tWaiting.RemoveThread( pTheThread ) )
			{ return; };
#if DEBUG>=20
		CERR << "Sync: no record of waiting thread (" << pTheThread <<
			")" << endl;
		CERR << "Sync: " << tWaiting.Size() << " waiting threads " << endl;
#endif
		assert( 0 ); 			/* why did that thread notify us? */
		};

	/* --- forbid copy constructor --- */
	UserLocalSemaphore( const UserLocalSemaphore & )
	:	bError( true ),
		iCurrentCount( 0 ),
		iMaxCount( 0 )
		{ assert( 0 ); };

public:
	UserLocalSemaphore( int iTheInitialCount, int iTheMaxCount )
	:	bError( true ),
		iCurrentCount( iTheInitialCount ),
		iMaxCount( iTheMaxCount )
		{
		if (	( iTheInitialCount <= iTheMaxCount ) &&
				( iTheInitialCount >= 0 ) &&
				( iTheMaxCount >= 0 ) )
			{ bError = false; };
		if ( bError )
			{ PIERROR( PIAPI_EINVAL ); };
		};

	virtual ~UserLocalSemaphore()
		{
		assert( !tWaiting.Size() );		/* no threads should be waiting */
		while( tWaiting.Size() )
			{ InternalWakeUpThread(); };
		};

	virtual int Lock()
		{
#if DEBUG>=25
		CERR << "Locking, threads:- (iCurrentCount, tWaiting.Size()) " 
			<< iCurrentCount << ", " << tWaiting.Size() << endl;
		DbgWriteAllThreads( CERR );
#endif
		if ( !iCurrentCount )
			{
			/* --- make current thread wait --- */
			int iRet = InternalSleepThread();
			if ( iRet )
				{
				/* --- thread couldn't wait, maybe deadlock? --- */
				PIERROR(iRet); return -1;
				};
			}
		else
			{
			iCurrentCount--;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -