my multithread class: how use the CreateThread()?

Category: visual studio vclanguage

Question

Cambalinho on Sat, 26 Dec 2015 17:51:59


i'm doing my own new class for multithread:

class UpdatedMultithread
{
private:
    HANDLE hThreadArray=NULL;
    DWORD dwThreadIdArray=0;
    function<void()> multithreadfunction=NULL;
    function<void(LPVOID param)> multithreadparameterfunction=NULL;
    HANDLE myEvent = CreateEvent(0, 0, 0, 0);

    struct mytread
    {
        UpdatedMultithread *classpointer=NULL;
        LPVOID multithreadparameters=NULL;
    };
    mytread mtparameterthread;

public:

    void WaitCondition()
    {
        WaitForSingleObject(myEvent, INFINITE);
    }

    void SetCondition()
    {
        SetEvent(myEvent);
    }

    static DWORD WINAPI MyThreadFunction( LPVOID lpParam )
    {
        UpdatedMultithread *pThis = static_cast<UpdatedMultithread*>(lpParam);
        pThis->multithreadfunction();
        return 0;
    }

    static DWORD WINAPI MyParameterThreadFunction( LPVOID lpParam )
    {
        mytread *pThis = static_cast<mytread*>(lpParam);
        pThis->classpointer->multithreadparameterfunction(pThis->multithreadparameters);
        return 0;
    }

    UpdatedMultithread(std::function<void()> SetFunction)
    {
        multithreadfunction=SetFunction;
    }

    UpdatedMultithread(std::function<void(LPVOID param)> SetFunction)
    {
        multithreadparameterfunction=SetFunction;
    }

    /*void operator ()(LPVOID lpParam)
    {
        mtparameterthread.classpointer=this;
        mtparameterthread.multithreadparameters=lpParam;

        hThreadArray = CreateThread(
            NULL,                   // default security attributes
            0,                      // use default stack size
            &UpdatedMultithread::MyThreadFunction,       // thread function name
            &mtparameterthread,          // argument to thread function
            0,                      // use default creation flags
            &dwThreadIdArray);
    }*/

    void operator ()()
    {
       hThreadArray = CreateThread(
            NULL,                   // default security attributes
            0,                      // use default stack size
            &UpdatedMultithread::MyThreadFunction,       // thread function name
            NULL,          // argument to thread function
            0,                      // use default creation flags
            &dwThreadIdArray);
    }

    ~UpdatedMultithread()
    {
        CloseHandle(hThreadArray);
        CloseHandle(myEvent);
    }
};

and heres how i use it:

UpdatedMultithread upMulti([]()
    {
        delay(5000);
        DebugText("hello 1");
    });
    upMulti();

    UpdatedMultithread upMulti1([]()
    {
        delay(5000);
        DebugText("hello 2");
    });
    //upMulti1();

i don't get any error. just a memory leak. i don't know why. can anyone explain to me?

by testing: i belive the memory leak is on CreateThread() function



Replies

Igor Tandetnik on Sat, 26 Dec 2015 18:14:40


On 12/26/2015 12:51 PM, Cambalinho wrote:

     static DWORD WINAPI MyThreadFunction( LPVOID lpParam )
     {
         UpdatedMultithread *pThis = static_cast<UpdatedMultithread*>(lpParam);

MyThreadFunction expects UpdatedMultithread* pointer as its parameter.

     void operator ()()
     {
        hThreadArray = CreateThread(
             NULL,                   // default security attributes
             0,                      // use default stack size
             &UpdatedMultithread::MyThreadFunction,       // thread function name
             NULL,          // argument to thread function

... but you instruct CreateThread to pass NULL as a parameter to MyThreadFunction.

Cambalinho on Sat, 26 Dec 2015 18:18:42


On 12/26/2015 12:51 PM, Cambalinho wrote:

     static DWORD WINAPI MyThreadFunction( LPVOID lpParam )
     {
         UpdatedMultithread *pThis = static_cast<UpdatedMultithread*>(lpParam);

MyThreadFunction expects UpdatedMultithread* pointer as its parameter.

     void operator ()()
     {
        hThreadArray = CreateThread(
             NULL,                   // default security attributes
             0,                      // use default stack size
             &UpdatedMultithread::MyThreadFunction,       // thread function name
             NULL,          // argument to thread function

... but you instruct CreateThread to pass NULL as a parameter to MyThreadFunction.

yes i found that error too.. thanks for all.

void operator ()()
    {
       hThreadArray = CreateThread(
            NULL,                   // default security attributes
            0,                      // use default stack size
            &UpdatedMultithread::MyThreadFunction,       // thread function name
            this,          // argument to thread function
            0,                      // use default creation flags
            &dwThreadIdArray);
    }


now, i'm testing the synchronization code.

i will come back... i'm testing more 1 thing.

thanks

Cambalinho on Sat, 26 Dec 2015 18:30:15


code tested without arguments:

class UpdatedMultithread
{
private:
    HANDLE hThreadArray=NULL;
    DWORD dwThreadIdArray=0;
    bool blnSingleThreadAtTime=false;
    function<void()> multithreadfunction=NULL;
    function<void(LPVOID param)> multithreadparameterfunction=NULL;
    HANDLE myEvent = CreateEvent(0, 0, 0, 0);

    struct mytread
    {
        UpdatedMultithread *classpointer=NULL;
        LPVOID multithreadparameters=NULL;
    };
    mytread mtparameterthread;

public:

    void SingleThreadAtTime(bool SingleThread)
    {
        blnSingleThreadAtTime=SingleThread;
    }

    bool SingleThreadAtTime()
    {
        return blnSingleThreadAtTime;
    }

    void WaitCondition()
    {
        WaitForSingleObject(myEvent, INFINITE);
    }

    void SetCondition()
    {
        SetEvent(myEvent);
    }

    static DWORD WINAPI MyThreadFunction( LPVOID lpParam )
    {
        static bool blnfirsttime=false;
        UpdatedMultithread *pThis = static_cast<UpdatedMultithread*>(lpParam);
        if(pThis->blnSingleThreadAtTime==true && blnfirsttime==true)
            pThis->WaitCondition();
        blnfirsttime=true;
        pThis->multithreadfunction();
        if(pThis->blnSingleThreadAtTime==true && blnfirsttime==true)
            pThis->SetCondition();
        return 0;
    }

    static DWORD WINAPI MyParameterThreadFunction( LPVOID lpParam )
    {
        mytread *pThis = static_cast<mytread*>(lpParam);
        pThis->classpointer->multithreadparameterfunction(pThis->multithreadparameters);
        return 0;
    }

    UpdatedMultithread(std::function<void()> SetFunction)
    {
        multithreadfunction=SetFunction;
    }

    UpdatedMultithread(std::function<void(LPVOID param)> SetFunction)
    {
        multithreadparameterfunction=SetFunction;
    }

    void operator ()(LPVOID lpParam)
    {
        mtparameterthread.classpointer=this;
        mtparameterthread.multithreadparameters=lpParam;

        hThreadArray = CreateThread(
            NULL,                   // default security attributes
            0,                      // use default stack size
            &UpdatedMultithread::MyThreadFunction,       // thread function name
            &mtparameterthread,          // argument to thread function
            0,                      // use default creation flags
            &dwThreadIdArray);
    }

    void operator ()()
    {
       hThreadArray = CreateThread(
            NULL,                   // default security attributes
            0,                      // use default stack size
            &UpdatedMultithread::MyThreadFunction,       // thread function name
            this,          // argument to thread function
            0,                      // use default creation flags
            &dwThreadIdArray);
    }

    ~UpdatedMultithread()
    {
        CloseHandle(hThreadArray);
        CloseHandle(myEvent);
    }
};

heres a sample:

UpdatedMultithread upMulti([&]()
    {
        /*static bool blnfirsttime=false;
        if(blnfirsttime==true)
            upMulti.WaitCondition();
        blnfirsttime=true;*/
        static int i=-1;
        i=i+1;
        delay(5000);
        DebugText("hello " + to_string(i));
        /*if(blnfirsttime==true)
            upMulti.SetCondition();*/
    });
    upMulti.SingleThreadAtTime(true);

    upMulti();
    upMulti();
    upMulti();
    upMulti();
    upMulti();

like you see the SingleThreadAtTime() avoids the commented code. vey cool

now i must do my own variable condition code.

PS: from my question, maybe i will go out-off topic(just continue the class).

Moderator: if you want, i can do another topic for continue the class

Cambalinho on Sat, 26 Dec 2015 19:00:24


now i'm trying use the parameters but i get a memory leak :(

see the parameters section:

class UpdatedMultithread
{
private:
    HANDLE hThread=NULL;
    DWORD dwThreadId=0;
    bool blnSingleThreadAtTime=false;
    function<void()> multithreadfunction=NULL;
    function<void(LPVOID param)> multithreadparameterfunction=NULL;
    HANDLE myEvent = CreateEvent(0, 0, 0, 0);

    struct mytread
    {
        UpdatedMultithread *classpointer=NULL;
        LPVOID multithreadparameters=NULL;
    };
    mytread mtparameterthread;

public:

    void SingleThreadAtTime(bool SingleThread)
    {
        blnSingleThreadAtTime=SingleThread;
    }

    bool SingleThreadAtTime()
    {
        return blnSingleThreadAtTime;
    }

    void WaitCondition()
    {
        WaitForSingleObject(myEvent, INFINITE);
    }

    void SetCondition()
    {
        SetEvent(myEvent);
    }

    
    static DWORD WINAPI MyParameterThreadFunction( LPVOID lpParam )
    {
        mytread *pThis = static_cast<mytread*>(lpParam);
        pThis->classpointer->multithreadparameterfunction(pThis->multithreadparameters);
        return 0;
    }

    UpdatedMultithread(std::function<void(LPVOID param)> SetFunction)
    {
        multithreadparameterfunction=SetFunction;
    }

    void operator ()(LPVOID lpParam)
    {
        mtparameterthread.classpointer=this;
        mtparameterthread.multithreadparameters=lpParam;

        hThread = CreateThread(
            NULL,                   // default security attributes
            0,                      // use default stack size
            &UpdatedMultithread::MyThreadFunction,       // thread function name
            &mtparameterthread,          // argument to thread function
            0,                      // use default creation flags
            &dwThreadId);
    }

    ~UpdatedMultithread()
    {
        CloseHandle(hThreadArray);
        CloseHandle(myEvent);
    }
};

and heres how i use it:

struct TestName
    {
        string Name="";
        int Age=0;
        string Adress;
        TestName(string strname, int age, string stradress)
        {
            Name=strname;
            Age=age;
            Adress=stradress;
        }
    };
    TestName tnJoao("joao cena", 20, "Hello");
    TestName tnJoana("joana carvalho", 20, "Hello planet");

    UpdatedMultithread upMulti([&](LPVOID param)
    {
        /*static bool blnfirsttime=false;
        if(blnfirsttime==true)
            upMulti.WaitCondition();
        blnfirsttime=true;*/
        TestName *j=static_cast<TestName*>(param);
        static int i=-1;
        i=i+1;
        delay(5000);
        DebugText(j->Name + to_string(i));
        /*if(blnfirsttime==true)
            upMulti.SetCondition();*/
    });
    upMulti.SingleThreadAtTime(true);

    upMulti(static_cast<LPVOID> (&tnJoao));

i get a memory leak


Cambalinho on Sat, 26 Dec 2015 20:42:35


i did another similar mistake on:

hThread = CreateThread(
            NULL,                   // default security attributes
            0,                      // use default stack size
            &UpdatedMultithread::MyThreadFunction,       // thread function name
            &mtparameterthread,          // argument to thread function
            0,                      // use default creation flags
            &dwThreadId);

i must convert the mtparameterthread to LPVOID using the static_cast.

see my actual code:

class UpdatedMultithread
{
private:
    HANDLE hThread=NULL;
    DWORD dwThreadId=0;
    bool blnSingleThreadAtTime=false;
    function<void()> multithreadfunction=NULL;
    function<void(LPVOID param)> multithreadparameterfunction=NULL;
    HANDLE myEvent = CreateEvent(0, 0, 0, 0);

    struct mytread
    {
        UpdatedMultithread *classpointer=NULL;
        LPVOID multithreadparameters=NULL;
    };
    mytread mtparameterthread;

public:

    void SingleThreadAtTime(bool SingleThread)
    {
        blnSingleThreadAtTime=SingleThread;
    }

    bool SingleThreadAtTime()
    {
        return blnSingleThreadAtTime;
    }

    void WaitCondition()
    {
        WaitForSingleObject(myEvent, INFINITE);
    }

    void SetCondition()
    {
        SetEvent(myEvent);
    }

    static DWORD WINAPI MyThreadFunction( LPVOID lpParam )
    {
        static bool blnfirsttime=false;
        UpdatedMultithread *pThis = static_cast<UpdatedMultithread*>(lpParam);
        if(pThis->blnSingleThreadAtTime==true && blnfirsttime==true)
            pThis->WaitCondition();
        blnfirsttime=true;
        pThis->multithreadfunction();
        if(pThis->blnSingleThreadAtTime==true && blnfirsttime==true)
            pThis->SetCondition();
        return 0;
    }

    static DWORD WINAPI MyParameterThreadFunction( LPVOID lpParam )
    {
        static bool blnfirsttime=false;
        mytread *pThis = static_cast<mytread*>(lpParam);
        if(pThis->classpointer->blnSingleThreadAtTime==true && blnfirsttime==true)
            pThis->classpointer->WaitCondition();
        pThis->classpointer->multithreadparameterfunction(pThis->multithreadparameters);
        if(pThis->classpointer->blnSingleThreadAtTime==true && blnfirsttime==true)
            pThis->classpointer->SetCondition();
        return 0;
    }

    UpdatedMultithread(std::function<void()> SetFunction)
    {
        multithreadfunction=SetFunction;
    }

    UpdatedMultithread(std::function<void(LPVOID param)> SetFunction)
    {
        multithreadparameterfunction=SetFunction;
    }

    void operator ()(LPVOID lpParam)
    {
        mtparameterthread.classpointer=this;
        mtparameterthread.multithreadparameters=lpParam;

        hThread= CreateThread(
            NULL,                   // default security attributes
            0,                      // use default stack size
            &UpdatedMultithread::MyParameterThreadFunction,       // thread function name
            static_cast<LPVOID>(&mtparameterthread),          // argument to thread function
            0,                      // use default creation flags
            &dwThreadId);
    }

    void operator ()()
    {
       hThread  = CreateThread(
            NULL,                   // default security attributes
            0,                      // use default stack size
            &UpdatedMultithread::MyThreadFunction,       // thread function name
            this,          // argument to thread function
            0,                      // use default creation flags
            &dwThreadId);
    }

    ~UpdatedMultithread()
    {
        CloseHandle(hThread);
        CloseHandle(myEvent);
    }
};

and how i use it:

struct TestName
    {
        string Name="";
        int Age=0;
        string Adress;
        TestName(string strname, int age, string stradress)
        {
            Name=strname;
            Age=age;
            Adress=stradress;
        }
    };
    TestName tnJoao("joao cena", 20, "Hello");
    TestName tnJoana("joana carvalho", 20, "Hello planet");

    UpdatedMultithread upMulti([&](LPVOID param)
    {
        /*static bool blnfirsttime=false;
        if(blnfirsttime==true)
            upMulti.WaitCondition();
        blnfirsttime=true;*/
        TestName *j=static_cast<TestName*>(param);
        static int i=-1;
        i=i+1;
        delay(5000);
        DebugText(j->Name + " " + j->Adress + " " + to_string(j->Age) + " " + to_string(i));
        /*if(blnfirsttime==true)
            upMulti.SetCondition();*/
    });
    
    upMulti.SingleThreadAtTime(true);

    upMulti(static_cast<LPVOID> (&tnJoao));
    upMulti(static_cast<LPVOID> (&tnJoana));

after the 5 seconds i get, only, the tnJoana data.

so heres the question: like you see i have 1 HANDLE variable the CreateThread() returns. what happens to the running thread or the hThread, when i call the CreateThread() after the 1st time?

that's why the exemples use the arrays?

Cambalinho on Sat, 26 Dec 2015 21:25:42


finally works fine... my problem was in 2 places:

1 - on MyParameterThreadFunction(), i forget the line blnfirsttime=true;

2 - i must do a delay between the 2 threads for not lose data... i accept sugestions.

heres the actual code:

class UpdatedMultithread
{
private:
    HANDLE hThread=NULL;
    DWORD dwThreadId=0;
    bool blnSingleThreadAtTime=false;
    function<void()> multithreadfunction=NULL;
    function<void(LPVOID param)> multithreadparameterfunction=NULL;
    HANDLE myEvent = CreateEvent(0, 0, 0, 0);

    struct mytread
    {
        UpdatedMultithread *classpointer=NULL;
        LPVOID multithreadparameters=NULL;
    };
    mytread mtparameterthread;

public:

    void SingleThreadAtTime(bool SingleThread)
    {
        blnSingleThreadAtTime=SingleThread;
    }

    bool SingleThreadAtTime()
    {
        return blnSingleThreadAtTime;
    }

    void WaitCondition()
    {
        WaitForSingleObject(myEvent, INFINITE);
    }

    void SetCondition()
    {
        SetEvent(myEvent);
    }

    static DWORD WINAPI MyThreadFunction( LPVOID lpParam )
    {
        static bool blnfirsttime=false;
        UpdatedMultithread *pThis = static_cast<UpdatedMultithread*>(lpParam);
        if(pThis->blnSingleThreadAtTime==true && blnfirsttime==true)
            pThis->WaitCondition();
        blnfirsttime=true;
        pThis->multithreadfunction();
        if(pThis->blnSingleThreadAtTime==true && blnfirsttime==true)
            pThis->SetCondition();
        return 0;
    }

    static DWORD WINAPI MyParameterThreadFunction( LPVOID lpParam )
    {
        static bool blnfirsttime=false;
        mytread *pThis = static_cast<mytread*>(lpParam);
        if(pThis->classpointer->blnSingleThreadAtTime==true && blnfirsttime==true)
            pThis->classpointer->WaitCondition();
        blnfirsttime=true;
        pThis->classpointer->multithreadparameterfunction(pThis->multithreadparameters);
        if(pThis->classpointer->blnSingleThreadAtTime==true && blnfirsttime==true)
            pThis->classpointer->SetCondition();
        return 0;
    }

    UpdatedMultithread(std::function<void()> SetFunction)
    {
        multithreadfunction=SetFunction;
    }

    UpdatedMultithread(std::function<void(LPVOID param)> SetFunction)
    {
        multithreadparameterfunction=SetFunction;
    }

    void operator ()(LPVOID lpParam)
    {

        mtparameterthread.classpointer=this;
        mtparameterthread.multithreadparameters=lpParam;

        hThread= CreateThread(
            NULL,                   // default security attributes
            0,                      // use default stack size
            &UpdatedMultithread::MyParameterThreadFunction,       // thread function name
            static_cast<LPVOID>(&mtparameterthread),          // argument to thread function
            0,                      // use default creation flags
            &dwThreadId);
        delay(100);
    }

    void operator ()()
    {
       hThread  = CreateThread(
            NULL,                   // default security attributes
            0,                      // use default stack size
            &UpdatedMultithread::MyThreadFunction,       // thread function name
            this,          // argument to thread function
            0,                      // use default creation flags
            &dwThreadId);
        delay(100);
    }

    ~UpdatedMultithread()
    {
        CloseHandle(hThread);
        CloseHandle(myEvent);
    }
};

and how i use it:

struct TestName
    {
        string Name="";
        int Age=0;
        string Adress;
        TestName(string strname, int age, string stradress)
        {
            Name=strname;
            Age=age;
            Adress=stradress;
        }
    };
    TestName tnJoao("joao cena", 20, "Hello");
    TestName tnJoana("joana carvalho", 20, "Hello planet");

    UpdatedMultithread upMulti([&](LPVOID param)
    {
        /*static bool blnfirsttime=false;
        if(blnfirsttime==true)
            upMulti.WaitCondition();
        blnfirsttime=true;*/
        TestName *j=static_cast<TestName*>(param);
        static int i=-1;
        i=i+1;
        delay(5000);
        MessageBox(j->Name + " " + j->Adress + " " + to_string(j->Age) + " " + to_string(i));
        /*if(blnfirsttime==true)
            upMulti.SetCondition();*/
    });

    upMulti.SingleThreadAtTime(true);

    upMulti(static_cast<LPVOID> (&tnJoao));

    upMulti(static_cast<LPVOID> (&tnJoana));

i need a sugestion... like you see i must convert the type to LPVOID. without speaking about the vector<typename>, can i use another way for resolve that?

yah the function<void(LPVOID param)> multithreadparameterfunction=NULL don't helps to much... unless i can use a template for it... tell me something, please