Guest User

Untitled

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