Advertisement
Guest User

pthread_problem

a guest
Apr 3rd, 2011
195
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 7.47 KB | None | 0 0
  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. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement