int32_t iolayer_shutdowns( iolayer_t self, sid_t * ids, uint32_t count ) { uint8_t i = 0; int32_t rc = 0; struct iolayer * layer = (struct iolayer *)self; for ( i = 0; i < layer->nthreads; ++i ) { struct sidlist * list = sidlist_create( count ); if ( list == NULL ) { continue; } sidlist_adds( list, ids, count ); // 参照iolayer_shutdown() // 跨线程提交批量终止任务 int32_t result = iothreads_post( layer->group, i, eIOTaskType_Shutdowns, list, 0 ); if ( unlikely(result != 0) ) { sidlist_destroy( list ); continue; } rc += count; } return rc; }
int32_t iolayer_shutdown( iolayer_t self, sid_t id ) { uint8_t index = SID_INDEX(id); struct iolayer * layer = (struct iolayer *)self; if ( index >= layer->nthreads ) { syslog(LOG_WARNING, "%s(SID=%ld) failed, the Session's index[%u] is invalid .", __FUNCTION__, id, index ); return -1; } // 避免在回调函数中直接终止会话 // 这样会引发后续对会话的操作都非法了 #if 0 if ( pthread_self() == iothreads_get_id( layer->group, index ) ) { // 本线程内直接终止 return _shutdown_direct( _get_manager(layer, index), &task ); } #endif // 跨线程提交终止任务 return iothreads_post( layer->group, index, eIOTaskType_Shutdown, (void *)&id, sizeof(id) ); }
int32_t iolayer_assign_session( struct iolayer * self, uint8_t index, struct task_assign * task ) { evsets_t sets = iothreads_get_sets( self->group, index ); pthread_t threadid = iothreads_get_id( self->group, index ); if ( pthread_self() == threadid ) { return _assign_direct( self, index, sets, task ); } // 跨线程提交发送任务 return iothreads_post( self->group, index, eIOTaskType_Assign, task, sizeof(struct task_assign) ); }
int32_t _send_buffer( struct iolayer * self, sid_t id, const char * buf, uint32_t nbytes, int32_t isfree ) { int32_t result = 0; uint8_t index = SID_INDEX(id); if ( unlikely(index >= self->nthreads) ) { syslog(LOG_WARNING, "%s(SID=%ld) failed, the Session's index[%u] is invalid .", __FUNCTION__, id, index ); return -1; } struct task_send task; task.id = id; task.nbytes = nbytes; task.isfree = isfree; task.buf = (char *)buf; if ( pthread_self() == iothreads_get_id( self->group, index ) ) { return _send_direct( self, _get_manager(self, index), &task ); } // 跨线程提交发送任务 if ( isfree == 0 ) { task.buf = (char *)malloc( nbytes ); if ( unlikely( task.buf == NULL ) ) { syslog(LOG_WARNING, "%s(SID=%ld) failed, can't allocate the memory for '_buf' .", __FUNCTION__, id ); return -2; } task.isfree = 1; memcpy( task.buf, buf, nbytes ); } result = iothreads_post( self->group, index, eIOTaskType_Send, (void *)&task, sizeof(task) ); if ( unlikely( result != 0 ) ) { free( task.buf ); } return result; }
// 服务器开启 // host - 绑定的地址 // port - 监听的端口号 // cb - 新会话创建成功后的回调,会被多个网络线程调用 // 参数1: 上下文参数; // 参数2: 网络线程本地数据(线程安全) // 参数3: 新会话ID; // 参数4: 会话的IP地址; // 参数5: 会话的端口号 // context - 上下文参数 int32_t iolayer_listen( iolayer_t self, const char * host, uint16_t port, int32_t (*cb)( void *, void *, sid_t, const char * , uint16_t ), void * context ) { struct iolayer * layer = (struct iolayer *)self; struct acceptor * acceptor = calloc( 1, sizeof(struct acceptor) ); if ( acceptor == NULL ) { syslog(LOG_WARNING, "%s(host:'%s', port:%d) failed, Out-Of-Memory .", __FUNCTION__, host, port); return -1; } acceptor->event = event_create(); if ( acceptor->event == NULL ) { syslog(LOG_WARNING, "%s(host:'%s', port:%d) failed, can't create AcceptEvent.", __FUNCTION__, host, port); return -2; } acceptor->fd = tcp_listen( (char *)host, port, iolayer_server_option ); if ( acceptor->fd <= 0 ) { syslog(LOG_WARNING, "%s(host:'%s', port:%d) failed, tcp_listen() failure .", __FUNCTION__, host, port); return -3; } acceptor->cb = cb; acceptor->context = context; acceptor->parent = self; acceptor->port = port; acceptor->host[0] = 0; if ( host != NULL ) { strncpy( acceptor->host, host, INET_ADDRSTRLEN ); } iothreads_post( layer->group, (acceptor->fd%layer->nthreads), eIOTaskType_Listen, acceptor, 0 ); return 0; }
int32_t iolayer_broadcast( iolayer_t self, sid_t * ids, uint32_t count, const char * buf, uint32_t nbytes ) { uint8_t i = 0; int32_t rc = 0; pthread_t threadid = pthread_self(); struct iolayer * layer = (struct iolayer *)self; for ( i = 0; i < layer->nthreads; ++i ) { struct message * msg = message_create(); if ( unlikely(msg == NULL) ) { continue; } message_add_receivers( msg, ids, count ); message_add_buffer( msg, (char *)buf, nbytes ); if ( threadid == iothreads_get_id( layer->group, i ) ) { // 本线程内直接广播 _broadcast_direct( layer, i, _get_manager(layer, i), msg ); } else { // 跨线程提交广播任务 int32_t result = iothreads_post( layer->group, i, eIOTaskType_Broadcast, msg, 0 ); if ( unlikely(result != 0) ) { message_destroy( msg ); continue; } } rc += count; } return rc; }
// 客户端开启 // host - 远程服务器的地址 // port - 远程服务器的端口 // seconds - 连接超时时间 // cb - 连接结果的回调 // 参数1: 上下文参数 // 参数2: 网络线程本地数据(线程安全) // 参数3: 连接结果 // 参数4: 连接的远程服务器的地址 // 参数5: 连接的远程服务器的端口 // 参数6: 连接成功后返回的会话ID // context - 上下文参数 int32_t iolayer_connect( iolayer_t self, const char * host, uint16_t port, int32_t seconds, int32_t (*cb)( void *, void *, int32_t, const char *, uint16_t , sid_t), void * context ) { struct iolayer * layer = (struct iolayer *)self; struct connector * connector = calloc( 1, sizeof(struct connector) ); if ( connector == NULL ) { syslog(LOG_WARNING, "%s(host:'%s', port:%d) failed, Out-Of-Memory .", __FUNCTION__, host, port); return -1; } connector->event = event_create(); if ( connector->event == NULL ) { syslog(LOG_WARNING, "%s(host:'%s', port:%d) failed, can't create ConnectEvent.", __FUNCTION__, host, port); return -2; } connector->fd = tcp_connect( (char *)host, port, iolayer_client_option ); if ( connector->fd <= 0 ) { syslog(LOG_WARNING, "%s(host:'%s', port:%d) failed, tcp_connect() failure .", __FUNCTION__, host, port); return -3; } connector->cb = cb; connector->context = context; connector->mseconds = seconds*1000; connector->parent = self; connector->port = port; strncpy( connector->host, host, INET_ADDRSTRLEN ); iothreads_post( layer->group, (connector->fd%layer->nthreads), eIOTaskType_Connect, connector, 0 ); return 0; }
int32_t main() { uint64_t index = 0; uint8_t i = 0; uint8_t nthreads = 4; iothreads_t threadgroup; uint64_t start_time = 0, end_time = 0; struct iothread_args * args = NULL; srand( (int32_t)time(NULL) ); signal( SIGINT, signal_handler ); // threadgroup = iothreads_start( nthreads, 0, task_method, NULL ); if ( threadgroup == NULL ) { printf("iothreads_start() failed \n"); return -1; } args = (struct iothread_args *)calloc( nthreads, sizeof(struct iothread_args) ); if ( args == NULL ) { printf("calloc for 'iothread_args' failed \n"); return -2; } // runflags = 1; // start_time = milliseconds(); while ( runflags ) { uint8_t _index = index&(nthreads-1); struct iothread_args * _args = args + _index; iothreads_post( threadgroup, _index, 0, _args, 0 ); ++index; } end_time = milliseconds(); // iothreads_stop( threadgroup ); // for ( i = 0; i < nthreads; ++i ) { struct iothread_args * _args = args + i; float rate = (float)(_args->taskcount)*1000.0f/(float)(end_time-start_time); printf("iothread[%d] process tasks: %ld, rate: %6.3f\n", i, _args->taskcount, rate ); } printf("dispatch tasks: %ld, rate: %6.3f\n", index, (float)(index)*1000.0f/(float)(end_time-start_time) ); return 0; }