Thread: class problem

  1. #1
    Registered User
    Join Date
    Sep 2008
    Posts
    48

    class problem

    the following code generates error and i can't figure out why:
    Code:
    class ModuleManager_c
    { protected:
      HANDLE hInputThread, hOutputThread;
      DWORD dwInputThread, dwOutputThread;
      
      void OutputThread(){}
      void InputThread() {}
      
          
          public:
      ModuleManager_c(){}
      ~ModuleManager_c(){}
       void status() {}
       void start(char ** argv)
       { 
            hInputThread = CreateThread(NULL,NULL,(LPTHREAD_START_ROUTINE)
            InputThread, (LPVOID) argv[0], NULL, &dwInputThread);
            }   
          };
    yet if i put
    Code:
     void InputThread() {}
    line outside the class it works.
    Compiler output:
    Code:
    \server\main.cpp In member function `void ModuleManager_c::start(char**)': 
    \server\main.cpp argument of type `void (ModuleManager_c::)()' does not match `DWORD (*)(void*)' 
    \server\Makefile.win [Build Error]  [main.o] Error 1
    Last edited by like_no_other; 04-27-2009 at 06:31 AM.

  2. #2
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    InputThread is a class member variable. It takes a hidden parameter "this" that is a the pointer to the current object. CreateThread has no idea about hidden parameter or the current object, so it will not be able to get that sort of information across.

    It is quite possibly that you are getting errors simply because you are taking the address of a class function without an explicit address-of-operator (&), but once you get past that problem, you would still have the problem you describe.

    There are several options to solve this, but they all amount to nearly the same thing: You start your thread with a function that doesn't have a hidden "this" parameter, and pass the pointer to the current object as the argument [In this case, you may have to make a struct, as you are already passing argv[0] in that place - you need both argv[0] and this].

    Once in this function, you cast your void pointer back to the class object (or struct in the case described above) and call a second level thread function.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  3. #3
    Registered User
    Join Date
    Sep 2008
    Posts
    48
    Here's what i've came up with:
    Code:
     class ModuleManager_c;
     void OutputThread(ModuleManager_c * pModuleManager);
      void InputThread(ModuleManager_c * pModuleManager );
    
    class ModuleManager_c
    { protected:
      HANDLE hInputThread, hOutputThread;
      DWORD dwInputThread, dwOutputThread;
      
     
      
          
          public:
      int test;
      ModuleManager_c(){test=17;}
      ~ModuleManager_c(){}
       void status() {}
       void start( ModuleManager_c * pModuleManager )
       { 
            hInputThread = CreateThread(NULL,NULL,(LPTHREAD_START_ROUTINE)
            InputThread, (LPVOID) pModuleManager, NULL, &dwInputThread);
            }   
          };
    
       void InputThread(ModuleManager_c * pModuleManager ) {cout<<pModuleManager->test; }
       void OutputThread(ModuleManager_c * pModuleManager) {}
    Yet i can't acces protected content.

  4. #4
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    A few comments:
    1. Assuming that start is called something like this:
    Code:
    ModuleManager_c mgr;
    mgr.tart(&mgr);
    (As opposed to
    Code:
    ModuleManager_c mgr;
    ModuleManager_c a;
    ... 
    mgr.start(&a)
    )
    then I'd suggest that you remove the pModuleManager and use "this" instead.

    As for using protected content, that's where you need to have a member function as well as a non-member function, e.g:
    Code:
    class ModuleManager_c
    {
    ...
    private: 
       int test;
    ...
    public:
       void showTest() { cout << test; }
    ...
    };
    
       void InputThread(ModuleManager_c * pModuleManager ) {cout<<pModuleManager->showTest(); }
    [The above is not complete, I've only posted the lines that are changed versus your original code, and enough original code to see where it's changed].

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  5. #5
    Registered User
    Join Date
    Sep 2008
    Posts
    48
    Ok, thanks matsp. I think it's ok now:
    Code:
    class ModuleManager_c;
     void OutputThread(ModuleManager_c * pModuleManager);
      void InputThread(ModuleManager_c * pModuleManager );
    
    class ModuleManager_c
    { protected:
      HANDLE hInputThread, hOutputThread;
      DWORD dwInputThread, dwOutputThread;
      int test;
     
      
          
          public:
      
      ModuleManager_c(){test=17;}
      ~ModuleManager_c(){}
       void ShowTest() {cout<<test;}
       void Status() {}
       void Start()
       { 
            hInputThread = CreateThread(NULL,NULL,(LPTHREAD_START_ROUTINE)
            InputThread, (LPVOID) this, NULL, &dwInputThread);
            }   
          };
    
       void InputThread(ModuleManager_c * pModuleManager ) {pModuleManager->ShowTest(); }
       void OutputThread(ModuleManager_c * pModuleManager) {}

  6. #6
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Ok, so technically (sorry for not pointing that out before), you should have a void * parameter to your InputThread function, as that is how it is being called from the thread creation function.

    You should then do something like this:
    Code:
    void InputThread(void *pArg ) 
    {
        ModuleManager_c * pModuleManager = reinterpret_cast<ModuleManager_c *>(pArg);
        pModuleManager->ShowTest(); 
    }
    That way, you should be able to take off the (LPTHREAD_START_ROUTINE) cast in the CreateThread function.

    Also be aware that if you call C library functions (e.g. using cout << x), you should use _beginthread or _beginthreadex(), as otherwise, you will leak resources when the thread is terminated.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  7. #7
    Registered User
    Join Date
    Sep 2008
    Posts
    48
    Code:
     class ModuleManager_c;
    unsigned __stdcall ModuleManagerOutputThread(void* pArg );
    unsigned __stdcall ModuleManagerInputThread(void* pArg  );
    
    class ModuleManager_c
    { protected:
      HANDLE hInputThread, hOutputThread;
      DWORD dwInputThread, dwOutputThread;
      unsigned InputThreadID;
     
      
          
          public:
      
      ModuleManager_c(){}
      ~ModuleManager_c(){}
       
       void Status() {}
       void Start()
       { 
            hInputThread =(HANDLE) _beginthreadex(NULL,0, &ModuleManagerInputThread,  
           (LPVOID) this, NULL, &InputThreadID);
            }   
          };
    
    unsigned __stdcall ModuleManagerInputThread(void* pArg ) 
    { ModuleManager_c * pModuleManager = reinterpret_cast<ModuleManager_c *>(pArg);  
      return 0;
    }
    
    
    unsigned __stdcall ModuleManagerOutputThread(void * pArg){ return 0; }
    Any other mistakes?
    Last edited by like_no_other; 04-27-2009 at 08:48 AM.

  8. #8
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Yes, that looks about right.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  9. #9
    Registered User
    Join Date
    Sep 2008
    Posts
    48
    Thanks again.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Mesh Class Design problem
    By sarah22 in forum Game Programming
    Replies: 2
    Last Post: 05-20-2009, 04:52 AM
  2. Getting an error with OpenGL: collect2: ld returned 1 exit status
    By Lorgon Jortle in forum C++ Programming
    Replies: 6
    Last Post: 05-08-2009, 08:18 PM
  3. Class design problem
    By h3ro in forum C++ Programming
    Replies: 10
    Last Post: 12-19-2008, 09:10 AM
  4. My Window Class
    By Epo in forum Game Programming
    Replies: 2
    Last Post: 07-10-2005, 02:33 PM
  5. Replies: 3
    Last Post: 12-03-2001, 01:45 PM