Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdlib.h>
- #include <stdio.h>
- #include <pthread.h>
- #include <errno.h>
- #include <string.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include <time.h>
- int thread_quantity;
- int buffer_size;
- char *requested_file_name;
- char *requested_word;
- int file_des = 0;
- int created_threads = 0;
- int alive_threads;
- pthread_mutex_t reading_mutex = PTHREAD_MUTEX_INITIALIZER;
- pthread_t *thread_id = NULL;
- off_t file_size;
- pthread_key_t buffer;
- void usage() {
- exit(1);
- }
- void err_exit(char *);
- void* thread_function(void *);
- void clean_thread(void *);
- void clean_tsd_buffer(void *); //thread specific data
- //############################################################
- int main(int argc, char *argv[]) {
- int i;
- if (argc != 5) {
- usage();
- } else {
- thread_quantity = (int) strtol(argv[1], NULL, 10);
- alive_threads = thread_quantity;
- thread_id = malloc(sizeof(pthread_t) * thread_quantity);
- requested_file_name = argv[2];
- buffer_size = (int) strtol(argv[3], NULL, 10);
- if (errno) {
- usage();
- }
- requested_word = argv[4];
- }
- if ((file_des = open(requested_file_name, O_RDONLY)) == -1) {
- err_exit("Error: open(requested_file_name)");
- }
- if ((file_size = lseek(file_des, 0, SEEK_END)) == (off_t) -1) {
- err_exit("Error: lseek(file_des, 0, SEEK_END)");
- }
- if (lseek(file_des, 0, SEEK_SET) == (off_t) -1) {
- err_exit("Error: lseek(file_des, 0, SEEK_END)");
- }
- if (pthread_mutex_init(&reading_mutex, NULL) != 0) {
- err_exit("Error: pthread_mutex_init(reading_mutex)");
- }
- if (pthread_key_create(&buffer, clean_tsd_buffer)) {
- err_exit("Error: pthread_key_create()");
- }
- //=========================================================
- for (i = 0; i < thread_quantity; i++) {
- if (pthread_create(&thread_id[i], NULL, thread_function, NULL)) {
- err_exit("Error: pthread_create()");
- } else {
- created_threads++;
- }
- }
- while (alive_threads) {
- usleep(1000);
- }
- for (i = 0; i < thread_quantity; i++) {
- if (pthread_join(thread_id[i], NULL)) {
- err_exit("Error: pthread_join()");
- }
- }
- //=========================================================
- err_exit(NULL);
- return EXIT_SUCCESS;
- }
- //############################################################
- void clean_tsd_buffer(void *arg) {
- if (arg != NULL) {
- free(arg);
- }
- }
- void clean_thread(void *arg) {
- alive_threads--;
- }
- //-----------------------------------------------------------
- void *thread_function(void *data) {
- pthread_cleanup_push(clean_thread, NULL);
- if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
- err_exit("Error: pthread_setcanceltype()");
- }
- if (pthread_setspecific(buffer, malloc(sizeof(char) * buffer_size))) {
- err_exit("Error: pthread_setspecific()");
- }
- int i, bytes_readed;
- off_t jump, current_offset;
- void *cbuffer = pthread_getspecific(buffer);
- for (i = 0; i < thread_quantity; i++) {
- if (pthread_equal(pthread_self(), thread_id[i])) {
- jump = (off_t) i * buffer_size;
- break;
- }
- }
- //==========================================================
- while (1) {
- if (pthread_mutex_lock(&reading_mutex) != 0) {
- err_exit("Error: pthread_mutex_lock(reading_mutex)");
- }
- if ((current_offset = lseek(file_des, jump, SEEK_SET)) == (off_t) -1) {
- err_exit("Error: lseek(reading_mutex)");
- }
- if (current_offset > file_size) {
- if (pthread_mutex_unlock(&reading_mutex) != 0) {
- err_exit("Error: pthread_mutex_unlock(reading_mutex)");
- }
- if (pthread_cancel(pthread_self())) {
- err_exit("Error: pthread_cancel()");
- }
- } else {
- bytes_readed = read(file_des, cbuffer, buffer_size);
- }
- if (pthread_mutex_unlock(&reading_mutex) != 0) {
- err_exit("Error: pthread_mutex_unlock(reading_mutex)");
- }
- usleep(50);
- if (bytes_readed > 0) {
- //no, don't need that code
- } else if (!bytes_readed) {
- if (pthread_cancel(pthread_self())) {
- err_exit("Error: pthread_cancel()");
- }
- } else { // Error
- err_exit("Error: czytanie z pliku w wątku");
- }
- jump += thread_quantity * buffer_size;
- }
- //==========================================================
- pthread_cleanup_pop(1);
- if (pthread_cancel(pthread_self())) {
- err_exit("Error: pthread_cancel()");
- }
- return data;
- }
- //-----------------------------------------------------------
- void err_exit(char *msg) {
- if (msg != NULL) {
- perror(msg);
- sleep(10);
- }
- if (file_des != 0) {
- if (close(file_des) == -1) {
- perror("Error: close(file_des)");
- }
- }
- if (thread_id != NULL) {
- free(thread_id);
- }
- exit(1);
- }
- /////////////////////////////////////####################### test.txt #################
- The pthread_cleanup_push() function pushes routine onto the top of the
- stack of clean-up handlers. When routine is later invoked, it will be
- given arg as its clean argument.
- The pthread_cleanup_pop() function removes the routine at the top of
- the stack of clean-up handlers, and optionally executes it if execute
- is nonzero.
- A cancellation clean-up handler is popped from the stack and executed
- in the following circumstances:
- 1. When a thread is canceled, all of the stacked clean-up handlers are
- popped and executed in the reverse of the order in which they were
- pushed onto the stack.
- 2. When a thread terminates by calling pthread_exit(3), all clean-up
- handlers are executed as described in the preceding point. (Clean-
- up handlers are not called if the thread terminates by performing a
- return from the thread start function.) clean
- 3. When a thread calls pthread_cleanup_pop() with a nonzero execute
- argument, the top-mst clean-up handler is popped and executed.
- POSIX.1 permits pthread_cleanup_push() and pthread_cleanup_pop() to be
- implemented as macros that expand to text containing '{' and '}',
- respectively. For this reason, the caller must ensure that call
Advertisement
Add Comment
Please, Sign In to add comment