Repository navigation
Expand file tree
/
Copy pathbuffer.c
More file actions
129 lines (100 loc) · 2.6 KB
/
Copy pathbuffer.c
File metadata and controls
129 lines (100 loc) · 2.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#include <limits.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define hexit \
do { \
displayHelp(); \
return -1; \
} while (0);
typedef struct {
// volatile _Bool read;
void *data;
} node;
typedef struct {
node *buf;
long size;
} thread_args;
void displayHelp() {
printf("Usage: buffer [buffer_size]\n");
exit(1);
}
void *writer(void *a);
void *reader(void *a);
long roundUp2Power(long n);
int main(int argc, char **argv) {
unsigned long size = 128;
pthread_t reader_t, writer_t;
node *buffer;
if (argc > 2) displayHelp();
if (argc == 2) size = strtol(argv[1], NULL, 10);
if (size > LONG_MAX) size = LONG_MAX;
size = roundUp2Power(size);
srand(time(NULL)); // seed
if ((buffer = calloc(size, sizeof(node))) == NULL) return (-1);
printf("Spawning threads...\n");
thread_args x = {.buf = buffer, .size = size};
if (pthread_create(&writer_t, NULL, writer, &x) == -1) exit(1);
if (pthread_create(&reader_t, NULL, reader, &x) == -1) exit(1);
pthread_join(reader_t, NULL);
pthread_join(writer_t, NULL);
}
void *reader(void *a) {
thread_args arg = *(thread_args *)a;
long size = arg.size;
node *buf = arg.buf;
long i = 0;
while (1) {
int *val;
while (buf[i].data == NULL) { // reader reached writer position
printf("READER -> Buffer empty\n");
usleep(rand() % 10);
}
val = buf[i].data;
printf("READER -> Read %d in buf[%ld]\n", *val, i);
free(buf[i].data);
buf[i].data =
NULL; // Important! Writer now knows the node has been emptied
i = (i + 1) & size;
usleep(1);
}
}
void *writer(void *a) {
thread_args arg = *(thread_args *)a;
long size = arg.size;
node *buf = arg.buf;
long i = 0;
while (1) {
int *val;
while (buf[i].data != NULL) { // reader is ahead of writer
printf("WRITER -> Buffer full\n");
usleep(rand() % 10); // wait until the reader consumes the buffer
}
val = malloc(sizeof(int));
if (val != NULL) {
*val = rand() % 1000;
buf[i].data = val;
printf("WRITER -> Wrote %d in buf[%ld]\n", *val, i);
i = (i + 1) & size;
}
usleep(1);
}
}
/**
*
* @note n must be > 0 && < LONG_MAX
* @return 'n' nearest greater power of 2 or lesser if n == LONG_MAX
*/
long roundUp2Power(long n) {
if (n <= 0)
return 0;
n = n - 1;
// unset rightmost bit until only one is left
while (n & n - 1) {
n = n & n - 1;
}
// n is a power of two but lesser than the given parameter
// left shift to get next power of 2 if not overflow
return n << 1 < 0 ? n : n << 1;
}