├── .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 |
--------------------------------------------------------------------------------