View difference between Paste ID: vxWnqttB and TrskKWYA
SHOW: | | - or go back to the newest paste.
1
int thread_quantity;
2
int buffer_size;
3
char *requested_file_name;
4
char *requested_word;
5
6
int file_des = 0;
7
int created_threads = 0;
8
int alive_threads;
9
10
pthread_mutex_t reading_mutex = PTHREAD_MUTEX_INITIALIZER;
11
pthread_t *thread_id = NULL;
12
off_t file_size;
13
pthread_key_t buffer;
14
15-
void usage();
15+
void usage() {
16
exit(1);
17
}
18
void err_exit(char *);
19
void* thread_function(void *);
20
void clean_thread(void *);
21
void clean_tsd_buffer(void *); //thread specific data
22
//############################################################
23
int main(int argc, char *argv[]) {
24
	int i;
25
	if (argc != 5) {
26
		usage();
27
	} else {
28
		thread_quantity = (int) strtol(argv[1], NULL, 10);
29
		alive_threads = thread_quantity;
30
		thread_id = malloc(sizeof(pthread_t) * thread_quantity);
31
		requested_file_name = argv[2];
32
		buffer_size = (int) strtol(argv[3], NULL, 10);
33
		if (errno) {
34
			usage();
35
		}
36
		requested_word = argv[4];
37
	}
38
	if ((file_des = open(requested_file_name, O_RDONLY)) == -1) {
39
		err_exit("Error: open(requested_file_name)");
40
	}
41
	if ((file_size = lseek(file_des, 0, SEEK_END)) == (off_t) -1) {
42
		err_exit("Error: lseek(file_des, 0, SEEK_END)");
43
	}
44
	if (lseek(file_des, 0, SEEK_SET) == (off_t) -1) {
45
		err_exit("Error: lseek(file_des, 0, SEEK_END)");
46
	}
47
	if (pthread_mutex_init(&reading_mutex, NULL) != 0) {
48
		err_exit("Error: pthread_mutex_init(reading_mutex)");
49
	}
50
	if (pthread_key_create(&buffer, clean_tsd_buffer)) {
51
		err_exit("Error: pthread_key_create()");
52
	}
53
	//=========================================================
54
	for (i = 0; i < thread_quantity; i++) {
55
		if (pthread_create(&thread_id[i], NULL, thread_function, NULL)) {
56
			err_exit("Error: pthread_create()");
57
		} else {
58
			created_threads++;
59
		}
60
	}
61
	while (alive_threads) {
62
		usleep(1000);
63
	}
64
	for (i = 0; i < thread_quantity; i++) {
65
		if (pthread_join(thread_id[i], NULL)) {
66
			err_exit("Error: pthread_join()");
67
		}
68
	}
69
	//=========================================================
70
	err_exit(NULL);
71
	return EXIT_SUCCESS;
72
}
73
//############################################################
74
void clean_tsd_buffer(void *arg) {
75
	if (arg != NULL) {
76
		free(arg);
77
	}
78
}
79
void clean_thread(void *arg) {
80
	alive_threads--;
81
}
82
//-----------------------------------------------------------
83
void *thread_function(void *data) {
84
	pthread_cleanup_push(clean_thread, NULL);
85
				if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
86
					err_exit("Error: pthread_setcanceltype()");
87
				}
88
				if (pthread_setspecific(buffer, malloc(sizeof(char) * buffer_size))) {
89
					err_exit("Error: pthread_setspecific()");
90
				}
91
				int i, bytes_readed;
92
				off_t jump, current_offset;
93
				void *cbuffer = pthread_getspecific(buffer);
94
				for (i = 0; i < thread_quantity; i++) {
95
					if (pthread_equal(pthread_self(), thread_id[i])) {
96
						jump = (off_t) i * buffer_size;
97
						break;
98
					}
99
				}
100
				//==========================================================
101
				while (1) {
102
					if (pthread_mutex_lock(&reading_mutex) != 0) {
103
						err_exit("Error: pthread_mutex_lock(reading_mutex)");
104
					}
105
					if ((current_offset = lseek(file_des, jump, SEEK_SET)) == (off_t) -1) {
106
						err_exit("Error: lseek(reading_mutex)");
107
					}
108
					if (current_offset > file_size) {
109
						if (pthread_mutex_unlock(&reading_mutex) != 0) {
110
							err_exit("Error: pthread_mutex_unlock(reading_mutex)");
111
						}
112
						if (pthread_cancel(pthread_self())) {
113
							err_exit("Error: pthread_cancel()");
114
						}
115
					} else {
116
						bytes_readed = read(file_des, cbuffer, buffer_size);
117
					}
118
					if (pthread_mutex_unlock(&reading_mutex) != 0) {
119
						err_exit("Error: pthread_mutex_unlock(reading_mutex)");
120
					}
121
					usleep(50);
122
					if (bytes_readed > 0) {
123
                        //no, don't need that code
124
					} else if (!bytes_readed) {
125
						if (pthread_cancel(pthread_self())) {
126
							err_exit("Error: pthread_cancel()");
127
						}
128
					} else { // Error
129
						err_exit("Error: czytanie z pliku w wÄ…tku");
130
					}
131
					jump += thread_quantity * buffer_size;
132
				}
133
				//==========================================================
134
				pthread_cleanup_pop(1);
135
	if (pthread_cancel(pthread_self())) {
136
		err_exit("Error: pthread_cancel()");
137
	}
138
	return data;
139
}
140
//-----------------------------------------------------------
141
void err_exit(char *msg) {
142
	if (msg != NULL) {
143
		perror(msg);
144
		sleep(10);
145
	}
146
	if (file_des != 0) {
147
		if (close(file_des) == -1) {
148
			perror("Error: close(file_des)");
149
		}
150
	}
151
	if (thread_id != NULL) {
152
		free(thread_id);
153
	}
154
	exit(1);
155
}
156
157
158
159
160
161
162
/////////////////////////////////////####################### test.txt #################
163
The pthread_cleanup_push() function pushes routine onto the top of  the
164
       stack  of clean-up handlers.  When routine is later invoked, it will be
165
       given arg as its clean argument.
166
       The pthread_cleanup_pop() function removes the routine at  the  top  of
167
       the  stack  of clean-up handlers, and optionally executes it if execute
168
       is nonzero. 
169
170
       A cancellation clean-up handler is popped from the stack  and  executed
171
       in the following circumstances:
172
173
       1. When  a thread is canceled, all of the stacked clean-up handlers are
174
          popped and executed in the reverse of the order in which  they  were
175
          pushed onto the stack.
176
177
       2. When  a  thread  terminates by calling pthread_exit(3), all clean-up
178
          handlers are executed as described in the preceding point.   (Clean-
179
          up  handlers are not called if the thread terminates by performing a
180
          return from the thread start function.) clean
181
182
       3. When a thread calls pthread_cleanup_pop()  with  a  nonzero  execute
183
          argument, the top-mst clean-up handler is popped and executed.
184
185
       POSIX.1  permits pthread_cleanup_push() and pthread_cleanup_pop() to be
186
       implemented as macros that expand  to  text  containing  '{'  and  '}',
187
       respectively.   For  this  reason, the caller must ensure that call