-
Notifications
You must be signed in to change notification settings - Fork 0
/
Lab8_Producer_Rewrite2.cpp
196 lines (140 loc) · 4.77 KB
/
Lab8_Producer_Rewrite2.cpp
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
#include <iostream>
#include <fstream>
#include <sstream>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <unistd.h>
using namespace std;
int main(int argc, char const *argv[]) {
//name of text file
string textFile = argv[1];
// Size of the shared memory in bytes.
// Preferably a power of 2
// This line of code assigns the size to be
// 1024 bytes or 1KB
int shmSize = atoi(argv[2]);
// -- Semaphore and Shared Memory Initialization --
// Semaphore set ID
int semID;
// Id for the shared memory
int shmID;
int fID;
// 1 key = 1 semaphore set (or array)
// Think of it like a map (the data structure)
// Put a large constant here, e.g. 1234
key_t semKey = 1234;
// 1 key = 1 shared memory segment
// Think of a map (the data structure)
key_t shmKey = 1234;
key_t fKey = 1235;
// Access file
ifstream myFile(textFile.c_str());
stringstream buffer;
buffer << myFile.rdbuf();
myFile.close();
string temp = buffer.str();
char *textFileContent = new char[temp.size() + 1];
copy(temp.begin(), temp.end(), textFileContent);
textFileContent[temp.size()] = '\0';
// Flags to use upon getting the semaphore set.
// Normally when dealing with flags, you usually bitwise-OR
// flags together.
// IPC_CREAT - If no existing semaphore set is associated with the key, create one
// 0666 - Remember chmod? The 0 in front specifies that the number is in octal
int semFlag = IPC_CREAT | 0666;
// Number of semaphores in the semaphore set
int nSems = 2;
// Attempt to get a semaphore set
// Returns -1 if there was an error.
semID = semget(semKey, nSems, semFlag);
if( semID == -1 ) {
perror( "semget" );
exit( 1 );
}
// Flags + permissions when creating the shared
// memory segment.
// IPC_CREAT - If the shared memory does not exist yet, automatically create it
// 0666 - Remember chmod? The 0 in front indicates that the number is expressed in octal.
int shmFlags = IPC_CREAT | 0666;
// Pointer for the starting address of the shared memory segment.
char* sharedMem;
int* f;
// Yes, this is almost the same as semget()
shmID = shmget(shmKey, shmSize, shmFlags);
// shmat() returns the starting address of the shared memory
// segment, so we assign it to sharedMem.
sharedMem = (char*) shmat(shmID, NULL, 0);
fID = shmget(fKey, 1, shmFlags);
f = (int*) shmat(fID, NULL, 0);
if( ((int*)sharedMem) == (int*)-1 || ((int*)f) == (int*)-1) {
perror( "shmop: shmat failed" );
} else {
int iterator = 0;
while (true) {
// -- Semaphore Accessing --
// Perform 4 operations
int nOperations = 4;
// Create an array of size 4 to hold
// the operations that we will do on the semaphore set
struct sembuf sema[nOperations];
// Definition for the first operation
// Our first operation will be to wait for the
// semaphore to become 0
sema[0].sem_num = 0; // Use the first semaphore in the semaphore set
sema[0].sem_op = 0; // Wait if semaphore != 0
sema[0].sem_flg = SEM_UNDO; // See slides
// Definition for the second operation
sema[1].sem_num = 0; // Use the first semaphore in the semaphore set
sema[1].sem_op = 1; // Increment semaphore by 1
sema[1].sem_flg = SEM_UNDO | IPC_NOWAIT; // See slides
// Definition for the third operation
sema[2].sem_num = 1; // Use the second semaphore in the semaphore set
sema[2].sem_op = 0; // Wait if semaphore != 0
sema[2].sem_flg = SEM_UNDO; // See slides
// Definition for the fourth operation
sema[3].sem_num = 1; // Use the second semaphore in the semaphore set
sema[3].sem_op = 1; // Increment semaphore by 1
sema[3].sem_flg = SEM_UNDO | IPC_NOWAIT;
// Perform the operations that we defined.
// Will return -1 on error.
int opResult = semop( semID, sema, nOperations );
if(opResult != -1) {
*f = 0;
// write to shared memory
strncpy(sharedMem, &textFileContent[iterator], shmSize);
sharedMem[shmSize] = '\0';
cout << sharedMem << endl;
iterator += shmSize;
// -- Semaphore Releasing --
// Set number of operations to 1
nOperations = 1;
// Modify the first operation such that it
// now decrements the semaphore.
sema[0].sem_num = 0; // Use the first semaphore in the semaphore set
sema[0].sem_op = -1; // Decrement semaphore by 1
sema[0].sem_flg = SEM_UNDO | IPC_NOWAIT;
opResult = semop( semID, sema, nOperations );
if(opResult == -1) {
perror("semop (decrement)");
}
} else {
perror("semop (increment)");
}
//To give the other program a chance to gain control of the semaphore
sleep(1);
if (iterator >= strlen(textFileContent)) {
break;
}
}
//Clean-up
delete[] textFileContent;
*f = 1;
}
cout << "Written" << endl;
return 0;
}