Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <stdlib.h>
- #include <pthread.h>
- #include <unistd.h>
- #include <string.h>
- #include <signal.h>
- #include <sys/queue.h>
- #define BUFFER_SIZE 16
- struct node {
- int value;
- CIRCLEQ_ENTRY(node) circleq;
- TAILQ_ENTRY(node) tailq;
- };
- CIRCLEQ_HEAD(circleq_head, node);
- TAILQ_HEAD(tailq_fifo, node);
- struct circle_buffer {
- struct node* buffer;
- struct node* cursor;
- struct circleq_head head;
- struct tailq_fifo* fifo;
- size_t buffer_size;
- size_t count;
- pthread_mutex_t fifo_lock;
- pthread_t fifo_thread;
- void (*process)(struct circle_buffer*, struct node*);
- void (*enqueue)(struct circle_buffer*, struct node*);
- struct node* (*get_slot)(struct circle_buffer*, size_t);
- struct node* (*get_current_node)(struct circle_buffer*);
- void (*start_processing)(struct circle_buffer*, void (*)(struct circle_buffer*, struct node*));
- };
- static void setup_signal_handler() {
- struct sigaction sa;
- memset(&sa, 0, sizeof(sa));
- sa.sa_handler = sigusr1_handler;
- sigaction(SIGUSR1, &sa, NULL);
- }
- static void* fifo_worker(void* arg) {
- struct circle_buffer* this = (struct circle_buffer*)arg;
- do {
- while (!TAILQ_EMPTY(this->fifo)) {
- pthread_mutex_lock(&this->fifo_lock);
- struct node* n = TAILQ_FIRST(this->fifo);
- if (n)
- TAILQ_REMOVE(this->fifo, n, tailq);
- pthread_mutex_unlock(&this->fifo_lock);
- if (this->process)
- this->process(this, n);
- }
- usleep(200); // leve delay para evitar busy wait
- } while (~0);
- return 0;
- }
- void enqueue(struct circle_buffer* this, struct node* n) {
- if (!n) return;
- pthread_mutex_lock(&this->fifo_lock);
- TAILQ_INSERT_TAIL(this->fifo, n, tailq);
- pthread_mutex_unlock(&this->fifo_lock);
- }
- struct node* get_slot(struct circle_buffer* this, size_t index) {
- if (index >= this->buffer_size)
- return 0;
- return (this->buffer + index);
- }
- struct node* get_current_node(struct circle_buffer* this) {
- if (!this->cursor || this->cursor == CIRCLEQ_END(&this->head))
- return 0;
- struct node* current = this->cursor;
- this->cursor = CIRCLEQ_NEXT(current, circleq);
- if (this->cursor == CIRCLEQ_END(&this->head))
- this->cursor = CIRCLEQ_FIRST(&this->head);
- return current;
- }
- void start_processing(struct circle_buffer* this, void (*callback)(struct circle_buffer*, struct node*)) {
- this->process = callback;
- pthread_create(&this->fifo_thread, 0, fifo_worker, this);
- }
- void process_node(struct circle_buffer* cb, struct node* n) {
- if (!cb || !n) return;
- struct node* slot = cb->get_current_node(cb);
- if (slot) {
- memcpy(slot, n, sizeof(struct node));
- printf("[worker] processou node com valor %d\n", slot->value);
- }
- }
- struct circle_buffer* new_circle_buffer(size_t size, struct tailq_fifo* fifo) {
- int i;
- struct circle_buffer* cb = calloc(1, sizeof(struct circle_buffer));
- if (!cb)
- return 0;
- cb->buffer_size = size;
- cb->buffer = calloc(size, sizeof(struct node));
- if (!cb->buffer) {
- free(cb);
- return 0;
- }
- CIRCLEQ_INIT(&cb->head);
- cb->fifo = fifo;
- i = 0;
- do
- {
- CIRCLEQ_INSERT_TAIL(&cb->head, (cb->buffer + i), circleq);
- } while (++i < size);
- cb->cursor = CIRCLEQ_EMPTY(&cb->head) ? 0 : CIRCLEQ_FIRST(&cb->head);
- pthread_mutex_init(&cb->fifo_lock, 0);
- cb->enqueue = enqueue;
- cb->get_slot = get_slot;
- cb->get_current_node = get_current_node;
- cb->start_processing = start_processing;
- return cb;
- }
- // --- SIGNAL HANDLER ---
- struct circle_buffer* global_cb = NULL;
- void sigusr1_handler(int sig) {
- if (global_cb) {
- printf("\n[SIGNAL] Recebido SIGUSR1. Cancelando thread fifo_worker...\n");
- pthread_cancel(global_cb->fifo_thread);
- pthread_join(global_cb->fifo_thread, NULL);
- printf("[SIGNAL] Thread finalizada com sucesso.\n");
- }
- exit(0);
- }
- int main() {
- signal(SIGUSR1, sigusr1_handler);
- struct tailq_fifo fifo;
- TAILQ_INIT(&fifo);
- struct circle_buffer* cb = new_circle_buffer(BUFFER_SIZE, &fifo);
- if (!cb) {
- fprintf(stderr, "Erro ao criar circle_buffer\n");
- return 1;
- }
- global_cb = cb;
- cb->start_processing(cb, process_node);
- // Simula socket_receiver jogando valores
- for (int i = 0; i < 10; ++i) {
- struct node* temp = malloc(sizeof(struct node));
- temp->value = 100 + i;
- cb->enqueue(cb, temp);
- usleep(30000);
- }
- printf(">>> Processo principal aguardando sinal SIGUSR1 (kill -USR1 %d)\n", getpid());
- pause();
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement