static thread_func_t tcp_register_server_thread(void* s) { char buffer[NL_BUFFER_SIZE+1]; server_game* g = (server_game*)s; lock_w(&game_server_array); rAdd(&game_server_array, (void*)g); lock_uw(&game_server_array); LOG("New server added: %s.", g->name); /* Let every client aware of the new server. */ broadcast_new_server(g); /* We do not have anything to share with the server. * So we do a tcp_rcv, and we know that is unlocks only when * the server leaves. */ nl_tcp_rcv(buffer, g->socket); /* Close the server socket */ close(g->socket); /* Let every client aware of the gone server. */ broadcast_delete_server(g); lock_w(&game_server_array); rDelete(&game_server_array, (void*)g, NULL); lock_uw(&game_server_array); delete_game_server((void*)g); LOG("Server thread terminated."); thread_exit(); }
static thread_func_t tcp_register_client_thread(void* s) { char buffer[NL_BUFFER_SIZE+1]; server_game* g; client* c = (client*)s; void* remember = NULL; /* Then, we add the client to the array, such that he will * be informed whenever a new server arrives or leaves. */ lock_w(&client_array); rAdd(&client_array, (void*)c); lock_uw(&client_array); /* We now give him the preliminary information, list all the * servers already present. */ lock_r(&game_server_array); nl_tcp_sndInt(game_server_array.length, c->socket); if((g = (server_game*)rGet(&game_server_array, FIRST, &remember)) != NULL) { do { nl_tcp_snd(g->name, c->socket); /* Send the server's name */ nl_snd_addr(g->addr, c->socket); /* And now it's address. */ } while((g = (server_game*)rGet(&game_server_array, NEXT, &remember)) != NULL); } lock_ur(&game_server_array); /* * Done. We can now communicate. * Actually we do not have much to say to each other. * This is just a little trick to just wait, and then the * client leaves, this will exit. */ nl_tcp_rcv(buffer, c->socket); /* Close the client socket * If it has been closed from extern, don't try to close it again! */ close(c->socket); lock_w(&client_array); rDelete(&client_array, (void*)c, NULL); delete_client((void*)c); lock_uw(&client_array); LOG("Client thread terminated."); thread_exit(); }
Lock::TempRelease::~TempRelease() { if( cant ) return; LockState& ls = lockState(); dassert( ls.recursive == 0 ); DESTRUCTOR_GUARD( fassert(0, ls.threadState == 't' || ls.threadState == 0); ls.threadState = 0; switch( type ) { case 'W': lock_W(); break; case 'R': lock_R(); break; case 'w': if( local ) localDBLock.lock(); else ls.otherLock->lock(); lock_w(); break; case 'r': if( local ) localDBLock.lock_shared(); else ls.otherLock->lock_shared(); lock_r(); break; default: wassert(false); } ) }
static void draw_player(void *ptr, void *unused) { (void)unused; cpShape* shape = (cpShape*)ptr; chipmunk_data* p = (chipmunk_data*)shape->data; //chipmunk_lock_data(p); if(p == NULL || p->del) { /* We test if the player is marked for deletation. * If so, we add it to the array of players ready to be deleted, * which will be purged by another thread to prevent concurrence * problems. */ lock_w(&to_remove_array); lAdd(&to_remove_array, (void*)shape); lock_uw(&to_remove_array); } else { p->px = (mFloat)shape->body->p.x; p->py = (mFloat)shape->body->p.y; p->an = (mFloat)shape->body->a; p->vx = (mFloat)shape->body->v.x; p->vy = (mFloat)shape->body->v.y; p->av = (mFloat)shape->body->w; /*p->ax = (mFloat)shape->body->f.x * shape->body->m_inv; p->ay = (mFloat)shape->body->f.y * shape->body->m_inv; p->aa = (mFloat)shape->body->t;*/ /* Acceleration already defined in physics.c/update_keys */ } //chipmunk_unlock_data(p); }
static void quit(void) { void* remember; client* c; server_game* g; int port = NL_REGISTER_PORT; int web_port = NL_REGISTER_WEB_PORT; if(exit_time) return; write_config(); exit_time = 1; /* We close everyone's socket, such that every thread * closes tighly. */ lock_r(&client_array); if((c = (client*)rGet(&client_array, FIRST, &remember)) != NULL) { do { /* This unlocks the server's recv call, who will close * his socket, and therefore unlock our call to recv as well, * letting the thread terminate. */ nl_tcp_snd("X", c->socket); } while((c = (client*)rGet(&client_array, NEXT, &remember)) != NULL); } lock_ur(&client_array); lock_r(&game_server_array); if((g = (server_game*)rGet(&game_server_array, FIRST, &remember)) != NULL) { do { /* This unlocks the server's recv call, who will close * his socket, and therefore unlock our call to recv as well, * letting the thread terminate. */ nl_tcp_snd("X", g->socket); } while((g = (server_game*)rGet(&game_server_array, NEXT, &remember)) != NULL); } lock_ur(&game_server_array); /* Now every thread should be terminated. * The list should be empty. Let's simply destroy the lists. */ lock_w(&game_server_array); rDestroy(&game_server_array, delete_game_server); rFree(&game_server_array); lock_w(&client_array); rDestroy(&client_array, delete_client); rFree(&client_array); nl_release_tcp_network(&port, "N"); LOG("The end."); nl_release_tcp_network(&web_port, NULL); thread_wait(web_t); common_finish(); destroy_lang(); exit(0); }