Question

The question is simple but the solution eludes me. I want to get two functions to be called and have them run at the same time (in separate threads), but I can only get void function1() called and void function2() runs only afterwards not during. I set the thread affinity for processor 1 and 2 (I have a multicore processor, hope you have one too).

The way I see that only one function is called at a time is simply because I get an output of only function 1 whereas normally I would see a mix of function 1 and function 2.

Feel free to reshuffle the code to make it work however possible but please try to keep the original methodology intact with the way a function is called by the thread within a class. Heres the complete code.

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include <iostream>

class thread_class
{
    private:


    public:

    void function1()
    {
        for(int count = 0; count < 1000; count++)
            std::cout<<"function 1"<<std::endl;
    }
    void function2()
    {
        for(int count = 0; count < 1000; count++)
            std::cout<<"function 2"<<std::endl;
    }
    thread_class(){}
    ~thread_class(){}
    DWORD_PTR WINAPI threadMain0()
    {
        function1();

        return 0;
    }
    DWORD_PTR WINAPI threadMain1()
    {
        function2();

        return 0;
    }
    void thread()
    {
        HANDLE *m_threads = NULL;
        DWORD_PTR c = 2;

        m_threads = new HANDLE[c];

        DWORD_PTR i = 0;
        DWORD_PTR m_id0 = 0;
        DWORD_PTR m_mask0 = 1 << i;

        m_threads[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)threadMain0(), (LPVOID)i, NULL, &m_id0);
        SetThreadAffinityMask(m_threads[i], m_mask0);

        wprintf(L"Creating Thread %d (0x%08x) Assigning to CPU 0x%08x\r\n", i, (LONG_PTR)m_threads[i], m_mask0);

        i = 1;
        DWORD_PTR m_id1 = 0;
        DWORD_PTR m_mask1 = 1 << i;

        m_threads[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)threadMain1(), (LPVOID)i, NULL, &m_id1);
        SetThreadAffinityMask(m_threads[i], m_mask1);

        wprintf(L"Creating Thread %d (0x%08x) Assigning to CPU 0x%08x\r\n", i, (LONG_PTR)m_threads[i], m_mask1);
    }
};
int main()
{
    thread_class* MAIN_THREADS;

    MAIN_THREADS = new thread_class();

    MAIN_THREADS->thread();

    delete MAIN_THREADS;

    return 0;
}

edit: This is a slightly modified version of the code below that shows its not running parallel.

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include <iostream>

class thread_class
{
    private:


    public:

    void function1()
    {
        int exit = 0;

        while(exit == 0)
        {
            std::cout<<"enter 1 to exit:"<<std::endl;
            std::cin>>exit;
        };
    }
    void function2()
    {
        for(int count = 0; count < 1000; count++)
            std::cout<<"function 2"<<std::endl;
    }
    thread_class(){}
    ~thread_class(){}
    DWORD_PTR WINAPI threadMain0()
    {
        function1();

        return 0;
    }
    DWORD_PTR WINAPI threadMain1()
    {
        function2();

        return 0;
    }
    void thread()
    {
        HANDLE *m_threads = NULL;
        DWORD_PTR c = 2;

        m_threads = new HANDLE[c];

        DWORD_PTR i = 0;
        DWORD_PTR m_id0 = 0;
        DWORD_PTR m_mask0 = 1 << i;

        m_threads[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)threadMain0(), (LPVOID)i, NULL, &m_id0);
        SetThreadAffinityMask(m_threads[i], m_mask0);

        wprintf(L"Creating Thread %d (0x%08x) Assigning to CPU 0x%08x\r\n", i, (LONG_PTR)m_threads[i], m_mask0);

        i = 1;
        DWORD_PTR m_id1 = 0;
        DWORD_PTR m_mask1 = 1 << i;

        m_threads[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)threadMain1(), (LPVOID)i, NULL, &m_id1);
        SetThreadAffinityMask(m_threads[i], m_mask1);

        wprintf(L"Creating Thread %d (0x%08x) Assigning to CPU 0x%08x\r\n", i, (LONG_PTR)m_threads[i], m_mask1);
    }
};
int main()
{
    thread_class* MAIN_THREADS;

    MAIN_THREADS = new thread_class();

    MAIN_THREADS->thread();

    delete MAIN_THREADS;

    return 0;
}
Was it helpful?

Solution

So, a few things:

1) You can't use regular member functions as a ThreadProc. If you have to cast it to get it to compile it's probably wrong. The ThreadProc functions need to be free or static. They also had the wrong signature as a ThreadProc takes a single void* parameter.

2) There are several places where you use DWORD_PTR when you really want DWORD such as the return value from the ThreadProc, c, i, etc.

3) From the CreateProcess docs:

A thread in an executable that calls the C run-time library (CRT) should use the _beginthreadex and _endthreadex functions for thread management rather than CreateThread and ExitThread; this requires the use of the multithreaded version of the CRT. If a thread created using CreateThread calls the CRT, the CRT may terminate the process in low-memory conditions.

Chances are writing to cout eventually hits the CRT. It may not, and even if it does you may not have issues, but if you do that's a good place to look.

4) I/O isn't guaranteed to be interleaved at all, so writing to cout is not a good way to decide if the threads are running simultaneously or not. I've added some Sleep calls to the threads and also created them suspended at first so I could start them as close together as possible to make it seem like the I/O is interleaved, but that may just be coincidence. Once thing I do see that you may as well is that right when the threads are started the string that's printed and the endl are not attached to each other, that is I see both strings followed by two line ends. After that is it somewhat interleaved.

5) You always want to wait for the threads to exit before you delete the class out from under them. You also generally want to close their handles once they are done.

I eliminated the constructor/destructor since they were empty and other fluff just to keep this as short as possible.

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include <iostream>

class thread_class
{
    public:
    void function1()
    {
        Sleep(0);
        for(int count = 0; count < 10; count++)
        {
            std::cout<<"function 1"<<std::endl;
            Sleep(0);
        }
    }
    void function2()
    {
        Sleep(0);
        for(int count = 0; count < 10; count++)
        {
            std::cout<<"function 2"<<std::endl;
            Sleep(0);
        }
    }
    static DWORD WINAPI threadMain0(LPVOID param)
    {
        thread_class* This = static_cast<thread_class*>(param);
        This->function1();
        return 0;
    }
    static DWORD WINAPI threadMain1(LPVOID param)
    {
        thread_class* This = static_cast<thread_class*>(param);
        This->function2();
        return 0;
    }
    void thread()
    {
        HANDLE m_threads[2] = {};
        DWORD threadIDs[2] = {};
        LPTHREAD_START_ROUTINE threadProcs[2] = {threadMain0, threadMain1};
        DWORD_PTR mask = 0;
        for(int i = 0; i < 2; ++i)
        {
            m_threads[i] = CreateThread(NULL, 0, threadProcs[i], this, CREATE_SUSPENDED, &threadIDs[i]);
            mask = 1 << i;
            SetThreadAffinityMask(m_threads[i], mask);
            wprintf(L"Creating Thread %d (0x%08p) Assigning to CPU 0x%08p\r\n", i, m_threads[i], mask);
        }
        for(int i = 0; i < 2; ++i)
        {
            ResumeThread(m_threads[i]);
        }
        WaitForMultipleObjects(2, m_threads, TRUE, INFINITE);
        for(int i = 0; i < 2; ++i)
        {
            CloseHandle(m_threads[i]);
        }
    }
};

int main()
{
    thread_class* MAIN_THREADS;
    MAIN_THREADS = new thread_class();
    MAIN_THREADS->thread();
    delete MAIN_THREADS;
    return 0;
}

OTHER TIPS

One of the problems I see in both revisions of your code is NULL passed to dwCreationFlags parameter of CreateThread() function. This means that created thread will be launched right after the CreateThread() exits (or even sooner if you're equipped with multi-core CPU and lucky sheduling). So it seems that your first thread finishes his job before the second thread has any chance to be born (because threada creation is costy operation in terms of time - tens or hundreds of miliseconds).

So could you try the following:

  1. Create both threads with CREATE_SUSPENDED flag instead of NULL
  2. Call ResumeThread to both threads then
  3. Make the functions execution time much longer (maybe millions of iterations)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top