pthreads/prod_cons_unbound/{given → src}/queue.c RENAMED
@@ -1,79 +1,95 @@
1
  // Copyright 2021 Jeisson Hidalgo-Cespedes <jeisson.hidalgo@ucr.ac.cr> CC-BY-4
2
 
3
  #include <assert.h>
4
  #include <stdlib.h>
5
 
6
  #include "queue.h"
7
 
8
- void queue_remove_first(queue_t* queue);
 
9
 
10
  int queue_init(queue_t* queue) {
11
  assert(queue);
 
12
  queue->head = NULL;
13
  queue->tail = NULL;
14
- return EXIT_SUCCESS;
15
  }
16
 
17
  int queue_destroy(queue_t* queue) {
18
  queue_clear(queue);
19
- return EXIT_SUCCESS;
20
  }
21
 
22
  bool queue_is_empty(queue_t* queue) {
23
  assert(queue);
 
 
 
 
 
 
 
 
24
  return queue->head == NULL;
25
  }
26
 
27
  int queue_enqueue(queue_t* queue, const size_t data) {
28
  assert(queue);
29
  int error = EXIT_SUCCESS;
30
 
31
  queue_node_t* new_node = (queue_node_t*) calloc(1, sizeof(queue_node_t));
32
  if (new_node) {
33
  new_node->data = data;
34
 
 
35
  if (queue->tail) {
36
  queue->tail = queue->tail->next = new_node;
37
  } else {
38
  queue->head = queue->tail = new_node;
39
  }
 
40
  } else {
41
  error = EXIT_FAILURE;
42
  }
43
 
44
  return error;
45
  }
46
 
47
  int queue_dequeue(queue_t* queue, size_t* data) {
48
  assert(queue);
49
  int error = 0;
50
 
51
- if (!queue_is_empty(queue)) {
 
52
  if (data) {
53
  *data = queue->head->data;
54
  }
55
- queue_remove_first(queue);
56
  } else {
57
  error = EXIT_FAILURE;
58
  }
 
59
 
60
  return error;
61
  }
62
 
63
- void queue_remove_first(queue_t* queue) {
64
  assert(queue);
65
- assert(!queue_is_empty(queue));
66
  queue_node_t* node = queue->head;
67
  queue->head = queue->head->next;
68
  free(node);
69
  if (queue->head == NULL) {
70
  queue->tail = NULL;
71
  }
72
  }
73
 
74
  void queue_clear(queue_t* queue) {
75
  assert(queue);
76
- while (!queue_is_empty(queue)) {
77
- queue_remove_first(queue);
 
78
  }
 
79
  }
1
  // Copyright 2021 Jeisson Hidalgo-Cespedes <jeisson.hidalgo@ucr.ac.cr> CC-BY-4
2
 
3
  #include <assert.h>
4
  #include <stdlib.h>
5
 
6
  #include "queue.h"
7
 
8
+ void queue_remove_first_unsafe(queue_t* queue);
9
+ bool queue_is_empty_unsafe(queue_t* queue);
10
 
11
  int queue_init(queue_t* queue) {
12
  assert(queue);
13
+ int error = pthread_mutex_init(&queue->can_access_queue, /*attr*/ NULL);
14
  queue->head = NULL;
15
  queue->tail = NULL;
16
+ return error;
17
  }
18
 
19
  int queue_destroy(queue_t* queue) {
20
  queue_clear(queue);
21
+ return pthread_mutex_destroy(&queue->can_access_queue);
22
  }
23
 
24
  bool queue_is_empty(queue_t* queue) {
25
  assert(queue);
26
+ pthread_mutex_lock(&queue->can_access_queue);
27
+ bool result = queue->head == NULL;
28
+ pthread_mutex_unlock(&queue->can_access_queue);
29
+ return result;
30
+ }
31
+
32
+ bool queue_is_empty_unsafe(queue_t* queue) {
33
+ assert(queue);
34
  return queue->head == NULL;
35
  }
36
 
37
  int queue_enqueue(queue_t* queue, const size_t data) {
38
  assert(queue);
39
  int error = EXIT_SUCCESS;
40
 
41
  queue_node_t* new_node = (queue_node_t*) calloc(1, sizeof(queue_node_t));
42
  if (new_node) {
43
  new_node->data = data;
44
 
45
+ pthread_mutex_lock(&queue->can_access_queue);
46
  if (queue->tail) {
47
  queue->tail = queue->tail->next = new_node;
48
  } else {
49
  queue->head = queue->tail = new_node;
50
  }
51
+ pthread_mutex_unlock(&queue->can_access_queue);
52
  } else {
53
  error = EXIT_FAILURE;
54
  }
55
 
56
  return error;
57
  }
58
 
59
  int queue_dequeue(queue_t* queue, size_t* data) {
60
  assert(queue);
61
  int error = 0;
62
 
63
+ pthread_mutex_lock(&queue->can_access_queue);
64
+ if (!queue_is_empty_unsafe(queue)) {
65
  if (data) {
66
  *data = queue->head->data;
67
  }
68
+ queue_remove_first_unsafe(queue);
69
  } else {
70
  error = EXIT_FAILURE;
71
  }
72
+ pthread_mutex_unlock(&queue->can_access_queue);
73
 
74
  return error;
75
  }
76
 
77
+ void queue_remove_first_unsafe(queue_t* queue) {
78
  assert(queue);
79
+ assert(!queue_is_empty_unsafe(queue));
80
  queue_node_t* node = queue->head;
81
  queue->head = queue->head->next;
82
  free(node);
83
  if (queue->head == NULL) {
84
  queue->tail = NULL;
85
  }
86
  }
87
 
88
  void queue_clear(queue_t* queue) {
89
  assert(queue);
90
+ pthread_mutex_lock(&queue->can_access_queue);
91
+ while (!queue_is_empty_unsafe(queue)) {
92
+ queue_remove_first_unsafe(queue);
93
  }
94
+ pthread_mutex_unlock(&queue->can_access_queue);
95
  }