Pastebin launched a little side project called VERYVIRAL.com, check it out ;-) Want more features on Pastebin? Sign Up, it's FREE!
Guest

pthread_problem

By: a guest on Apr 3rd, 2011  |  syntax: C  |  size: 7.47 KB  |  views: 74  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <time.h>
  4. #include <errno.h>
  5. #include <pthread.h>
  6. #include <unistd.h>
  7. #include <string.h>
  8.  
  9. // number of threads, for monitoring actions.
  10. #define NTHREAD 3
  11.  
  12. // path, where to store files, with result of action# work
  13. const char path[] = "/home/zythar";
  14.  
  15. // main working structure
  16.  
  17. /*
  18.         kinda dummy. in real program this is replaced with real functions.
  19. */
  20. struct server_t {
  21.     char *name;
  22.  
  23.     int (*triggered)(struct server_t *);  // event, thar is monitored
  24.     int (*action)(struct server_t *);      // action taken, when event triggered
  25. };
  26.  
  27. typedef struct server_t server_t;
  28.  
  29. /* structs for threads */
  30. typedef struct act_threads {
  31.         pthread_t tid;
  32.         char *servername;
  33. } act_threads_t;
  34.  
  35. typedef struct act_checker {
  36.         act_threads_t **actions;
  37.         int count;
  38. } act_checker_t;
  39.  
  40. /* structs for threads */  //END
  41.  
  42. // function that is called, when action completed. it takes value, that action func returned, and write it to file named thread_#thread_id#
  43.  
  44. int return_thread(pthread_t tid, int retval)
  45. {
  46.         FILE *thread;
  47.         char *fullpath;
  48.         fullpath = (char *) malloc((strlen(path) + strlen("thread_") + 12) * sizeof(char));
  49.         snprintf(fullpath, strlen(path) + strlen("thread_") + 12, "%s/thread_%lu", path, tid);
  50.         thread = fopen(fullpath, "w");
  51.  
  52.         if (thread != NULL) {
  53.                 printf("%s created successfully\n", fullpath);
  54.                 fprintf(thread, "%d", retval);
  55.  
  56.                 fclose(thread);
  57.         } else {
  58.                 printf("Cannot create file for thread #%lu.\n", tid);
  59.                 printf("Exiting...\n");
  60.                 exit(0);
  61.         }
  62.  
  63.         free(fullpath);
  64.  
  65.         return 0;
  66.  
  67. }
  68.  
  69. /* dummy funcs for events and actions */
  70.  
  71. int triggered1(struct server_t * server)
  72. {
  73.         if  (time(NULL) % 5 == 0) {
  74.                 return 0;
  75.         } else {
  76.                 return -1;
  77.         }
  78. }
  79.  
  80. int triggered2(struct server_t * server)
  81. {
  82.         if  (time(NULL) % 13 == 0) {
  83.                 return 0;
  84.         } else {
  85.                 return -1;
  86.         }
  87. }
  88.  
  89. int triggered3(struct server_t * server)
  90. {
  91.         if  (time(NULL) % 17 == 0) {
  92.                 return 0;
  93.         } else {
  94.                 return -1;
  95.         }
  96. }
  97.  
  98. int action1(struct server_t * server)
  99. {
  100.         static int called_times;
  101.         called_times = ( called_times > 0) ? called_times : 0;
  102.         called_times++;
  103.         int i = 0;
  104.  
  105.         while (i < 17) {
  106.                 i++;
  107.                 sleep(1);
  108.         }
  109.  
  110.         return_thread(pthread_self(), 0);
  111.         pthread_exit(NULL);
  112.         return 0;
  113. }
  114.  
  115. int action2(struct server_t * server)
  116. {
  117.         static int called_times;
  118.         called_times = ( called_times > 0) ? called_times : 0;
  119.         called_times++;
  120.         int i = 0;
  121.  
  122.         while (i < 41) {
  123.                 i++;
  124.                 sleep(1);
  125.         }
  126.  
  127.         return_thread(pthread_self(), 0);
  128.         pthread_exit(NULL);
  129.         return 0;
  130. }
  131.  
  132. int action3(struct server_t * server)
  133. {
  134.         static int called_times;
  135.         called_times = ( called_times > 0) ? called_times : 0;
  136.         called_times++;
  137.         int i = 0;
  138.  
  139.         while (i < 10) {
  140.                 i++;
  141.                 sleep(1);
  142.         }
  143.  
  144.         return_thread(pthread_self(), 0);
  145.         pthread_exit(NULL);
  146.         return 0;
  147. }
  148.  
  149. /* dummy funcs for events and actions */ //END
  150.  
  151. /*int print_struct(act_checker_t *checker)
  152. {
  153.         if (checker->count <= 0)
  154.                 return -1;
  155.  
  156.         int i;
  157.         for (i = 0; i < checker->count; i++)
  158.                 printf("\t%d-th element. tid -- %lu\n", i, checker->actions[i]->tid);
  159.  
  160.         printf("\n\n");
  161.  
  162.         return 1;
  163. }*/
  164.  
  165. // mutex, that is locked, when trying to modify struct checker
  166. pthread_mutex_t checker_mutex;
  167.  
  168.  
  169. // func, that checks if actions are completed, and if they are free space allocated for particular action
  170. void * check_threads(act_checker_t *checker)
  171. {
  172.         printf("\n\n\t\tin %s\n\n", __FUNCTION__);
  173.         FILE *thread;
  174.         char *fullpath;
  175.         int i; int status; int mut;
  176.         fullpath = (char *) malloc((strlen(path) + strlen("thread_") + 12) * sizeof(char));  // path, where files are stored
  177.  
  178.         while (1) {
  179.  
  180.                 // trying to lock mutex for modifying @checker. if not succeded try again, until lock is successfull.
  181.                 while (1) {
  182.                         mut = pthread_mutex_trylock (&checker_mutex);
  183.                         if (mut == 0 || mut == EDEADLK) {       //if okay, or we own the lock then continue
  184.                                 break;
  185.                         } else {
  186.                                 sleep(3);
  187.                         }
  188.                 }
  189.  
  190.                 // if no elements,  then nothing to do. free mutex for others.
  191.  
  192.                 if (checker->count <= 0) {
  193.                         pthread_mutex_unlock (&checker_mutex);
  194.                         continue;
  195.                 }
  196.  
  197.                 // there are elements. check if threads completed, and if they are delete files and free alocated space for that thread
  198.  
  199.                 for (i = 0; i < checker->count; i++) {
  200.                         snprintf(fullpath, strlen(path) + strlen("thread_") + 12, "%s/thread_%lu", path, checker->actions[i]->tid);
  201.                         thread = fopen(fullpath, "r");
  202.                         if (thread == NULL) {   // if no such file, then thread not completed. continue to another thread.
  203.                                 continue;
  204.                         } else {
  205.                                 fscanf(thread, "%d", &status);          // thread completed. read returned value and...
  206.                                 fclose(thread);                        
  207.                                 if (remove(fullpath) == 0) {            // delete file.
  208.                                         printf("%s removed successfully\n", fullpath);
  209.                                 } else {
  210.                                         printf("Cannot remove file for thread #%lu.\n", checker->actions[i]->tid);
  211.                                         printf("Exiting...\n");
  212.                                         exit(0);
  213.                                 }
  214.  
  215.                                 free(checker->actions[i]); --checker->count;  // free alocated memory for that thread.
  216.                         }
  217.                 }
  218.  
  219.                 pthread_mutex_unlock (&checker_mutex);
  220.                 sleep(1);
  221.         }
  222.  
  223.         free(fullpath);
  224.  
  225. }
  226.  
  227. // func, for creating thread for concrete action.
  228.  
  229. void create_action_thread(act_checker_t *checker, server_t *server)
  230. {
  231.         int actret; int mut;
  232.         printf("\n\n\t\tin %s\n\n", __FUNCTION__);
  233.  
  234.         // locking mutex, because trying to modify @checker. until mutex locked don't do anything.
  235.  
  236.         while (1) {
  237.                 mut = pthread_mutex_trylock (&checker_mutex);
  238.                 if (mut == 0 || mut == EDEADLK) {
  239.                         break;
  240.                 } else {
  241.                         sleep(3);
  242.                 }
  243.         }
  244.  
  245.         // if successfull, then alocating memory for that thread, creating the thread and unlocking mutex.
  246.  
  247.         ++checker->count;
  248.         checker->actions = (act_threads_t **) realloc(checker->actions, checker->count * sizeof(act_threads_t *));
  249.  
  250.         checker->actions[checker->count-1] = (act_threads_t *) malloc(sizeof(act_threads_t ));
  251.  
  252.         checker->actions[checker->count-1]->servername = (char *) malloc((strlen(server->name) + 2) * sizeof(char));
  253.  
  254.         strncpy(checker->actions[checker->count-1]->servername, server->name, strlen(server->name) + 2);
  255.  
  256.         actret = pthread_create(&(checker->actions[checker->count-1]->tid), NULL, server->action, (void *) server);
  257.  
  258.         pthread_mutex_unlock (&checker_mutex);
  259. }
  260.  
  261. int main()
  262. {
  263.         /* initialization */
  264.         printf("Initing mutex...");
  265.         int init_ret;
  266.         init_ret = pthread_mutex_init(&checker_mutex, NULL);
  267.         if (init_ret != 0) {
  268.                 printf("pthread_mutex_init return %d. exiting...", init_ret);
  269.                 exit(0);
  270.         } else {
  271.                 printf("Seems ok. %d returned\n", init_ret);
  272.         }
  273.  
  274.         pthread_t threads[NTHREAD];
  275.         pthread_t action_check;
  276.  
  277.         act_checker_t checker;
  278.  
  279.         checker.actions = NULL;
  280.         checker.count = 0;
  281.  
  282.         int  iret;
  283.         int action_ret;
  284.         long i; int ret = 1;
  285.         server_t servers[] = {
  286.                 {"server1", triggered1, action1},
  287.                 {"server2", triggered2, action2},
  288.                 {"server3", triggered3, action2},
  289.         };
  290.         /* initialization */ // END
  291.  
  292.         // creating separate thread, to monitor file system.
  293.  
  294.         action_ret = pthread_create(&action_check, NULL, check_threads, (void *) &checker);
  295.  
  296.     /* create independent threads each of which will execute function */
  297.  
  298.         while (1)  {
  299.                 for (i = 0; i < NTHREAD; i++) {
  300.                         iret = pthread_create(&threads[i], NULL, servers[i].triggered, (void *) &servers[i]);
  301.                 }
  302.  
  303.                 for (i = 0; i < NTHREAD; i++) {
  304.                         pthread_join(threads[i], (void *) &ret);
  305.                         if (ret == 0) {         // if any event triggered then...
  306.                                 // creating thread for action of that event.
  307.  
  308.                                 create_action_thread(&checker, &servers[i]);
  309.                         }
  310.                 }
  311.  
  312.                 sleep(1);
  313.         }
  314.  
  315.         pthread_mutex_destroy(&checker_mutex);
  316.         pthread_exit(NULL);
  317.  
  318.         return 0;
  319. }