samedi 2 mai 2015

C++, signal and threads

I'm having some hard time designing the main workflow of my application, using threads and signals.

My goal here is to have a main thread, catching signals, and n other threads doing stuff periodically (actually using sensors on a raspberry pi, and saving retrieved data). I want the ability to close the program in a clean way, i.e. wait that a sensor has finished writing data (if they are when the signal occur) before closing it. I'm using C++ 11.

For now, I have this example :

#include <iostream>
#include <thread>
#include <csignal>
#include <mutex>

#define NUM_THREAD 3;

static volatile int stop = 0;     // If the threads needs to stop
std::mutex m;                     // Mutex

void threadHandle(int tid) {
    while(1) {
        std::cout << "Launched by thread " << tid << std::endl;
        std::this_thread::sleep_for(std::chrono::seconds(2));
        std::cout << "I have sleep well " << tid << std::endl;

        m.lock();
        if(stop) {
            std::cout << "Thread " << tid << " needs to stop" << std::endl;
            m.unlock();
            break;
        }
        m.unlock();
    }
}

void signalHandler(int signum) {
    m.lock();
    std::cout << "Signal " << signum << " received" << std::endl;
    stop = 1;
    m.unlock();
}

int main() {
    std::thread t[NUM_THREAD];
    std::signal(SIGINT, signalHandler);

     //Launch a group of threads
     for (int i = 0; i < NUM_THREAD; i++) {
         t[i] = std::thread(call_from_thread, i);
     }

     std::cout << "Launched from the main\n";

     for (int i = 0; i < NUM_THREAD; i++) {
         t[i].join();
     }

     return 0;
}

My stop value is volatile only because I'm using it inside a signal handler. Should I use an std::atomic_int to ensure atomic calls to my signal value? Is the mutex really necessary? Or more generally, is this a good way to achieve what I want ?

Another problem I could have, is that some sensors may have a waiting time between measures really long (like 2 or 3 hours), so I would be in need to check the stop value every 2 or 3 seconds.. and it doesn't feel really like the clean way to do it. The other solution, sending signals to the threads, allow me to simply make my thread "sleep"; but again I have no controls to tell the thread to complete its action before terminating.

Thanks in advance !

Aucun commentaire:

Enregistrer un commentaire