CDList* CD_CloneList (CDList* self) { CDList* cloned = CD_CreateList(); assert(self); CD_LIST_FOREACH(self, it) { CD_ListPush(cloned, CD_ListIteratorValue(it)); }
void CD_AddJob (CDWorkers* self, CDJob* job) { pthread_mutex_lock(&self->lock.mutex); CD_ListPush(self->jobs, (CDPointer) job); pthread_cond_signal(&self->lock.condition); pthread_mutex_unlock(&self->lock.mutex); }
CDList* CD_CreateEventParameters (const char* first, ...) { va_list ap; CDList* self = CD_CreateList(); char* current = NULL; if (first) { va_start(ap, first); CD_ListPush(self, (CDPointer) strdup(first)); while ((current = va_arg(ap, char*))) { CD_ListPush(self, (CDPointer) strdup(current)); } va_end(ap); } return self; }
bool CD_RunWorker (CDWorker* self) { assert(self); SLOG(self->server, LOG_INFO, "worker %d started", self->id); while (self->working) { self->job = NULL; if (!CD_HasJobs(self->workers)) { pthread_mutex_lock(&self->workers->lock.mutex); SDEBUG(self->server, "worker %d ready", self->id); pthread_cond_wait(&self->workers->lock.condition, &self->workers->lock.mutex); pthread_mutex_unlock(&self->workers->lock.mutex); } if (!self->working) { break; } self->job = CD_NextJob(self->workers); if (!self->job) { SDEBUG(self->server, "no jobs for %d :<", self->id); continue; } SDEBUG(self->server, "worker %d running", self->id); if (self->job->type == CDCustomJob) { CDCustomJobData* data = (CDCustomJobData*) self->job->data; data->callback(data->data); CD_DestroyJob(self->job); } else if (CD_JOB_IS_PLAYER(self->job)) { CDClient* client; if (self->job->type == CDClientProcessJob) { client = ((CDClientProcessJobData*) self->job->data)->client; } else { client = (CDClient*) self->job->data; } if (!client) { CD_DestroyJob(self->job); continue; } pthread_rwlock_rdlock(&client->lock.status); if (client->status == CDClientDisconnect) { if (self->job->type != CDClientDisconnectJob) { CD_DestroyJob(self->job); self->job = NULL; client->jobs--; } } pthread_rwlock_unlock(&client->lock.status); if (!self->job) { continue; } if (self->job->type == CDClientConnectJob) { CD_EventDispatch(self->server, "Client.connect", client); pthread_rwlock_wrlock(&client->lock.status); if (client->status != CDClientDisconnect) { client->status = CDClientIdle; } pthread_rwlock_unlock(&client->lock.status); CD_DestroyJob(self->job); if (CD_BufferLength(client->buffers->input) > 0) { CD_ReadFromClient(client); } } else if (self->job->type == CDClientProcessJob) { CD_EventDispatch(self->server, "Client.process", client, ((CDClientProcessJobData*) self->job->data)->packet); CD_EventDispatch(self->server, "Client.processed", client, ((CDClientProcessJobData*) self->job->data)->packet); pthread_rwlock_wrlock(&client->lock.status); if (client->status != CDClientDisconnect) { client->status = CDClientIdle; } client->jobs--; pthread_rwlock_unlock(&client->lock.status); CD_DestroyJob(self->job); if (CD_BufferLength(client->buffers->input) > 0) { CD_ReadFromClient(client); } } else if (self->job->type == CDClientDisconnectJob) { while (true) { pthread_rwlock_rdlock(&client->lock.status); if (client->jobs < 1) { pthread_rwlock_unlock(&client->lock.status); break; } pthread_rwlock_unlock(&client->lock.status); } CD_EventDispatch(self->server, "Client.disconnect", client, (bool) ERROR(client)); CD_ListPush(self->server->disconnecting, (CDPointer) client); CD_ServerFlush(client->server, false); CD_DestroyJob(self->job); } } self->job = NULL; } return true; }