Search code examples
c++multithreadingqnx

QNX c++ thread question


I have a question concerning this code which I want to run on QNX:

class ConcreteThread : public Thread
{
public:
    ConcreteThread(int test)
    {
        testNumber = test;
    }

    void *start_routine() 
    { 
        for(int i = 0; i < 10; i++)
        {
            sleep(1);
            cout << testNumber << endl;
        }   
    }

private:
    int testNumber;
};




class Thread 
{
public:
    Thread(){};

    int Create()
    {
        pthread_t m_id;
        return pthread_create(&m_id, NULL, &(this->start_routine_trampoline), this);
    }

protected:
    virtual void *start_routine() = 0;

private:

    static void *start_routine_trampoline(void *p)
    {
        Thread *pThis = (Thread *)p;
        return pThis->start_routine();
    }
};

Now, when I run this code without the sleep in *start_routine, it will simply print the number 10 times, before continuing on to the next line of code (sequential instead of parallel). However, when I use a sleep like in the code, it doesn't print any numbers at all and simply goes on to the next line of code. Why doesn't sleep work and how can I make a thread like this work, instead of running sequential?


Solution

  • Note 1: If you only have 1 processor the code can only be done sequentially no matter how many threads you create. Each thread is given a slice of processor time before it is swapped out for the next threads.

    Note 2: If the main thread exits pthreads will kill all child threads before they have a chance to execute.

    Now to answer you questions:

    Without the sleep. The thread once started has enough time in the single slice it was given to execute the loop 10 times completely.

    With the sleep: Your worker thread is going to sleep for a full second. So your main thread has time to do a lot of work. If the main thread exits in this time the worker will be killed.

    I would make the following changes:

    //  Remove the Create() method
    //  Put thread creation in the constructor.
    //  Make the thread variable part of the object
    
    pthread_t m_id;
    
    Thread()
    {
        if (pthread_create(&m_id, NULL, &(this->start_routine_trampoline), this) != 0)
        {
            throw std::runtime_error("Thread was not created");
        }
    }
    
    // Make sure the destructor waits for the thread to exit.
    ~Thread()
    {
        pthread_join(m_id);
    }
    

    If you go and look at boost threading library. you will find that all the little mistakes like this have already been taken care of; Thus making threading easier to use.

    Also note. That using a static may work but it is non portable. This is because pthread's is a C library and is thus expecting a function pointer with a C ABI. You are just getting lucky for your platform here. You need to define this as a function and declare the ABI by using extern "C"

    // This needs to be a standard function with C Interface.
    extern "C" void *start_routine_trampoline(void *p)
    {
    }