Advertisement
tarruda

Read input from another thread

Dec 3rd, 2013
175
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 3.15 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <pthread.h>
  4. #include <unistd.h>
  5. #include <string.h>
  6.  
  7. typedef enum { USER_INPUT, COMMAND } EventType;
  8.  
  9. typedef struct event_t
  10. {
  11.   EventType type;
  12.   void *data;
  13.   struct event_t * next;
  14. } event_t;
  15.  
  16. typedef struct
  17. {
  18.   pthread_mutex_t mutex;
  19.   pthread_cond_t cond;
  20.   event_t * head;
  21.   event_t * tail;
  22. } event_queue_t;
  23.  
  24. pthread_t user_input_thread;
  25. pthread_t async_commands_thread;
  26. event_queue_t event_queue;
  27. char *current_input;
  28.  
  29. void queue_init()
  30. {
  31.   pthread_mutex_init(&event_queue.mutex, NULL);
  32.   pthread_cond_init(&event_queue.cond, NULL);
  33.   event_queue.head = NULL;
  34.   event_queue.tail = NULL;
  35. }
  36.  
  37.  
  38. void queue_add(EventType type, void *data)
  39. {
  40.   event_t *ev = (event_t *)malloc(sizeof(event_t));
  41.   ev->type = type;
  42.   ev->data = data;
  43.   ev->next = NULL;
  44.  
  45.   pthread_mutex_lock(&event_queue.mutex);
  46.  
  47.   if (event_queue.head == NULL) {
  48.     event_queue.head = ev;
  49.     // queue was empty and consequently the main thread was waiting, so wake it
  50.     // up to continue after the lock is released
  51.     pthread_cond_broadcast(&event_queue.cond);
  52.   } else {
  53.     if (event_queue.tail != NULL) {
  54.       event_queue.tail->next = ev;
  55.     } else {
  56.       event_queue.head->next = ev;
  57.     }
  58.     event_queue.tail = ev;
  59.   }
  60.  
  61.   pthread_mutex_unlock(&event_queue.mutex);
  62.  
  63. }
  64.  
  65. event_t * queue_remove()
  66. {
  67.   event_t *rv;
  68.   pthread_mutex_lock(&event_queue.mutex);
  69.  
  70.   if (event_queue.head == NULL) {
  71.     // queue is empty, temporarily release the lock and wait for events
  72.     pthread_cond_wait(&event_queue.cond, &event_queue.mutex);
  73.   }
  74.  
  75.   rv = event_queue.head;
  76.   event_queue.head = rv->next;
  77.  
  78.   pthread_mutex_unlock(&event_queue.mutex);
  79.  
  80.   return rv;
  81. }
  82.  
  83.  
  84. // This will put a string that will be evaluated as a vim command in the next
  85. // main_loop iteration.
  86. void enqueue_command(char *command_str)
  87. {
  88.   queue_add(COMMAND, command_str);
  89. }
  90.  
  91.  
  92. void * generate_async_commands()
  93. {
  94.   while (1)
  95.   {
  96.     sleep(5);
  97.     char *command_str = (char *)malloc(1024);
  98.     strcpy(command_str, "[SOME VIMSCRIPT CODE TO EXECUTE]");
  99.     enqueue_command(command_str);
  100.   }
  101. }
  102.  
  103.  
  104. void * vgetc(void *arg)
  105. {
  106.   while (1)
  107.   {
  108.     char *data = (char *)malloc(1024);
  109.     scanf("%s", data);
  110.     queue_add(USER_INPUT, data);
  111.   }
  112.  
  113.   return NULL;
  114. }
  115.  
  116.  
  117. int next_event()
  118. {
  119.   event_t *next = queue_remove();
  120.   switch (next->type)
  121.   {
  122.     case USER_INPUT:
  123.       current_input = next->data;
  124.       free(next);
  125.       return 0;
  126.     case COMMAND:
  127.       printf("Received command: '%s'\n", (char *)next->data);
  128.       free(next->data);
  129.       free(next);
  130.       return 1;
  131.   }
  132. }
  133.  
  134.  
  135. void main_loop()
  136. {
  137.   pthread_attr_t attr;
  138.   pthread_attr_init(&attr);
  139.  
  140.   // Create a dedicated thread for reading user input
  141.   pthread_create(&user_input_thread, &attr, &vgetc, NULL);
  142.  
  143.   // Create a background thread to illustrate communication from plugins
  144.   pthread_create(&async_commands_thread, &attr, &generate_async_commands,
  145.       NULL);
  146.  
  147.   while (1) {
  148.     if (next_event()) continue;
  149.     printf("User input '%s'\n", current_input);
  150.     free(current_input);
  151.   }
  152. }
  153.  
  154.  
  155. int main()
  156. {
  157.   main_loop();
  158.   return 0;
  159. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement