Advertisement
Guest User

Untitled

a guest
Dec 16th, 2018
73
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 3.66 KB | None | 0 0
  1. /*
  2. Author: Aleksi Kuznetsov
  3. C-program for run-length-encoding/decoding multithreaded
  4. */
  5.  
  6. #include <stdio.h>
  7. #include <stdlib.h> // exit() and malloc()
  8. #include <stdint.h> // uint_32
  9. #include <limits.h> // UINT_MAX
  10. #include <sys/sysinfo.h> // get_nprocs()
  11. #include <sys/stat.h> // fstat()
  12. #include <sys/mman.h> // mmap()
  13. #include <fcntl.h> // open()
  14. #include <unistd.h> // read()
  15. #include <pthread.h> // threads
  16. #include <math.h> // round()
  17.  
  18. // Struct to store a character and how many times it repeats
  19. typedef struct buffered_write {
  20.     int repeat;
  21.     char character;
  22.     struct buffered_write *next;
  23. } bw, *bw_ptr;
  24.  
  25. // Struct for arg to threads
  26. typedef struct _myarg_t {
  27.     bw_ptr ptr;
  28.     char * adr;
  29.     int length;
  30. } myarg_t;
  31.  
  32. void compress_file(bw_ptr ptr) {
  33.     while (ptr != NULL) {
  34.         int count = ptr->repeat;
  35.         char character = ptr->character;
  36.  
  37.         (void)write(STDERR_FILENO,&character,1);
  38.  
  39.         fwrite(&count, 1, 4, stdout);
  40.         fwrite(&character, 1, 1, stdout);
  41.  
  42.         ptr = ptr->next;
  43.     }
  44. }
  45.  
  46. void freeList(bw_ptr root) {
  47.     bw_ptr tmp;
  48.  
  49.     while (root != NULL) {
  50.         tmp = root;
  51.         root = root->next;
  52.         free(tmp);
  53.     }
  54. }
  55.  
  56. void read_from_file(bw_ptr ptr, char * adr, int length) {
  57.     unsigned int count = 1;
  58.     char ch = adr[0];
  59.     char ch_last = adr[0];
  60.  
  61.     ptr->repeat = count;
  62.     ptr->character = ch;
  63.  
  64.  
  65.     for (int i = 1; i < length; i++) {
  66.         char ch = adr[i];
  67.         if (ch == ch_last) {
  68.             count++;
  69.  
  70.             ptr->repeat = count;
  71.         }
  72.         if (ch != ch_last) {
  73.             count = 1;
  74.             ptr->next = malloc(sizeof(bw));
  75.             if (ptr->next == NULL) {
  76.                 exit(1);
  77.             }
  78.             ptr = ptr->next;
  79.             ptr->repeat = count;
  80.             ptr->character = adr[i];
  81.             ptr->next = NULL;
  82.         }
  83.         ch_last = ch;
  84.     }
  85.  
  86.     if (count == UINT_MAX) {
  87.         ptr = ptr->next;
  88.         count = 1;
  89.     }
  90. }
  91.  
  92. void *mythread(void *arg) {
  93.     myarg_t *m = (myarg_t *)arg;
  94.     read_from_file(m->ptr, m->adr, m->length);
  95.     return NULL;
  96. }
  97.  
  98. int main(int argc, char **argv) {
  99.     if (argc != 2) {
  100.         fprintf(stderr, "Wrong amount of arguments.\n");
  101.         exit(1);
  102.     }
  103.  
  104.     // Get threads, init file stats and addresses
  105.     int num_of_threads = get_nprocs();
  106.     struct stat buffer;
  107.     int fd;
  108.     char *addr;
  109.  
  110.     // Open file
  111.     fd = open(argv[1], O_RDONLY);
  112.     if (fd == -1) {
  113.         exit(1);
  114.     }
  115.     // Get file size
  116.     if (fstat(fd, &buffer) == -1) {
  117.         exit(1);
  118.     }
  119.     // Memory map the file contents
  120.     addr = mmap(NULL, buffer.st_size, PROT_READ,
  121.                        MAP_PRIVATE, fd, 0);
  122.     if (addr == MAP_FAILED) {
  123.         exit(1);
  124.     }
  125.  
  126.     // Buffers
  127.     bw_ptr buffers[num_of_threads];
  128.     // Offset so we can divide the workload to several threads
  129.     int offset = round(buffer.st_size / num_of_threads);
  130.     // Thread container
  131.     pthread_t thread_container[num_of_threads];
  132.  
  133.     for (int i = 0; i < num_of_threads; i++) {
  134.         // Create struct for buffering input
  135.         bw *x_ptr = NULL;
  136.         x_ptr = malloc(sizeof(bw));
  137.         if (x_ptr == NULL) {
  138.             exit(1);
  139.         }
  140.         // Here we add to struct pointer array so we can iterate it later when writing output
  141.         buffers[i] = x_ptr;
  142.  
  143.         // Write to the buffer and add to thread_container
  144.         myarg_t args;
  145.         args.ptr = x_ptr;
  146.         args.adr = addr + offset * i;
  147.         args.length = offset;
  148.         pthread_create(thread_container+i, NULL, mythread, &args);
  149.     }
  150.  
  151.     // Join threads
  152.     for (int i = 0; i < num_of_threads; i++) {
  153.         pthread_join(thread_container[i], NULL);
  154.     }
  155.  
  156.     // Collect the data and write to stdout
  157.     for (int i = 0; i < num_of_threads; i++) {
  158.         compress_file(buffers[i]);
  159.     }
  160.  
  161.     // Free memory from linked list and mmap under
  162.     for (int i = 0; i < num_of_threads; i++) {
  163.         freeList(buffers[i]);
  164.     }
  165.  
  166.     munmap(addr, buffer.st_size);
  167.  
  168.     return 0;
  169. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement