0

I have new data appearing over a bus. I want my main thread to "wake up" when the new data arrives. My original version of the code is this:

#include <time.h>
#include <stdio.h>
#include <pthread.h>
#include <time.h>

int data = 0;

void* thread_func(void* args)
{
    while(1)
    {
        sleep(2);
        
        data = random() % 5;
    }
    
    return NULL;
}


int main()
{
    int tid;

    pthread_create(&tid, NULL, &thread_func, NULL);
    
    while(1)
    {
        // Check data.
        printf("New data arrived: %d.\n", data);
        sleep(2);
    }
    
    return 0;
}

But clearly an infinite while loop in the main thread is overkill. So I thought how about this?

#include <time.h>
#include <stdio.h>
#include <pthread.h>
#include <time.h>

int data = 0;
pthread_mutex_t mtx;

void* thread_func(void* args)
{
    while(1)
    {
        sleep(2);
        
        // Data has appeared and can be read by main().
        data = random() % 5;
        
        pthread_mutex_unlock(&mtx);
    }
    
    return NULL;
}


int main()
{
    int tid;
       

    pthread_mutex_init(&mtx, NULL);
    
    pthread_create(&tid, NULL, &thread_func, NULL);
    
    while(1)
    {
        pthread_mutex_lock(&mtx);
        printf("New data has arrived: %d.\n", data);
    }
    
    return 0;
}

This works, but is it the best way?

In actual fact, I don't just have a main thread, but several threads that I would like to be asleep until new data for them arrived. This would involve using one mutex lock for each thread. Is this the best way to do things?

I hope it's clear. Thanks.

Stacksly
  • 1
  • 1
  • C **or** C++? These are completely different languages. This looks like 100% C code. – tadman Apr 12 '21 at 10:17
  • The language-agnostic keyword for that is *message queue*. – mouviciel Apr 12 '21 at 10:18
  • 2
    Look up "semaphores". – tadman Apr 12 '21 at 10:19
  • 1
    Hi, I have written C code for simplicity and would prefer to stick to that unless C++ provides useful tools. – Stacksly Apr 12 '21 at 10:19
  • you lock in one thread, but unlock in the other one?.. – Jarod42 Apr 12 '21 at 10:20
  • Semaphore is not what I want as in my situation as thread_func would end up incrementing the semaphore to some arbitrary number if my main thread was not consuming (?) the semaphores generated on a one-to-one basis. – Stacksly Apr 12 '21 at 10:22
  • Yes, I repeatedly unlock in the data-collecting thread. In reality, it is not a constant 2 second delay between new data, but the data arrives at random. – Stacksly Apr 12 '21 at 10:22
  • C++ provides useful tool `std::thread`, `std::unique_lock`, `std::atomic`, `std::condition_variable` but C-way is possible. – Jarod42 Apr 12 '21 at 10:22
  • I fear you have UB, see [pthread-mutex-lock-unlock-by-different-threads](https://stackoverflow.com/questions/5454746/pthread-mutex-lock-unlock-by-different-threads) – Jarod42 Apr 12 '21 at 10:29
  • Google 'producer consumer queue'. Yes, you are misusing a mutex, (why so many devs try to use a mutex like this I have no idea). – Martin James Apr 12 '21 at 15:02

1 Answers1

1

You can use pthread_cond_wait to wait for a change on the data you share between your threads. This function automatically blocks your mutex and you have to release it afterwards. To notify your threads that the data is ready use the pthread_cond_signal function.

But be careful, you must always lock and unlock your mutex in each of your threads, not as you do in your example.

tr4cks
  • 126
  • 1
  • 8
  • 1
    And beware of "spurious wakeup" phenomenon of your conditionnal variable. To learn more, click [here](https://stackoverflow.com/questions/13122406/why-do-we-need-a-condition-check-before-pthread-cond-wait). – tr4cks Apr 12 '21 at 10:40
  • Thanks, this seems to do what I want. – Stacksly Apr 12 '21 at 16:33