mirror of
				https://github.com/ossrs/srs.git
				synced 2025-03-09 15:49:59 +00:00 
			
		
		
		
	use libco instead of state-thread(st), still have some bug
This commit is contained in:
		
							parent
							
								
									51d6c367f5
								
							
						
					
					
						commit
						7c8a35aea9
					
				
					 88 changed files with 4836 additions and 19273 deletions
				
			
		
							
								
								
									
										318
									
								
								trunk/3rdparty/libco/co_epoll.cpp
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										318
									
								
								trunk/3rdparty/libco/co_epoll.cpp
									
										
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,318 @@
 | 
			
		|||
/*
 | 
			
		||||
* Tencent is pleased to support the open source community by making Libco available.
 | 
			
		||||
 | 
			
		||||
* Copyright (C) 2014 THL A29 Limited, a Tencent company. All rights reserved.
 | 
			
		||||
*
 | 
			
		||||
* Licensed under the Apache License, Version 2.0 (the "License"); 
 | 
			
		||||
* you may not use this file except in compliance with the License. 
 | 
			
		||||
* You may obtain a copy of the License at
 | 
			
		||||
*
 | 
			
		||||
*	http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
*
 | 
			
		||||
* Unless required by applicable law or agreed to in writing, 
 | 
			
		||||
* software distributed under the License is distributed on an "AS IS" BASIS, 
 | 
			
		||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 | 
			
		||||
* See the License for the specific language governing permissions and 
 | 
			
		||||
* limitations under the License.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include "co_epoll.h"
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#if !defined( __APPLE__ ) && !defined( __FreeBSD__ )
 | 
			
		||||
 | 
			
		||||
int	co_epoll_wait( int epfd,struct co_epoll_res *events,int maxevents,int timeout )
 | 
			
		||||
{
 | 
			
		||||
	return epoll_wait( epfd,events->events,maxevents,timeout );
 | 
			
		||||
}
 | 
			
		||||
int	co_epoll_ctl( int epfd,int op,int fd,struct epoll_event * ev )
 | 
			
		||||
{
 | 
			
		||||
	return epoll_ctl( epfd,op,fd,ev );
 | 
			
		||||
}
 | 
			
		||||
int	co_epoll_create( int size )
 | 
			
		||||
{
 | 
			
		||||
	return epoll_create( size );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct co_epoll_res *co_epoll_res_alloc( int n )
 | 
			
		||||
{
 | 
			
		||||
	struct co_epoll_res * ptr = 
 | 
			
		||||
		(struct co_epoll_res *)malloc( sizeof( struct co_epoll_res ) );
 | 
			
		||||
 | 
			
		||||
	ptr->size = n;
 | 
			
		||||
	ptr->events = (struct epoll_event*)calloc( 1,n * sizeof( struct epoll_event ) );
 | 
			
		||||
 | 
			
		||||
	return ptr;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
void co_epoll_res_free( struct co_epoll_res * ptr )
 | 
			
		||||
{
 | 
			
		||||
	if( !ptr ) return;
 | 
			
		||||
	if( ptr->events ) free( ptr->events );
 | 
			
		||||
	free( ptr );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
class clsFdMap // million of fd , 1024 * 1024 
 | 
			
		||||
{
 | 
			
		||||
private:
 | 
			
		||||
	static const int row_size = 1024;
 | 
			
		||||
	static const int col_size = 1024;
 | 
			
		||||
 | 
			
		||||
	void **m_pp[ 1024 ];
 | 
			
		||||
public:
 | 
			
		||||
	clsFdMap()
 | 
			
		||||
	{
 | 
			
		||||
		memset( m_pp,0,sizeof(m_pp) );
 | 
			
		||||
	}
 | 
			
		||||
	~clsFdMap()
 | 
			
		||||
	{
 | 
			
		||||
		for(int i=0;i<sizeof(m_pp)/sizeof(m_pp[0]);i++)
 | 
			
		||||
		{
 | 
			
		||||
			if( m_pp[i] ) 
 | 
			
		||||
			{
 | 
			
		||||
				free( m_pp[i] );
 | 
			
		||||
				m_pp[i] = NULL;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	inline int clear( int fd )
 | 
			
		||||
	{
 | 
			
		||||
		set( fd,NULL );
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
	inline int set( int fd,const void * ptr )
 | 
			
		||||
	{
 | 
			
		||||
		int idx = fd / row_size;
 | 
			
		||||
		if( idx < 0 || idx >= sizeof(m_pp)/sizeof(m_pp[0]) )
 | 
			
		||||
		{
 | 
			
		||||
			assert( __LINE__ == 0 );
 | 
			
		||||
			return -__LINE__;
 | 
			
		||||
		}
 | 
			
		||||
		if( !m_pp[ idx ] ) 
 | 
			
		||||
		{
 | 
			
		||||
			m_pp[ idx ] = (void**)calloc( 1,sizeof(void*) * col_size );
 | 
			
		||||
		}
 | 
			
		||||
		m_pp[ idx ][ fd % col_size ] = (void*)ptr;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
	inline void *get( int fd )
 | 
			
		||||
	{
 | 
			
		||||
		int idx = fd / row_size;
 | 
			
		||||
		if( idx < 0 || idx >= sizeof(m_pp)/sizeof(m_pp[0]) )
 | 
			
		||||
		{
 | 
			
		||||
			return NULL;
 | 
			
		||||
		}
 | 
			
		||||
		void **lp = m_pp[ idx ];
 | 
			
		||||
		if( !lp ) return NULL;
 | 
			
		||||
 | 
			
		||||
		return lp[ fd % col_size ];
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
__thread clsFdMap *s_fd_map = NULL;
 | 
			
		||||
 | 
			
		||||
static inline clsFdMap *get_fd_map()
 | 
			
		||||
{
 | 
			
		||||
	if( !s_fd_map )
 | 
			
		||||
	{
 | 
			
		||||
		s_fd_map = new clsFdMap();
 | 
			
		||||
	}
 | 
			
		||||
	return s_fd_map;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct kevent_pair_t
 | 
			
		||||
{
 | 
			
		||||
	int fire_idx;
 | 
			
		||||
	int events;
 | 
			
		||||
	uint64_t u64;
 | 
			
		||||
};
 | 
			
		||||
int co_epoll_create( int size )
 | 
			
		||||
{
 | 
			
		||||
	return kqueue();
 | 
			
		||||
}
 | 
			
		||||
int co_epoll_wait( int epfd,struct co_epoll_res *events,int maxevents,int timeout )
 | 
			
		||||
{
 | 
			
		||||
	struct timespec t = { 0 };
 | 
			
		||||
	if( timeout > 0 )
 | 
			
		||||
	{
 | 
			
		||||
		t.tv_sec = timeout;
 | 
			
		||||
	}
 | 
			
		||||
	int ret = kevent( epfd, 
 | 
			
		||||
					NULL, 0, //register null
 | 
			
		||||
					events->eventlist, maxevents,//just retrival
 | 
			
		||||
					( -1 == timeout ) ? NULL : &t );
 | 
			
		||||
	int j = 0;
 | 
			
		||||
	for(int i=0;i<ret;i++)
 | 
			
		||||
	{
 | 
			
		||||
		struct kevent &kev = events->eventlist[i];
 | 
			
		||||
		struct kevent_pair_t *ptr = (struct kevent_pair_t*)kev.udata;
 | 
			
		||||
		struct epoll_event *ev = events->events + i;
 | 
			
		||||
		if( 0 == ptr->fire_idx )
 | 
			
		||||
		{
 | 
			
		||||
			ptr->fire_idx = i + 1;
 | 
			
		||||
			memset( ev,0,sizeof(*ev) );
 | 
			
		||||
			++j;
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			ev = events->events + ptr->fire_idx - 1;
 | 
			
		||||
		}
 | 
			
		||||
		if( EVFILT_READ == kev.filter )
 | 
			
		||||
		{
 | 
			
		||||
			ev->events |= EPOLLIN;
 | 
			
		||||
		}
 | 
			
		||||
		else if( EVFILT_WRITE == kev.filter )
 | 
			
		||||
		{
 | 
			
		||||
			ev->events |= EPOLLOUT;
 | 
			
		||||
		}
 | 
			
		||||
		ev->data.u64 = ptr->u64;
 | 
			
		||||
	}
 | 
			
		||||
	for(int i=0;i<ret;i++)
 | 
			
		||||
	{
 | 
			
		||||
		(( struct kevent_pair_t* )(events->eventlist[i].udata) )->fire_idx = 0;
 | 
			
		||||
	}
 | 
			
		||||
	return j;
 | 
			
		||||
}
 | 
			
		||||
int co_epoll_del( int epfd,int fd )
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
	struct timespec t = { 0 };
 | 
			
		||||
	struct kevent_pair_t *ptr = ( struct kevent_pair_t* )get_fd_map()->get( fd );
 | 
			
		||||
	if( !ptr ) return 0;
 | 
			
		||||
	if( EPOLLIN & ptr->events )
 | 
			
		||||
	{
 | 
			
		||||
		struct kevent kev = { 0 };
 | 
			
		||||
		kev.ident = fd;
 | 
			
		||||
		kev.filter = EVFILT_READ;
 | 
			
		||||
		kev.flags = EV_DELETE;
 | 
			
		||||
		kevent( epfd,&kev,1, NULL,0,&t );
 | 
			
		||||
	}
 | 
			
		||||
	if( EPOLLOUT & ptr->events )
 | 
			
		||||
	{
 | 
			
		||||
		struct kevent kev = { 0 };
 | 
			
		||||
		kev.ident = fd;
 | 
			
		||||
		kev.filter = EVFILT_WRITE;
 | 
			
		||||
		kev.flags = EV_DELETE;
 | 
			
		||||
		kevent( epfd,&kev,1, NULL,0,&t );
 | 
			
		||||
	}
 | 
			
		||||
	get_fd_map()->clear( fd );
 | 
			
		||||
	free( ptr );
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
int co_epoll_ctl( int epfd,int op,int fd,struct epoll_event * ev )
 | 
			
		||||
{
 | 
			
		||||
	if( EPOLL_CTL_DEL == op )
 | 
			
		||||
	{
 | 
			
		||||
		return co_epoll_del( epfd,fd );
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	const int flags = ( EPOLLIN | EPOLLOUT | EPOLLERR | EPOLLHUP );
 | 
			
		||||
	if( ev->events & ~flags ) 
 | 
			
		||||
	{
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if( EPOLL_CTL_ADD == op && get_fd_map()->get( fd ) )
 | 
			
		||||
	{
 | 
			
		||||
		errno = EEXIST;
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
	else if( EPOLL_CTL_MOD == op && !get_fd_map()->get( fd ) )
 | 
			
		||||
	{
 | 
			
		||||
		errno = ENOENT;
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	struct kevent_pair_t *ptr = (struct kevent_pair_t*)get_fd_map()->get( fd );
 | 
			
		||||
	if( !ptr )
 | 
			
		||||
	{
 | 
			
		||||
		ptr = (kevent_pair_t*)calloc(1,sizeof(kevent_pair_t));
 | 
			
		||||
		get_fd_map()->set( fd,ptr );
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	int ret = 0;
 | 
			
		||||
	struct timespec t = { 0 };
 | 
			
		||||
 | 
			
		||||
	// printf("ptr->events 0x%X\n",ptr->events);
 | 
			
		||||
 | 
			
		||||
	if( EPOLL_CTL_MOD == op )
 | 
			
		||||
	{
 | 
			
		||||
		//1.delete if exists
 | 
			
		||||
		if( ptr->events & EPOLLIN ) 
 | 
			
		||||
		{
 | 
			
		||||
			struct kevent kev = { 0 };
 | 
			
		||||
			EV_SET( &kev,fd,EVFILT_READ,EV_DELETE,0,0,NULL );
 | 
			
		||||
			kevent( epfd, &kev,1, NULL,0, &t );
 | 
			
		||||
		}	
 | 
			
		||||
		//1.delete if exists
 | 
			
		||||
		if( ptr->events & EPOLLOUT ) 
 | 
			
		||||
		{
 | 
			
		||||
			struct kevent kev = { 0 };
 | 
			
		||||
			EV_SET( &kev,fd,EVFILT_WRITE,EV_DELETE,0,0,NULL );
 | 
			
		||||
			ret = kevent( epfd, &kev,1, NULL,0, &t );
 | 
			
		||||
			// printf("delete write ret %d\n",ret );
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	do
 | 
			
		||||
	{
 | 
			
		||||
		if( ev->events & EPOLLIN )
 | 
			
		||||
		{
 | 
			
		||||
			
 | 
			
		||||
			//2.add
 | 
			
		||||
			struct kevent kev = { 0 };
 | 
			
		||||
			EV_SET( &kev,fd,EVFILT_READ,EV_ADD,0,0,ptr );
 | 
			
		||||
			ret = kevent( epfd, &kev,1, NULL,0, &t );
 | 
			
		||||
			if( ret ) break;
 | 
			
		||||
		}
 | 
			
		||||
		if( ev->events & EPOLLOUT )
 | 
			
		||||
		{
 | 
			
		||||
				//2.add
 | 
			
		||||
			struct kevent kev = { 0 };
 | 
			
		||||
			EV_SET( &kev,fd,EVFILT_WRITE,EV_ADD,0,0,ptr );
 | 
			
		||||
			ret = kevent( epfd, &kev,1, NULL,0, &t );
 | 
			
		||||
			if( ret ) break;
 | 
			
		||||
		}
 | 
			
		||||
	} while( 0 );
 | 
			
		||||
	
 | 
			
		||||
	if( ret )
 | 
			
		||||
	{
 | 
			
		||||
		get_fd_map()->clear( fd );
 | 
			
		||||
		free( ptr );
 | 
			
		||||
		return ret;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ptr->events = ev->events;
 | 
			
		||||
	ptr->u64 = ev->data.u64;
 | 
			
		||||
	 
 | 
			
		||||
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct co_epoll_res *co_epoll_res_alloc( int n )
 | 
			
		||||
{
 | 
			
		||||
	struct co_epoll_res * ptr = 
 | 
			
		||||
		(struct co_epoll_res *)malloc( sizeof( struct co_epoll_res ) );
 | 
			
		||||
 | 
			
		||||
	ptr->size = n;
 | 
			
		||||
	ptr->events = (struct epoll_event*)calloc( 1,n * sizeof( struct epoll_event ) );
 | 
			
		||||
	ptr->eventlist = (struct kevent*)calloc( 1,n * sizeof( struct kevent) );
 | 
			
		||||
 | 
			
		||||
	return ptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void co_epoll_res_free( struct co_epoll_res * ptr )
 | 
			
		||||
{
 | 
			
		||||
	if( !ptr ) return;
 | 
			
		||||
	if( ptr->events ) free( ptr->events );
 | 
			
		||||
	if( ptr->eventlist ) free( ptr->eventlist );
 | 
			
		||||
	free( ptr );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue