一个c写的线程安全fifo队列

git目录如下:
https://github.com/rdhananjaya/thread-safe-fifo-queue
fifo.h

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>

#ifndef FIFO_H
#define FIFO_H

struct _node {
	void *data;
	struct _node * next;
};
typedef struct _node node;
  
struct _end_q {
	node * first;
	node * last;
};
typedef struct _end_q queue;


// create and return the queue
queue * queue_factory(void);

// destory the queue (free all the memory associate with the que even the data)
void queue_destroy(queue * que);


// enque the data into queue
// data is expected to a pointer to a heap allocated memory
int enque(queue * que, void * data);

// return the data from the que (FIFO)
// and free up all the internally allocated memory
// but the user have to free the returning data pointer
void * deque(queue * que);

#endif

fifo.c

#include "fifo.h"
#include <time.h>


#define DEBUG
#undef DEBUG /*  uncomment when you are done! */
  
#ifdef DEBUG
    #define print printf
#else
    #define print(...)
#endif



/*****************************************
struct _node {
    void *data;
    struct _node * next;
};
typedef struct _node node;

struct _end_q {
   node * first;
   node * last;
};
typedef struct _end_q queue;

****************************************/


pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

/**
 * create and return a new queue
 **/
queue * queue_factory()
{
   queue * new_queue = malloc(sizeof(queue));
   if(new_queue == NULL) {
       fprintf(stderr, "Malloc failed creating the que\n");
       return NULL;
   }
   new_queue->first = NULL;
   new_queue->last = NULL;

   print("Generated the que @ %p\n", new_queue);

   return new_queue;
}

void queue_destroy(queue * que)
{
    
    print("Enterd to queue_destroy\n");

    if(que == NULL) {
        return;
    }

    print("que is not null, que = %p\n", que);

    pthread_mutex_lock(&mutex);
    if(que->first == NULL) {
        print("que->first == NULL .... \n");
        free(que);
        pthread_mutex_unlock(&mutex);
        return;
    }

    print("que is there lets try to free it...\n");

    node * _node = que->first;

    while(_node != NULL) {
        // freeing the data coz it's on the heap and no one to free it
        // except for this one
        print("freeing : %s\n", (char *)_node->data);
        free(_node->data);
        node *tmp = _node->next;
        free(_node);
        _node = tmp;
    }

    free(que);

    pthread_mutex_unlock(&mutex);
}

/**
 * que is a queue pointer
 * data is a heap allocated memory pointer
 */
int enque(queue * que, void * data)
{
    node * new_node = malloc(sizeof(node));
    if(new_node == NULL) {
        fprintf(stderr, "Malloc failed creating a node\n");
        return -1;
    }
    // assumming data is in heap
    new_node->data = data;
    new_node->next = NULL;

    pthread_mutex_lock(&mutex);
    if (que->first == NULL) {
        // new que
        que->first = new_node;
        que->last = new_node;
    } else {
        que->last->next = new_node;
        que->last = new_node;
    }
    pthread_mutex_unlock(&mutex);

    return 0;
}

void * deque(queue * que) 
{
    print("Entered to deque\n");
    if (que == NULL) {
        print("que is null exiting...\n");
        return NULL;
    }


    pthread_mutex_lock(&mutex);
    if (que->first == NULL) {
        pthread_mutex_unlock(&mutex);
        print("que->first is null exiting...\n");
        return NULL;
    }

    void * data;
    node * _node = que->first;
    if (que->first == que->last) {
        que->first = NULL;
        que->last = NULL;
    } else {
        que->first = _node->next;
    }

    data = _node->data;

    print("Freeing _node@ %p", _node);
    free(_node);
    pthread_mutex_unlock(&mutex);
    print("Exiting deque\n");
    return data;
}

test.c

/*
 * @Author: your name
 * @Date: 2021-03-23 21:04:13
 * @LastEditTime: 2021-03-23 22:04:27
 * @LastEditors: Please set LastEditors
 * @Description: In User Settings Edit
 * @FilePath: \thread-safe-fifo-queue-master\fifo_test.c
 */
#include <stdio.h>
#include "fifo.h"

#define number_of_threads	6 
#define number_of_threads_d 5
#define number_of_iters		1000
 
#define DEBUG
//#undef DEBUG /*   uncomment when you are done! */
 
#ifdef DEBUG
	#define print printf
#else
    #define print(...)
#endif


typedef struct info{
    char messge[16];
    int data_len;
}info_t;

struct _stru {
    int number;
    int thread_no;
    queue * q;
};
 
void * func(void * arg)
{
    struct _stru * args = (struct _stru *) arg;
    int number = args->number;
    //int th_number = args->thread_no;
    queue * q = args->q;

    int i;
    srand(time(NULL));
    for(i = 0; i < number; i++) {
        info_t* message = (info_t*)malloc(sizeof(info_t));
        snprintf(message->messge, 15, "rand: %d", rand());
        enque(q, (void *)message);
    }

    return NULL;
}


void * func_d(void * args)
{
    print("Func_D running....\n");

    queue * q = (queue *) args;

    void * data;
    while((data = deque(q)) != NULL) {
        char * string = ((info_t *)data)->messge;
        print("DeQued : %s, @%p\n", string, data);
        free(data);
    }
    print("Func_D exiting....\n");

    return NULL;
}

int main(void) 
{
    queue * q = queue_factory();

    pthread_t threads[number_of_threads];
    pthread_t thread_d[number_of_threads_d];
    
    int i;
    struct _stru arg[number_of_threads];
    for(i = 0; i < number_of_threads; i++) {
        arg[i].number = number_of_iters;
        arg[i].thread_no = i;
        arg[i].q = q;
        pthread_create(threads+i, NULL, func, (void *)&arg[i]); 
    }

    for(i = 0; i < number_of_threads_d; i++) {
        pthread_create(thread_d+i, NULL, func_d, (void *)q);
    }

    for(i = 0; i < number_of_threads; i++) {
        pthread_join(*(threads+i), NULL);
    }
    
    for(i = 0; i < number_of_threads_d; i++) {
        pthread_join(*(thread_d+i), NULL);   
    }

    print("Going to run queue_destroy(...) \n");
    queue_destroy(q);
    print("que freeed... :) \n");

    return 0;
}

Makefile

CFLAGS=-I./ -Wall -Wstrict-prototypes -Werror -g
CC=gcc

all: test 

test: fifo.o test.o 
	$(CC) -o $@ $? -pthread
	
%.o:%.c
	$(CC) $(CFLAGS) -c $? -o $@

clean:
	rm -f *.o *~
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
FIFO线程等待队列是指一种先入先出的数据结构,用于在多线程编程中安全地传递生产者和消费者线程之间的消息或其他数据。它可以确保多个线程可以按照先入先出的顺序安全地处理同一个队列实例。 与标准的FIFO队列不同,Python的queue模块还提供了LifoQueue,它使用后进先出的顺序,通常与栈相关联。可以通过导入queue模块并创建LifoQueue实例来使用后进先出的线程等待队列。例如: ```python import queue q = queue.LifoQueue() for i in range(5): q.put(i) while not q.empty(): print(q.get(), end=' ') ``` 上述代码会输出:4 3 2 1 0,即按照后进先出的顺序从队列中取出并打印元素。这种FIFO线程等待队列的特点可以满足一些特定的线程处理需求。 需要注意的是,在多线程编程中,线程等待队列的实现会有一定的复杂性,包括设置当前线程为工作线程、同步状态的管理、添加节点到队列中等。但总的来说,FIFO线程等待队列是一种常用的数据结构,可以在多线程编程中有效地进行线程间通信和数据传递。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [队列--线程安全FIFO实现](https://blog.csdn.net/weixin_33946020/article/details/94214683)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *3* [21-AQS:基于FIFO等待队列的阻塞锁](https://blog.csdn.net/qq_38331606/article/details/84621377)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值