├── .gitattributes ├── LICENSE ├── README.md ├── fifoQ.h └── fifoQ.c /.gitattributes: -------------------------------------------------------------------------------- 1 | *.h linguist-language=C 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Federico 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # synchronized-queue 2 | 3 | A thread synchonized FIFO queue made for C's PThreads. 4 | 5 | ## Usage 6 | 7 | Place the files [fifoQ.c](fifoQ.c) and [fifoQ.h](fifoQ.h) in your project directory. 8 | 9 | In order to compile the code and run it, first off you have to compile the library: 10 | 11 | ``` 12 | gcc fifoQ.c -c -o fifoQ.o 13 | ``` 14 | 15 | Then create the static library: 16 | 17 | ``` 18 | ar rvs libfifoq.a fifoQ.o 19 | ``` 20 | 21 | And compile with your source code: 22 | 23 | ``` 24 | gcc main.c -lpthread -o main -L. -lfifoq 25 | ``` 26 | 27 |
28 |
29 | 30 | Here's what you can do with this library: 31 | ```c 32 | //Create the queue 33 | queue Q = initQueue(); 34 | 35 | //Insert an element in the queue 36 | void *element; 37 | push(Q, element); 38 | 39 | //Remove an element from the queue 40 | void *head = pop(Q); 41 | 42 | //Get the size of the queue 43 | size_t size = getSize(Q); 44 | 45 | //Delete and free the space of the queue 46 | deleteQueue(Q); 47 | ``` 48 | 49 | ## License 50 | 51 | Under the MIT License, you can do whatever you want with this library. Anyway, a mention would be appreciated :wink:. 52 | -------------------------------------------------------------------------------- /fifoQ.h: -------------------------------------------------------------------------------- 1 | #ifndef FIFOQ_H 2 | #define FIFOQ_H 3 | 4 | #include 5 | 6 | //Support struct 7 | typedef struct node { 8 | void *info; //Void pointer to use the queue with everything 9 | struct node *next; //Pointer to the following element of the queue 10 | } node; 11 | 12 | //Queue struct 13 | typedef struct queue { 14 | size_t size; //Queue dimension 15 | struct node *first; //Pointer to the first element of the queue 16 | struct node *last; //Pointer to the last element of the queue 17 | pthread_mutex_t lock; //Mutex semaphore within the queue 18 | pthread_cond_t cond; //Condition variable within the queue 19 | } queue; 20 | 21 | /** 22 | * Creates and initializes a new queue 23 | * \returns queue - if everything is ok 24 | * \returns NULL - if errors occurred 25 | */ 26 | queue *initQueue (); 27 | 28 | /** 29 | * Creates a new element and pushes it to the tail of the queue 30 | * \returns 0 - if everything is ok 31 | * \returns 1 - if errors occurred 32 | */ 33 | int push (queue *q, void *data); 34 | 35 | /** 36 | * Removes the head of the queue 37 | * \returns head's info - if everything is ok 38 | * \returns NULL - if the queue is empty 39 | */ 40 | void* pop (queue *q); 41 | 42 | /** 43 | * Returns the size of the queue 44 | * \returns queue size - if everything ok 45 | * \returns -1 - if errors occurred 46 | */ 47 | size_t getSize (queue *q); 48 | 49 | // Deletes and frees the queue 50 | void deleteQueue (queue *q); 51 | 52 | #endif -------------------------------------------------------------------------------- /fifoQ.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "fifoQ.h" 7 | 8 | queue* initQueue () { 9 | queue *q=malloc(sizeof(queue)); 10 | if (!q) return NULL; 11 | q->first=malloc(sizeof(node)); 12 | if (!q->first) return NULL; 13 | q->first->info = NULL; 14 | q->first->next = NULL; 15 | q->last = q->first; 16 | q->size=0; 17 | if (pthread_mutex_init(&q->lock, NULL) != 0) { 18 | perror("Error inizializing mutex in queue"); 19 | free(q); 20 | free(q->first); 21 | return NULL; 22 | } 23 | if (pthread_cond_init(&q->cond, NULL) != 0) { 24 | perror("Error initializing varcond in queue"); 25 | if (&q->lock) pthread_mutex_destroy(&q->lock); 26 | free(q); 27 | free(q->first); 28 | return NULL; 29 | } 30 | return q; 31 | } 32 | 33 | int push (queue*q, void *data) { 34 | node *ins=malloc(sizeof(node)); 35 | if (!q || !data || !ins) return -1; 36 | ins->info=data; 37 | ins->next=NULL; 38 | pthread_mutex_lock(&q->lock); 39 | if (q->size==0) { 40 | q->first->next=ins; 41 | q->last=ins; 42 | } else { 43 | q->last->next=ins; 44 | q->last=ins; 45 | } 46 | (q->size)++; 47 | pthread_cond_signal(&q->cond); 48 | pthread_mutex_unlock(&q->lock); 49 | return 0; 50 | } 51 | 52 | void* pop (queue*q) { 53 | if (q==NULL) return NULL; 54 | pthread_mutex_lock(&q->lock); 55 | while (q->size == 0) { 56 | pthread_cond_wait(&q->cond, &q->lock); 57 | } 58 | assert(q->first->next); 59 | node*n=(node*)q->first; 60 | void*data=(q->first->next)->info; 61 | q->first=q->first->next; 62 | (q->size)--; 63 | assert(q->size>=0); 64 | pthread_mutex_unlock(&q->lock); 65 | free(n); 66 | return data; 67 | } 68 | 69 | size_t getSize (queue*q) { 70 | if (q==NULL) return -1; 71 | size_t size=-1; 72 | pthread_mutex_lock(&q->lock); 73 | size=q->size; 74 | pthread_mutex_unlock(&q->lock); 75 | return size; 76 | } 77 | 78 | void deleteQueue (queue*q) { 79 | while (q->first != q->last) { 80 | node *killer=(node*)q->first; 81 | q->first=q->first->next; 82 | free(killer); 83 | } 84 | if (q->first) free(q->first); 85 | if (&q->lock) pthread_mutex_destroy(&q->lock); 86 | if (&q->cond) pthread_cond_destroy(&q->cond); 87 | free(q); 88 | } 89 | --------------------------------------------------------------------------------