Share Pastebin
Guest
Public paste!

MrX

By: a guest | Jun 13th, 2009 | Syntax: None | Size: 5.80 KB | Hits: 41 | Expires: Never
This paste has a previous version, view the difference. Copy text to clipboard
  1. // Compile with -lpthread
  2. // Written by Cléo Saulnier
  3. #include <stdio.h>
  4. #include <unistd.h>
  5. #include <sys/wait.h>
  6. #include <fcntl.h>
  7. #include <string.h>
  8. #include <pthread.h>
  9. #include <errno.h>
  10. #include <sys/time.h>
  11.  
  12. #define BUFFER_SIZE 32*1024
  13.  
  14. class CStopWatch
  15. {
  16.    private:
  17.       typedef struct {
  18.          timeval start;
  19.          timeval stop;
  20.       } stopWatch;
  21.       stopWatch timer;
  22.    public:
  23.       void startTimer( ) { gettimeofday(&(timer.start),0); }
  24.       void stopTimer( ) { gettimeofday(&(timer.stop),0); }
  25.       double getElapsedTime()
  26.       {
  27.          timeval res;
  28.          timersub(&(timer.stop),&(timer.start),&res);
  29.          return res.tv_sec + res.tv_usec/1000000.0;
  30.       }
  31. };
  32.  
  33. // Thread stuff
  34. int threadID;
  35. int threadPID;
  36. char threadStack[64*1024];
  37.  
  38. // Buffer
  39. struct timeval tm;
  40. volatile unsigned char *buffer1;
  41. volatile unsigned char *buffer2;
  42. volatile unsigned int *b1;
  43. volatile unsigned int *b2;
  44. volatile int rd2;
  45. volatile int rd1;
  46.  
  47. // Communication between threads.
  48. int pipe1[2];
  49. int pipe2[2];
  50.  
  51. // Write to pipe1
  52. // Read from pipe2
  53. int processfile(void *arg)
  54. {
  55.   struct timeval tm2;
  56.   fd_set fds2;
  57.   FD_ZERO(&fds2);
  58.   FD_SET(pipe2[0],&fds2);
  59.  
  60.   int count[256];
  61.   memset(count,0,256*sizeof(int));
  62.  
  63.   for(;;)
  64.   {
  65.     // Wait on pipe2
  66.     // Wait until data ready.
  67.     char d;
  68.     int st = read(pipe2[0],&d,1);
  69.     if (st!=1) return 2;
  70.        
  71.     if (d==0) return 2;
  72.     if (d==2) break;
  73.                
  74.     // Process input buffer.
  75.     int rdd = rd1;  // Read it in to avoid volatile property.
  76.     int cnt = rdd>>2;
  77.     unsigned int *ptr = (unsigned int*)b1;
  78.     for(register int i=0;i<cnt;i++)
  79.     {
  80.       register int a = *ptr++;
  81.       count[a&255]++;
  82.       count[(a>>8)&255]++;
  83.       count[(a>>16)&255]++;
  84.       count[(a>>24)&255]++;
  85.     }
  86.        
  87.     // Send that we are ready.
  88.     d = 1;
  89.     write(pipe1[1],&d,1);                      
  90.   }
  91.  
  92.   // Print the results.
  93.   int total = 0;
  94.   for(int i='A';i<='Z';i++)
  95.   {
  96.     count[i]+=count[i-'A'+'a'];
  97.     total+=count[i];
  98.   }
  99.   double dtotal = ((double)total)/100.0;
  100.   for(int i='A';i<='Z';i++)
  101.   {
  102.     printf("%c: %.3f%% %d\n",(unsigned char)i,((double)count[i])/dtotal,count[i]);
  103.   }
  104.   printf("total: %d\n",total);
  105.        
  106.   return 0;
  107. }
  108.  
  109. int main(int argc, char **argv)
  110. {
  111.   clock_t const start = clock();
  112.   CStopWatch s;
  113.   s.startTimer();
  114.   // Check if filename given.
  115.   if (argc!=2)
  116.   {
  117.     printf("No filename.\n");
  118.     return 1;
  119.   }
  120.  
  121.   int pid;
  122.        
  123.   pipe(pipe1);
  124.   pipe(pipe2);
  125.  
  126.   memset(&tm,0,sizeof(timeval));
  127.  
  128.   // Spawn thread that will count the data.
  129.   threadID = 1;
  130.  
  131.   if (0!=pthread_create((pthread_t*)&pid,NULL,(void* (*)(void*))&processfile,(void*)&threadID))
  132.   {
  133.     printf("Error creating thread.\n");
  134.     if (errno==EAGAIN)
  135.     {
  136.       printf("Too many processes.\n");
  137.     }
  138.     else if (errno==ENOMEM)
  139.     {
  140.       printf("Out of memory.\n");
  141.     }
  142.     return 4;
  143.   }
  144.   else
  145.   {
  146.     threadPID = pid;
  147.   }
  148.  
  149.   // Open file
  150.   int fd = open(argv[1], O_RDONLY, 0);
  151.   if (fd==-1)
  152.   {
  153.     printf("Cannot open file %s.\n",argv[1]);
  154.     char d = 0;
  155.     write(pipe2[1],&d,1);
  156.     int exitcode;
  157.     pthread_join(threadPID,(void**)&exitcode);
  158.     return 2;
  159.   }
  160.  
  161.   // fd_set for select()
  162.   fd_set fds,fds2;
  163.   FD_ZERO(&fds2);
  164.   FD_SET(pipe1[0],&fds2);
  165.  
  166.   // Allocate memory to use for buffer.
  167.   unsigned char *buffer = new unsigned char[(BUFFER_SIZE)*2];
  168.   buffer1 = buffer;
  169.   buffer2 = buffer+(BUFFER_SIZE);
  170.   b1 = (unsigned int*)buffer;
  171.   b2 = (unsigned int*)buffer2;
  172.  
  173.   // start reading
  174.   rd1 = read(fd, (void*)buffer1, BUFFER_SIZE);
  175.   if (rd1==-1)
  176.   {
  177.     // Read error
  178.     close(fd);
  179.     delete[] buffer;
  180.     printf("Read error.\n");
  181.     fflush(stdout);
  182.     char d = 0;
  183.     write(pipe2[1],&d,1);
  184.     int exitcode;
  185.     pthread_join(threadPID,(void**)&exitcode);
  186.     return 3;
  187.   }
  188.  
  189.   // Send ok to read.
  190.   char d = rd1?1:2;
  191.   write(pipe2[1],&d,1);
  192.  
  193.   while(rd1 > 0)
  194.   {
  195.     // Start reading next group
  196.     rd2 = read(fd,(void*)buffer2,BUFFER_SIZE);
  197.     if (rd2==-1)
  198.     {
  199.       // Read error
  200.       printf("Read error.\n");
  201.       char d = 0;
  202.       write(pipe2[1],&d,1);
  203.       int exitcode;
  204.       pthread_join(threadPID,(void**)&exitcode);
  205.       close(pipe1[0]);
  206.       close(pipe1[1]);
  207.       close(pipe2[0]);
  208.       close(pipe2[1]);
  209.       close(fd);
  210.       delete[] buffer;
  211.       return 3;
  212.     }
  213.     // Blank end of buffer if necessary so that our stats don't get messed up.
  214.     if (rd2&3)
  215.     {
  216.       int rd3 = 4-(rd2&3);
  217.       for(int i=0;i<rd3;i++)
  218.       {
  219.         buffer2[rd2+i] = '\0';
  220.       }
  221.       rd2+=4;
  222.       rd2&=~3;
  223.     }
  224.  
  225.     // read
  226.     char d;
  227.     int st = read(pipe1[0],&d,1);              
  228.     if (st!=1)
  229.     {
  230.       // Pipe error
  231.       printf("Pipe error.\n");
  232.       fflush(stdout);
  233.       char d = 0;
  234.       write(pipe2[1],&d,1);
  235.       int exitcode;
  236.       pthread_join(threadPID,(void**)&exitcode);
  237.       close(pipe1[0]);
  238.       close(pipe1[1]);
  239.       close(pipe2[0]);
  240.       close(pipe2[1]);
  241.       close(fd);
  242.       delete[] buffer;
  243.       return 3;
  244.     }
  245.        
  246.     if (d==0) break;
  247.                
  248.     // Swap buffers.
  249.     unsigned char *b = (unsigned char*)buffer1;
  250.     buffer1 = buffer2;
  251.     buffer2 = b;
  252.     unsigned int *bb = (unsigned int*)b1;
  253.     b1 = b2;
  254.     b2 = bb;
  255.     int rr = rd1;
  256.     rd1 = rd2;
  257.     rd2 = rr;
  258.                
  259.     // report back that buffer1 is ready to be processed.
  260.     d = rd1?1:2;
  261.     write(pipe2[1],&d,1);
  262.   }
  263.  
  264.   int exitcode;
  265.   pthread_join(threadPID,(void**)&exitcode);
  266.  
  267.   delete[] buffer;
  268.   close(fd);
  269.   close(pipe1[0]);
  270.   close(pipe1[1]);
  271.   close(pipe2[0]);
  272.   close(pipe2[1]);
  273.        
  274.   s.stopTimer();
  275.   printf("Total runtime: %f seconds\n",s.getElapsedTime());
  276.        
  277.   clock_t const end = clock();
  278.   printf("Execution time only: %f seconds\n",(((double)end - (double)start) / CLOCKS_PER_SEC));
  279.  
  280.   return 0;
  281. }