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

📄 usersync.cpp

📁 mini http server,可以集成嵌入到程序中,实现简单的web功能
💻 CPP
📖 第 1 页 / 共 5 页
字号:
 Function:
 Synopsis:	  static, public:
 Description:
\*___________________________________________________________________________*/
Thread *Platform::GetMainThread()
{
	return ___pTheMainThread;
}

/*___________________________________________________________________________*\
 *
 Function:
 Synopsis:	  static, public:
 Description:
\*___________________________________________________________________________*/
int Platform::AllocThreadKey()
{
	for( int i=0; i<PI_MAXTHREADKEYS; i++ )
		{
		if ( !aUsedKeys[i] )
			{
			aUsedKeys[i] = 1;
			return i;
			};
		};
	PIERROR( PIAPI_EXHAUSTED );
	return -1;
}

/*___________________________________________________________________________*\
 *
 Function:
 Synopsis:	  static, public:
 Description:
\*___________________________________________________________________________*/
bool Platform::DeleteThreadKey( int iKey )
{
	if ( iKey<0 || iKey>=PI_MAXTHREADKEYS || !aUsedKeys[iKey] )
		{
		PIERROR( PIAPI_EINVAL );
		return false;
		};
	aUsedKeys[iKey] = 0;
	return true;
}

/*___________________________________________________________________________*\
 *
 Function:
 Synopsis:	  static, public:
 Description:
\*___________________________________________________________________________*/
void Platform::ThreadDbgDump( ostream &os )
{
	DbgWriteAllThreads( os );
}

/*___________________________________________________________________________*\
 *
 Function:
 Synopsis:	  static, public:
 Description:
\*___________________________________________________________________________*/
int Platform::PollFD( int iFD, int iFlags, int iTimeout )
{
#if defined(CONFIG_OS_POSIX)
#	if defined(CONFIG_OS_SOLARIS)
		/*
		** Solaris 2.x: man -s 3C select
		**	
		** [File descriptors associated with regular files always select
		** true  for  ready  to  read, ready to write, and error conditions.]
		**
		** NOTE:
		**		- What about pipes?
		**		- Also change other instances of this function
		*/
		/* so just return the requested status */
		return iFlags;
#	endif
	return Platform::PollNetFD( iFD, iFlags, iTimeout );
#elif defined(CONFIG_OS_WIN32)
	/* ---
	Win32 SDK, says that WaitForSingleObject() can be used to
	check if a file handle operation will succeed without blocking
	'under certain circumstances' and is 'discouraged'. But there doesn't
	seem to be another way to do this without side effects.
	NOTE: The reason this is discouraged is because confusion can arise if
	multiple waits exists for the the same handle, therefore its
	suggested to use an event. Anyway.....
	--- */
	int iRetFlags = 0;
	switch( ::WaitForSingleObject( (HANDLE)iFD, iTimeout*1000 ) )
		{
		case WAIT_FAILED:
			PIOSERR;
			return -1;

		default:;
			/* ---
			Don't know what made the handle signalled so set the
			return code based on what the callee requested. Files
			are unidirectional anyway so this doesn't cause confusion
			like it would with sockets
			--- */
			if ( iFlags & Platform::POLL_READ )
				{ iRetFlags = iRetFlags | Platform::POLL_READ; };
			if ( iFlags & Platform::POLL_WRITE )
				{ iRetFlags = iRetFlags | Platform::POLL_WRITE; };
			return iRetFlags;
		};
#else
		/*
		** Return ready without yielding
		*/
		(void)iFD;
		(void)iTimeout;
		return iFlags;
#endif
}

/*___________________________________________________________________________*\
 *
 Function:
 Synopsis:	  static, public:
 Description:
\*___________________________________________________________________________*/
int Platform::PollPipeFD( int iFD, int iFlags, int iTimeout )
{
#if defined(CONFIG_OS_WIN32)
	int iRetFlags = 0;

	if ( iFlags & ~Platform::POLL_WRITE )
		{
		int iRet = Platform::PollFD( iFD, iFlags & ~Platform::POLL_WRITE,
			iTimeout );

		if ( iRet<0 )
			{ return iRet; };

		iRetFlags |= iRet;
		};

	/* ---
	Named pipes on Win32. Always return 'Ready to Write'.
	--- */
	if ( iFlags & Platform::POLL_WRITE )
		{ iRetFlags |= Platform::POLL_WRITE; };

	return iRetFlags;
#endif
	/*
	** Otherwise behaviour is the same as Platform::PollFD
	*/
	return Platform::PollFD( iFD, iFlags, iTimeout );	
}

/*___________________________________________________________________________*\
 *
 Function:
 Synopsis:	  static, public:
 Description:
\*___________________________________________________________________________*/
int Platform::PollNetFD( int iFD, int iFlags, int iTimeout )
{
	if ( iFD<0 )
		{
		PIERROR( PIAPI_EINVAL );
		return -1;
		};
	int iRet = PollInfo::Poll( ___pTheCurrentThread, iFD, iFlags,
		(iTimeout==-1) ? -1 : (iTimeout * 1000) );
	if ( iRet<=0 )
		{ PIERROR(iRet); };
	return iRet;
}

/*___________________________________________________________________________*\
 *
 Function:
 Synopsis:	  static, public:
 Description:
\*___________________________________________________________________________*/
int Platform::Sleep( int iMilliseconds )
{
	if ( iMilliseconds<0 )
		{
		PIERROR( PIAPI_EINVAL );
		return -1;
		};
	int iRet = PollInfo::Poll( ___pTheCurrentThread, -1, 0, iMilliseconds );
	if ( iRet!=0 )
		{ PIERROR(iRet); };
	return iRet;
}

/*___________________________________________________________________________*\
 *
 Function:
 Synopsis:	  static, public:
 Description:
\*___________________________________________________________________________*/
void Platform::CatchExceptions( void (* fn)( void *), void *pArg )
{
	/* ---
	It is an internal error for this function to be used on 
	threads other than the main thread
	--- */
	assert( ___pTheCurrentThread==___pTheMainThread );
	assert( fn );
#if defined(CONFIG_CPP_EXCEPTIONS)
	try	{
		(fn)( pArg );
		}
	catch( UserThread::StackUnwindException *pE )
		{
		PI_DELETE( pE );
		}
	catch( ... )
		{
		};
#else
	if ( setjmp( ___pTheMainThread->tJmpBuf )==0 )
		{ (fn)( pArg ); };
#endif
}

/*___________________________________________________________________________*\
 *
 Function:
 Synopsis:		static, public:
 Description:
\*___________________________________________________________________________*/
int Platform::Read( int iFd, int iLength, void *pData )
{
	assert( iFd!=-1 && iLength && pData );
	if ( iFd==-1 || !iLength || !pData )
		{
		PIERROR( PIAPI_EINVAL );
		return -1;
		};
	int iToRead = iLength;
	int iRead;
	for(; iToRead ;)
		{
		iRead = -1;
		/* --- yield if necessary --- */
		if ( Platform::PollFD( iFd, POLL_READ, -1 )<=0 )
			{ break; };
#if defined(CONFIG_OS_POSIX)
		iRead = ::read( iFd, pData, iLength );
		if ( iRead==-1 && errno==EINTR )
			{ continue; };

#elif defined(CONFIG_OS_WIN32)
		/* --- 
		the cast from int * to DWORD * (DWORD is currrently unsigned long), is
		not	so bad because iLength is the maximum size that can be sent and 
		is also an int
		--- */
		if ( !::ReadFile( (HANDLE)iFd, pData, iLength, (DWORD *)&iRead,
			0 ) )
			{ iRead=-1; };

#endif
		if ( !iRead || iRead==-1 )
			{ break; };
		iToRead -= iRead;
		};

	if ( iRead==-1 )
		{
		PIOSERR;
		return PIAPI_ERROR;
		};
	return PIAPI_COMPLETED;
}

/*___________________________________________________________________________*\
 *
 Function:
 Synopsis:		static, public:
 Description:
\*___________________________________________________________________________*/
int Platform::Write( int iFd, int iLength, const void *pData )
{
	assert( iFd!=-1 && iLength && pData );
	if ( iFd==-1 || !iLength || !pData )
		{
		PIERROR( PIAPI_EINVAL );
		return -1;
		};
	int iToWrite = iLength;
	int iWritten;
	for(; iToWrite ;)
		{
		iWritten = -1;
		/* --- yield if necessary --- */
		if ( Platform::PollFD( iFd, POLL_WRITE, -1 )<=0 )
			{ break; };
#if defined(CONFIG_OS_POSIX)
		iWritten = ::write( iFd, pData, iLength );
		if ( iWritten==-1 && errno==EINTR )
			{ continue; };

#elif defined(CONFIG_OS_WIN32)
		/* --- 
		the cast from int * to DWORD * (DWORD is currrently unsigned long), is
		not	so bad because iLength is the maximum size that can be sent and 
		is also an int
		--- */
		if ( !::WriteFile( (HANDLE)iFd, pData, iLength, (DWORD *)&iWritten,
			0 ) )
			{ iWritten=-1; };

#endif
		if ( !iWritten || iWritten==-1 )
			{ break; };
		iToWrite -= iWritten;
		};

	if ( iWritten==-1 )
		{
		PIOSERR;
		return PIAPI_ERROR;
		};
	return PIAPI_COMPLETED;
}

/*___________________________________________________________________________*\
 *
 Function:
 Synopsis:		static, public:
 Description:
\*___________________________________________________________________________*/
int Platform::WriteAtomic( int iFd, int iLength, const void *pData )
{
	assert( iFd!=-1 && iLength && pData );
	if ( iFd==-1 || !iLength || !pData )
		{
		PIERROR( PIAPI_EINVAL );
		return -1;
		};
	int iToWrite = iLength;
	int iWritten;

	/* --- yield until write is writtable --- */
	if ( Platform::PollFD( iFd, POLL_WRITE, -1 )<=0 )
		{ assert( 0 ); return PIAPI_ERROR; };

	if ( Platform::LockFd( iFd )!=PIAPI_COMPLETED )
		{	
		return PIAPI_ERROR;
		};

	for(; iToWrite ;)
		{
		iWritten = -1;

#if defined(CONFIG_OS_POSIX)
		iWritten = ::write( iFd, pData, iLength );
		if ( iWritten==-1 && errno==EINTR )
			{ continue; };

#elif defined(CONFIG_OS_WIN32)
		/* --- 
		the cast from int * to DWORD * (DWORD is currrently unsigned long), is
		not	so bad because iLength is the maximum size that can be sent and 
		is also an int
		--- */
		if ( !::WriteFile( (HANDLE)iFd, pData, iLength, (DWORD *)&iWritten,
			0 ) )
			{ iWritten=-1; };

#endif
		if ( !iWritten || iWritten==-1 )
			{ break; };
		iToWrite -= iWritten;
		};

	iWritten = Platform::UnlockFd( iFd );
	if ( iWritten!=PIAPI_COMPLETED )
		{
		PIOSERR;
		return PIAPI_ERROR;
		};

	return PIAPI_COMPLETED;
}

/*___________________________________________________________________________*\
 *
 Function:
 Synopsis:	  static, public:
 Description:
\*___________________________________________________________________________*/
int Platform::WaitForProcess( int tProcess, int iFlags, int /* iTimeout */ )
{
	(void)iFlags;	/* not used */
#if defined(CONFIG_OS_POSIX)
	for(;;)
		{
		int iRet = ::waitpid( tProcess, 0, WNOHANG );
#if !defined(CONFIG_NO_ERESTART)
		if ( iRet==-1 && errno!=EINTR && errno!=ERESTART )
#else
		if ( iRet==-1 && errno!=EINTR )
#endif
			{
			PIOSERR;
			return PIAPI_ERROR;
			};

		if ( iRet==tProcess )
			{ return PIAPI_COMPLETED; };

		/* --- yield and try again --- */
		Platform::YieldThread();
		};

#elif defined(CONFIG_OS_WIN32)
	for(;;)
		{
		DWORD dwWait=::WaitForSingleObject( (HANDLE)tProcess, 0 /* no wait */ );
		switch( dwWait )
			{
			case WAIT_TIMEOUT:
				/* --- yield and try again --- */
				Platform::YieldThread();	// or yield timeslice
				break;

			case WAIT_OBJECT_0:
				return PIAPI_COMPLETED;

			case WAIT_FAILED:
				PIOSERR;
				return PIAPI_ERROR;

			default:
				/* how did we get here */
				assert( 0 );
				PIERROR( PIAPI_ERROR );
				return PIAPI_ERROR;
			};
		};
#endif
	(void)tProcess;
	return PIAPI_NOTSUPPORTED;
}

/*___________________________________________________________________________*\
 *
 Function:
 Synopsis:		static, public:
 Description:
\*___________________________________________________________________________*/
#if defined(CONFIG_LOCK_FLOCK)
#	define PI_LOCK_BLOCK		(LOCK_EX)
#	define PI_LOCK_NOBLOCK		(LOCK_EX | LOCK_NB)
#else
#	define PI_LOCK_BLOCK		(F_LOCK)
#	define PI_LOCK_NOBLOCK		(F_TLOCK)
#endif
int Platform::LockFd( int iFd )
{
	assert( iFd!=-1 );
	if ( iFd==-1 )
		{
		PIERROR( PIAPI_EINVAL );
		return -1;
		};

#if defined(CONFIG_OS_POSIX)
	/* ---
	Enter loop to obtain a lock on the file
	--- */
	int iFlags = PI_LOCK_NOBLOCK;
	for(;;)
		{
		/* --- non-blocking call to flock --- */
#if defined(CONFIG_LOCK_FLOCK)
		if ( ::flock( iFd, iFlags )==0 )
#else
		if ( ::lockf( iFd, iFlags, 0 )==0 )
#endif
			{
			/* --- got the lock, continue --- */
			break;
			}
		else if ( errno==EWOULDBLOCK || errno==EAGAIN )
			{
			/* ---
			Another process has the lock, try to yield the thread. 
			If th

⌨️ 快捷键说明

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