-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathline_processor.c
More file actions
305 lines (292 loc) · 8.69 KB
/
line_processor.c
File metadata and controls
305 lines (292 loc) · 8.69 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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
/* ******************************
* Program Name: line_processor.c
* By: Benjamin Reed
* ONID: 933 889 437
* Email: reedbe@oregonstate.edu
* Desc: lineprocessor.c creates 4 seperate threads and follows this:
* stdin --> input --> buffer1 --> line_processor --> buffer2 --> plus_sign --> buffer3 --> output -->stdout
* The program follows the consumer-producer outlined in class
* There are shared buffers between each of the threads that use the mutex locks to stop any race cases
* The mutex locks also implement semaphores so that deadlocks do not occur in the programs and all the functions
* wait for the locks to lift before attempting to call any get functions.
****************************** */
// SOURCES: Use of scripts given on assigment page
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>
int num_chars = 0;
//line input for user input option
char line_input[1000];
//pthreads
pthread_t input_id, output_id, plus_sign_id, line_separator_id;
// Buffer 1, shared resource between input thread and line-seperator thread
char buffer1[50000];
// Number of items in the buffer
int count_1 = 0;
// Index where the input thread will put the next item
int prod_idx_1 = 0;
// Index where the line-seperator thread will pick up the next item
int con_idx_1 = 0;
// Initialize the mutex for buffer 1
pthread_mutex_t mutex_1 = PTHREAD_MUTEX_INITIALIZER;
// Initialize the condition variable for buffer 1
pthread_cond_t full_1 = PTHREAD_COND_INITIALIZER;
// Buffer 2, shared resource between line-seperator thread and plus-sign thread
char buffer2[50000];
// Number of items in the buffer
int count_2 = 0;
// Index where the line-seperator will put the next item
int prod_idx_2 = 0;
// Index where the plus-sign thread will pick up the next item
int con_idx_2 = 0;
// Initialize the mutex for buffer 1
pthread_mutex_t mutex_2 = PTHREAD_MUTEX_INITIALIZER;
// Initialize the condition variable for buffer 1
pthread_cond_t full_2 = PTHREAD_COND_INITIALIZER;
// Buffer 2, shared resource between plus-sign thread and output thread
char buffer3[50000];
// Number of items in the buffer
int count_3 = 0;
// Index where the plus-sign will put the next item
int prod_idx_3 = 0;
// Index where the output thread will pick up the next item
int con_idx_3 = 0;
// Initialize the mutex for buffer 1
pthread_mutex_t mutex_3 = PTHREAD_MUTEX_INITIALIZER;
// Initialize the condition variable for buffer 1
pthread_cond_t full_3 = PTHREAD_COND_INITIALIZER;
/* ******************************
* Function Name: get_buf_1
* Input: NA
* Output: int
* Desc: Gets the next char from the buffer1
****************************** */
int get_buf_1(){
pthread_mutex_lock(&mutex_1);
while(count_1 == 0)
pthread_cond_wait(&full_1, &mutex_1);
char line_char = buffer1[con_idx_1];
con_idx_1 = con_idx_1 + 1;
count_1--;
pthread_mutex_unlock(&mutex_1);
return line_char;
}
/* ******************************
* Function Name: set_buf_1
* Input: char
* Output: NA
* Desc: Sets the buffer1 at the current
* position to the char passed
****************************** */
void set_buf_1(char line_char){
pthread_mutex_lock(&mutex_1);
buffer1[prod_idx_1] = line_char;
prod_idx_1 = prod_idx_1 + 1;
count_1++;
pthread_cond_signal(&full_1);
pthread_mutex_unlock(&mutex_1);
}
/* ******************************
* Function Name: get_buf_2
* Input: NA
* Output: int
* Desc: Gets the next char from the buffer2
****************************** */
int get_buf_2(){
pthread_mutex_lock(&mutex_2);
while(count_2 == 0)
pthread_cond_wait(&full_2, &mutex_2);
char line_char = buffer2[con_idx_2];
con_idx_2 = con_idx_2 + 1;
count_2--;
pthread_mutex_unlock(&mutex_2);
return line_char;
}
/* ******************************
* Function Name: set_buf_2
* Input: char
* Output: NA
* Desc: Sets the buffer2 at the current
* position to the char passed
****************************** */
void set_buf_2(char line_char){
pthread_mutex_lock(&mutex_2);
buffer2[prod_idx_2] = line_char;
prod_idx_2 = prod_idx_2 + 1;
count_2++;
pthread_cond_signal(&full_2);
pthread_mutex_unlock(&mutex_2);
}
/* ******************************
* Function Name: get_buf_3
* Input: NA
* Output: int
* Desc: Gets the next char from the buffer3
****************************** */
int get_buf_3(){
pthread_mutex_lock(&mutex_3);
while(count_3 == 0)
pthread_cond_wait(&full_3, &mutex_3);
char line_char = buffer3[con_idx_3];
con_idx_3 = con_idx_3 + 1;
count_3--;
pthread_mutex_unlock(&mutex_3);
return line_char;
}
/* ******************************
* Function Name: set_buf_3
* Input: char
* Output: NA
* Desc: Sets the buffer3 at the current
* position to the char passed
****************************** */
void set_buf_3(char line_char){
pthread_mutex_lock(&mutex_3);
buffer3[prod_idx_3] = line_char;
prod_idx_3 = prod_idx_3 + 1;
count_3++;
pthread_cond_signal(&full_3);
pthread_mutex_unlock(&mutex_3);
}
int char_num;
int line_nums;
int stopped = 0;
/* ******************************
* Function Name: input
* Input: void *
* Output: void *
* Desc: Takes the input from the user until a stop is reached
* splits the input into whether a file is open or not
****************************** */
void *input(void *args){
num_chars = 0;
int i = 0;
if(isatty(0)){
while(i != 50){
fgets(line_input, 1000, stdin);
if(!strcmp(line_input, "STOP\n")){
stopped = 1;
//Concatitnates an invisible character to indicicate the end of buffer
set_buf_1(27);
_Exit(1);
break;
}
for(int x = 0; x < strlen(line_input); x++){
set_buf_1(line_input[x]);
//num_chars++;
}
i++;
//line_nums++;
}
}
else{
while(fgets(line_input, 1000, stdin) != NULL && i != 50) {
if(!strcmp(line_input, "STOP\n")){
stopped = 1;
set_buf_1(27);
break;
}
for(int x = 0; x < strlen(line_input); x++){
set_buf_1(line_input[x]);
//num_chars++;
}
i++;
//line_nums++;
}
}
return NULL;
}
/* ******************************
* Function Name: line_separator
* Input: void *
* Output: void *
* Desc: When the line seperator gets the input from the buffer
* it sets the newlines to a space.
****************************** */
void *line_separator(void *args){
char tmp;
for(int i = 0; i < 50000; i++){
tmp = get_buf_1();
if(tmp == 27){
set_buf_2(27);
break;
}
if(tmp == '\n'){
line_nums++;
set_buf_2(' ');
continue;
}
set_buf_2(tmp);
}
return NULL;
}
/* ******************************
* Function Name: plus_sign
* Input: void *
* Output: void *
* Desc: When the plus_sign function gets the input
* from the buffer it sets the plus signs in groups
* of two to a carrot.
****************************** */
void *plus_sign(void *args){
int plus_num = 0;
char tmp;
for(int j = 0; j < 50000; j++){
tmp = get_buf_2();
if(tmp == 27){
set_buf_3(27);
break;
}
if(tmp == '+'){
plus_num++;
if(plus_num % 2 == 0){
set_buf_3('^');
}
}
else{
set_buf_3(tmp);
plus_num=0;
}
num_chars++;
}
return NULL;
}
/* ******************************
* Function Name: output
* Input: void *
* Output: void *
* Desc: prints the output from the buffer 3
* when it's recieved, every 80 lines it prints a newline
* The function will also only print when 80 lines is reached
****************************** */
void *output(void *args){
int j = 0;
char tmp;
for(int x = 0; x < 50; x++){
for(int i = 0; i < 80; i++){
tmp = get_buf_3();
fputc(tmp, stdout);
}
fputc('\n', stdout);
}
return NULL;
}
/* ******************************
* Function Name: main
* Input: NA
* Output: NA
* Desc: creates the 4 seperate threads for each of the functions
****************************** */
int main(){
pthread_create(&input_id, NULL, input, NULL);
pthread_create(&line_separator_id, NULL, line_separator, NULL);
pthread_create(&plus_sign_id, NULL, plus_sign, NULL);
pthread_create(&output_id, NULL, output, NULL);
pthread_join(input_id, NULL);
pthread_join(line_separator_id, NULL);
pthread_join(plus_sign_id, NULL);
pthread_join(output_id, NULL);
exit(1);
}