-2

i searched for an answer but couldnt find it. im working on threads. i have a thread class and 3 subclass of it. when i call one of these 3 subclass i have to create a thread in thread class and use their main(since threads main is pure virtual abstract) but the problem is before it call the Create Thread function(c'tor of thread) it calls those sub-mains.

thread.h

#ifndef _THREAD_H_
#define _THREAD_H_

#include <string>
#include <Windows.h>
#include <iosfwd>
#include "Mutex.h"
#include "SynchronizedArray.h"
#include "SynchronizedCounter.h"



std::string message = "";


class Thread{ 

private:
    HANDLE hThread;
    int idThread;

protected:

    SynchronizedArray *arr;
    int size;
    SynchronizedCounter *counter;

public:

    Thread(DWORD funct){   //creates a thread by calling subclasses main functions appropriately 
        hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) funct, NULL, 0, (LPDWORD)&idThread);
    }

    virtual DWORD WINAPI main(void*) = 0;  // pure virtual abstract class 

    void suspend(){  //suspent the thread 
        SuspendThread(hThread);
    }
    void resume(){// retume the thread 
        ResumeThread(hThread);
    }

    void terminate(){ // terminates the thread
    TerminateThread(hThread,0);
    }
    void join(){ // joins the thread 
        Mutex mut;
        mut.lock();
    }
    static void sleep(int sec){ //wrapper of sleep   by sec
        Sleep(sec*1000);
    }

};


#endif

1 of 3 inherited class of Thread as example (all of them do the same)

PrintThread.h

#ifndef _PRINTINGTHREAD_H_
#define _PRINTINGTHREAD_H_
#include "SynchronizedArray.h"
#include "SynchronizedCounter.h"
#include "Thread.h"
#include <iostream>
#include "SortingThread.h"
#include "CountingThread.h"
#include <string>
#include <Windows.h>

extern CountingThread counterThread1;
extern CountingThread counterThread2;
extern SortingThread sortingThread1;
extern SortingThread sortingThread2;


class PrintingThread:public Thread{
private:
    char temp;
public:
    PrintingThread() :Thread(main(&temp)){
    }


    DWORD WINAPI main(void* param)
    {
        std::cout << "Please enter an operation ('showcounter1','showcounter2','showarray1','showarray2' or 'quit')" << std::endl;
        std::cin >> message;
        while (message != "quit")
        {
            if (message == "showcounter1")
            {
                std::cout << counterThread1<<std::endl;
            }
            else if (message == "showcounter2")
            {
                std::cout << counterThread2 << std::endl;
            }
            else if (message == "showarray1")
            {
                std::cout << sortingThread1 << std::endl;
            }
            else if (message == "showarray2")
            {
                std::cout << sortingThread2 << std::endl;
            }
            else {
                std::cout << "Invalid operation";
            }
            std::cout << "Please enter an operation ('show counter 1','show counter 2','show array 1','show array 2' or 'quit')" << std::endl;
            std::cin >> message;

        }
        return 0;

    }
};




#endif

Why its calling mains before it calls the c'tor of thread.

enesdisli
  • 23
  • 6
  • Why call main? You shouldn't even have functions called "main" other than that of the entry point of your program. Name it something like "run" instead or even "start". – Brandon Aug 21 '14 at 18:08
  • this is what i'm assigned for. but even if i change the name of the main (for example "func") it does the same thing – enesdisli Aug 21 '14 at 18:10
  • You'd have to do something like this: http://pastebin.com/CfYTY0qu See here for more info: http://stackoverflow.com/questions/1372967/how-do-you-use-createthread-for-functions-which-are-class-members Btw.. if your teacher gave you an assignment and had a function called "main" and it isn't the entry point, you should point it out to them. – Brandon Aug 21 '14 at 18:29
  • 1
    (1) Functions that you pass to `CreateThread` should be `static` (so you don't try to access any members) (2) You haven't showed us any code that makes instances of these classes. – nobody Aug 21 '14 at 18:32
  • Obligatory: [A function pointer cast is a bug waiting to happen](http://blogs.msdn.com/b/oldnewthing/archive/2011/05/06/10161590.aspx). – Adam Rosenfield Aug 21 '14 at 18:51
  • There's loads wrong here. That cast is particularly egregious. But the use of SuspendThread and TerminateThread are also ill advised. – David Heffernan Aug 22 '14 at 19:31

2 Answers2

2

Your PrintingThread constructor initializer list is actually calling PrintingThread::main and passing the result of that to the Thread constructor. That means that the CreateThread call is receiving a DWORD (in this case, 0) as its function argument.

You need to change your class design to actually pass the function pointer and context argument around, e.g.:

Thread(DWORD funct){
    hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) funct, NULL, 0, (LPDWORD)&idThread);

should be:

Thread(LPTHREAD_START_ROUTINE funct, LPVOID arg) {
    hThread = CreateThread(NULL, 0, funct, arg, 0, (LPDWORD)&idThread);

(The fact that you had to cast funct should have been a giant red flag.)

Likewise, the subclass constructors will change from:

PrintingThread() :Thread(main(&temp)){

to:

PrintingThread(): Thread(main, &temp) {

Note that your code will still have other issues, like the fact that the thread functions should be static (so you can't try to access member functions).

nobody
  • 19,814
  • 17
  • 56
  • 77
2

you need to do something more like this instead:

thread.h:

#ifndef _THREAD_H_
#define _THREAD_H_

#include <string>
#include <Windows.h>
#include <iosfwd>
#include "Mutex.h"
#include "SynchronizedArray.h"
#include "SynchronizedCounter.h"

class Thread
{ 
private:
    HANDLE hThread;
    DWORD idThread;
    void *pParam;    

    static DWORD WINAPI ThreadProc(LPVOID lpParameter)
    {
        Thread *pThis = (Thread*) lpParameter;
        return pThis->main(pThis->pParam);
    }

protected:
    SynchronizedArray *arr;
    int size;
    SynchronizedCounter *counter;

public:    
    Thread(void *aParam)
    {
        //creates a thread by calling subclasses main functions appropriately 
        pParam = aParam;
        hThread = CreateThread(NULL, 0, &ThreadProc, this, 0, &idThread);
    }

    virtual DWORD main(void*) = 0;  // pure virtual abstract class 

    void suspend()
    {
        //suspent the thread 
        SuspendThread(hThread);
    }

    void resume()
    {
        // resume the thread 
        ResumeThread(hThread);
    }

    void terminate()
    {
        // terminates the thread
        TerminateThread(hThread, 0);
    }

    void join()
    {
        // joins the thread 
        Mutex mut;
        mut.lock();
    }

    static void sleep(int sec)
    {
        //wrapper of sleep   by sec
        Sleep(sec*1000);
    }
};

#endif

PrintThread.h:

include <iostream>
#include "SortingThread.h"
#include "CountingThread.h"
#include <string>
#include <Windows.h>

extern CountingThread counterThread1;
extern CountingThread counterThread2;
extern SortingThread sortingThread1;
extern SortingThread sortingThread2;

class PrintingThread : public Thread
{
private:
    char temp;

public:
    PrintingThread() : Thread(&temp)
    {
    }

    virtual DWORD main(void* param)
    {
        std::string message;

        do
        {
            std::cout << "Please enter an operation ('showcounter1','showcounter2','showarray1','showarray2' or 'quit')" << std::endl;
            std::cin >> message;
            if (message == "quit")
            {
                break;
            }
            if (message == "showcounter1")
            {
                std::cout << counterThread1 << std::endl;
            }
            else if (message == "showcounter2")
            {
                std::cout << counterThread2 << std::endl;
            }
            else if (message == "showarray1")
            {
                std::cout << sortingThread1 << std::endl;
            }
            else if (message == "showarray2")
            {
                std::cout << sortingThread2 << std::endl;
            }
            else
            {
                std::cout << "Invalid operation";
            }
        }
        while (true);

        return 0;    
    }
};

#endif
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770