#define _POSIX_C_SOURCE 200112L #include "log.h" #include #include #include #include #include #include int in_log(logs *log,log_manager *self) { sem_wait(&self->log_sem);//加锁 logs *buf = self->rear; if(self->log == NULL){ self->log = log; self->rear = log; self->count++; sem_post(&self->log_sem); return 0; } self->count++; buf->next = log; log->next = NULL; self->rear = log; sem_post(&self->log_sem); return self->count; } logs *out_log(log_manager *self) { sem_wait(&self->log_sem); logs *buf = self->log; if(self->log==NULL) { sem_post(&self->log_sem); return NULL; } if(self->log->next ==NULL) self->log = self->rear = NULL; self->count--; sem_post(&self->log_sem); buf->next =NULL; return buf; } int sleep_with_signal(log_manager *self) { struct timespec ts; int rc; /* 计算绝对超时:当前 + 1000 s */ if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) return -1; /* 罕见失败 */ ts.tv_sec += 1000; /* 纳秒部分无需处理,1000 s 整不会溢出 */ pthread_mutex_lock(&self->mtx); /* 进入临界区 */ while (1) { rc = pthread_cond_timedwait(&self->cond, &self->mtx, &ts); if (rc == ETIMEDOUT) { /* 1000 s 到点 */ pthread_mutex_unlock(&self->mtx); return 1; /* 正常超时 */ } if (rc != 0) { /* 其他错误 */ pthread_mutex_unlock(&self->mtx); return -1; } /* 被 signal / broadcast 提前唤醒,检查 stop */ if (self->stop == 1) {/* 主线程要求退出 */ pthread_mutex_unlock(&self->mtx); return 0; /* 告诉调用者:该结束了 */ } } } int cleanup(log_manager *self) { if(self->log ==NULL) return 1; logs *tobeclean,*loc; sem_wait(&self->log_sem); loc = self->log; self->log = NULL; self->count = 0; sem_post(&self->log_sem); while(loc->next !=NULL) { tobeclean = loc; loc = loc->next; free(tobeclean); } free(loc); } void log_manager_stop(log_manager *self) { pthread_mutex_lock(&self->mtx); self->stop = 1; /* 置退出标志 */ pthread_cond_broadcast(&self->cond); /* 唤醒所有等待线程 */ printf("SYS:stopping loger\n"); pthread_mutex_unlock(&self->mtx); printf("SYS:done\n"); } //定期清理函数 void *clear_log(void *self_p) { log_manager *self = (log_manager*)self_p; for(;;) { sleep_with_signal(self); sem_wait(&self->log_sem); if((self->count<256||self->log==NULL)&&self->stop !=1){ sem_post(&self->log_sem); continue; } sem_post(&self->log_sem); cleanup(self); if(self->stop == 1){ return NULL; } } } int init_loger(log_manager *self) { if(self == NULL) { perror("NULL\n"); return -1; } sem_init(&self->log_sem, 0,1); pthread_mutex_init(&self->mtx,NULL); pthread_cond_init(&self->cond,NULL); self->in_log = in_log; self->out_log = out_log; self->clear_log = clear_log; self->log = NULL; self->stop = 0; self->cleanup = cleanup; self->count = 0; }