Recent Posts
Ruby | 2 sec ago
None | 17 sec ago
None | 25 sec ago
None | 29 sec ago
None | 34 sec ago
None | 42 sec ago
None | 59 sec ago
ASM (NASM) | 1 min ago
None | 1 min ago
None | 1 min ago
Sitereport
Find cool info about any domain on the internet?
visit sitereport
Free Subdomains
Want a pastebin.com sub-domain for your community?
learn more...
What is pastebin?
Pastebin is a website that hosts all your text & code on dedicated servers for easy sharing.
learn more...
Learn a little bit about the new Pastebin.com on our help page. hide message
By MrX on the 12th of Jun 2009 05:26:48 PM Download | Raw | Embed | Report
  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. #define PACKET_SIZE 1024
  15.  
  16. class CStopWatch
  17. {
  18.    private:
  19.       typedef struct {
  20.          timeval start;
  21.          timeval stop;
  22.       } stopWatch;
  23.       stopWatch timer;
  24.    public:
  25.       void startTimer( ) { gettimeofday(&(timer.start),0); }
  26.       void stopTimer( ) { gettimeofday(&(timer.stop),0); }
  27.       double getElapsedTime()
  28.       {
  29.          timeval res;
  30.          timersub(&(timer.stop),&(timer.start),&res);
  31.          return res.tv_sec + res.tv_usec/1000000.0;
  32.       }
  33. };
  34.  
  35. // Thread stuff
  36. int threadID;
  37. int threadPID;
  38. char threadStack[64*1024];
  39.  
  40. // Buffer
  41. struct timeval tm;
  42. volatile unsigned char *buffer1;
  43. volatile unsigned char *buffer2;
  44. volatile unsigned int *b1;
  45. volatile unsigned int *b2;
  46. volatile int rd2;
  47. volatile int rd1;
  48.  
  49. // Communication between threads.
  50. int pipe1[2];
  51. int pipe2[2];
  52.  
  53. // Write to pipe1
  54. // Read from pipe2
  55. int processfile(void *arg)
  56. {
  57.         struct timeval tm2;
  58.         fd_set fds2;
  59.         FD_ZERO(&fds2);
  60.         FD_SET(pipe2[0],&fds2);
  61.  
  62.   int count[256];
  63.   memset(count,0,256*sizeof(int));
  64.  
  65.   for(;;)
  66.   {
  67.         // Wait on pipe2
  68.         // Wait until data ready.
  69.         char d;
  70.         int st = read(pipe2[0],&d,1);
  71.         if (st!=1) return 2;
  72.        
  73.         if (d==0) return 2;
  74.         if (d==2) break;
  75.                
  76.         // Process input buffer.
  77.         int rdd = rd1;  // Read it in to avoid volatile property.
  78.                 int cnt = rdd>>2;
  79.                 unsigned int *ptr = (unsigned int*)b1;
  80.                 for(register int i=0;i<cnt;i++)
  81.                 {
  82.                 register int a = *ptr++;
  83.                 count[a&255]++;
  84.                 count[(a>>8)&255]++;
  85.                 count[(a>>16)&255]++;
  86.                 count[(a>>24)&255]++;
  87.                 }
  88.        
  89.         // Send that we are ready.
  90.         d = 1;
  91.           write(pipe1[1],&d,1);                        
  92.   }
  93.  
  94.         // Print the results.
  95.         int total = 0;
  96.         for(int i='A';i<='Z';i++)
  97.         {
  98.                 count[i]+=count[i-'A'+'a'];
  99.                 total+=count[i];
  100.         }
  101.         double dtotal = ((double)total)/100.0;
  102.         for(int i='A';i<='Z';i++)
  103.         {
  104.                 printf("%c: %.3f%% %d\n",(unsigned char)i,((double)count[i])/dtotal,count[i]);
  105.         }
  106.         printf("total: %d\n",total);
  107.        
  108.   return 0;
  109. }
  110.  
  111. int main(int argc, char **argv)
  112. {
  113.         clock_t const start = clock();
  114.         CStopWatch s;
  115.   s.startTimer();
  116.   // Check if filename given.
  117.   if (argc!=2)
  118.   {
  119.     printf("No filename.\n");
  120.     return 1;
  121.   }
  122.  
  123.         int pid;
  124.        
  125.         pipe(pipe1);
  126.         pipe(pipe2);
  127.  
  128.         memset(&tm,0,sizeof(timeval));
  129.  
  130.   // Spawn thread that will count the data.
  131.   threadID = 1;
  132.  
  133.   if (0!=pthread_create((pthread_t*)&pid,NULL,(void* (*)(void*))&processfile,(void*)&threadID))
  134.   {
  135.                 printf("Error creating thread.\n");
  136.     if (errno==EAGAIN)
  137.     {
  138.           printf("Too many processes.\n");
  139.     }
  140.     else if (errno==ENOMEM)
  141.     {
  142.         printf("Out of memory.\n");
  143.     }
  144.     return 4;
  145.   }
  146.   else
  147.   {
  148.     threadPID = pid;
  149.   }
  150.  
  151.   // Open file
  152.         int fd = open(argv[1], O_RDONLY, 0);
  153.   if (fd==-1)
  154.   {
  155.     printf("Cannot open file %s.\n",argv[1]);
  156.     char d = 0;
  157.     write(pipe2[1],&d,1);
  158.     int exitcode;
  159.     pthread_join(threadPID,(void**)&exitcode);
  160.     return 2;
  161.   }
  162.  
  163.   // fd_set for select()
  164.         fd_set fds,fds2;
  165.         FD_ZERO(&fds2);
  166.         FD_SET(pipe1[0],&fds2);
  167.  
  168.         unsigned int b1size;
  169.         unsigned int b2size;
  170.  
  171.   // Allocate memory to use for buffer.
  172.         const int maxreadsize = BUFFER_SIZE/PACKET_SIZE;
  173.   int gap = 1;     // how much to increase or deacrease read size * PACKET_SIZE bytes.
  174.   int lastdir = 1; // -1 is reduction in size.
  175.   int readsize = 1; // buffersize to load
  176.   unsigned char *buffer = new unsigned char[maxreadsize*PACKET_SIZE*2];
  177.         buffer1 = buffer;
  178.         buffer2 = buffer+(maxreadsize*PACKET_SIZE);
  179.         b1 = (unsigned int*)buffer;
  180.         b2 = (unsigned int*)buffer2;
  181.  
  182.         // start reading
  183.         b1size = readsize*PACKET_SIZE;
  184.         rd1 = read(fd, (void*)buffer1, b1size);
  185.         if (rd1==-1)
  186.         {
  187.                 // Read error
  188.                 close(fd);
  189.                 delete[] buffer;
  190.                 printf("Read error.\n");
  191.     char d = 0;
  192.     write(pipe2[1],&d,1);
  193.     int exitcode;
  194.     pthread_join(threadPID,(void**)&exitcode);
  195.                 return 3;
  196.         }
  197.  
  198.         // Send ok to read.
  199.         char d = rd1?1:2;
  200.         write(pipe2[1],&d,1);
  201.  
  202.   int lastread;
  203.         while(rd1 > 0)
  204.         {
  205.                 // Start reading next group
  206.                 b2size = readsize*PACKET_SIZE;
  207.                 rd2 = read(fd,(void*)buffer2,b2size);
  208.                 if (rd2==-1)
  209.                 {
  210.                         // Read error
  211.                         printf("Read error.\n");
  212.             char d = 0;
  213.           write(pipe2[1],&d,1);
  214.       int exitcode;
  215.       pthread_join(threadPID,(void**)&exitcode);
  216.                   close(pipe1[0]);
  217.                 close(pipe1[1]);
  218.                 close(pipe2[0]);
  219.                 close(pipe2[1]);
  220.                         close(fd);
  221.                         delete[] buffer;
  222.                         return 3;
  223.                 }
  224.                 // Blank end of buffer if necessary so that our stats don't get messed up.
  225.                 if (rd2&3)
  226.                 {
  227.                         int rd3 = 4-(rd2&3);
  228.                         for(int i=0;i<rd3;i++)
  229.                         {
  230.                                 buffer2[rd2+i] = '\0';
  231.                         }
  232.                         rd2+=4;
  233.                         rd2&=~3;
  234.                 }
  235.  
  236.         // Wait on pipe1
  237.         // Wait for buffer1 to be free.
  238.         bool increase = false;
  239.         fd_set fds = fds2;
  240.         struct timeval tm2 = tm;
  241.         int r = select(pipe1[0]+1,&fds,NULL,NULL,&tm2);
  242.         if (r<0)
  243.         {
  244.             char d = 0;
  245.           write(pipe2[1],&d,1);                
  246.           break;
  247.         }
  248.         if (r==0)
  249.         {
  250.                 // We have to wait.
  251.                 fds = fds2;
  252.                 int r = select(pipe1[0]+1,&fds,NULL,NULL,NULL);
  253.                 if (r<0)
  254.                 {
  255.                 char d = 0;
  256.                   write(pipe2[1],&d,1);                
  257.                   break;
  258.                 }              
  259.         }
  260.         else
  261.         {
  262.                 increase = true;
  263.         }
  264.        
  265.         // read
  266.         char d;
  267.         int st = read(pipe1[0],&d,1);          
  268.         if (st!=1)
  269.                 {
  270.                         // Pipe error
  271.                         printf("Pipe error.\n");
  272.             char d = 0;
  273.           write(pipe2[1],&d,1);
  274.       int exitcode;
  275.       pthread_join(threadPID,(void**)&exitcode);
  276.                   close(pipe1[0]);
  277.                 close(pipe1[1]);
  278.                 close(pipe2[0]);
  279.                 close(pipe2[1]);
  280.                         close(fd);
  281.                         delete[] buffer;
  282.                         return 3;
  283.                 }
  284.        
  285.         if (d==0) break;
  286.                
  287.                 // Swap buffers.
  288.                 unsigned char *b = (unsigned char*)buffer1;
  289.                 buffer1 = buffer2;
  290.                 buffer2 = b;
  291.                 unsigned int *bb = (unsigned int*)b1;
  292.                 b1 = b2;
  293.                 b2 = bb;
  294.                 unsigned int s = b1size;
  295.                 b1size = b2size;
  296.                 b2size = s;
  297.                 int rr = rd1;
  298.                 rd1 = rd2;
  299.                 rd2 = rr;
  300.                
  301.                 // report back that buffer1 is ready to be processed.
  302.                 d = rd1?1:2;
  303.                 write(pipe2[1],&d,1);
  304.                
  305.                 // Adjust gap size.
  306.                 if (increase)
  307.                 {
  308.                         if (rd1==readsize*PACKET_SIZE)
  309.                         {
  310.                                 if (lastdir!=1) {gap=1; lastdir = 1;}
  311.                                 else if (gap<0x40000000) gap<<=1;                      
  312.                                 readsize+=gap;
  313.                                 if (readsize>maxreadsize) readsize = maxreadsize;
  314.                         }
  315.                 }
  316.                 else
  317.                 {
  318.                         if (lastdir!=-1) {gap=1; lastdir = -1;}
  319.                         else if (gap<0x40000000) gap<<=1;                      
  320.                         readsize-=gap;
  321.                         if (readsize<1) readsize = 1;
  322.                 }
  323.         }
  324.  
  325.   int exitcode;
  326.   pthread_join(threadPID,(void**)&exitcode);
  327.  
  328.         delete[] buffer;
  329.   close(fd);
  330.   close(pipe1[0]);
  331.   close(pipe1[1]);
  332.   close(pipe2[0]);
  333.   close(pipe2[1]);
  334.        
  335.         s.stopTimer();
  336.         printf("Total runtime: %f seconds\n",s.getElapsedTime());
  337.        
  338.         clock_t const end = clock();
  339.         printf("Execution time only: %f seconds\n",(((double)end - (double)start) / CLOCKS_PER_SEC));
  340.   return 0;
  341. }
Submit a correction or amendment below. Make A New Post
To highlight particular lines, prefix each line with @h@
Syntax highlighting:
Post expiration:
Post exposure:
Name / Title:
Email: