CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 10 of 10
  1. #1
    Join Date
    Nov 2010
    Posts
    30

    [RESOLVED] Start thread within a object, and have acces to it aswell

    Hello everyone,

    I found a similar thread that talked more or less about the same issue but it was 6 years old so I decided to start this thread.

    Before we start I have read the: http://www.codeguru.com/forum/showthread.php?t=312452 FAQ but that didn't help much.

    I have the following:
    A .dll made in vc++ 2010. This library contains many classes of which one needs to create an actual thread to work called CSoftPLC (guess what it does :P). This method has the function "StartPLC()" which creates the thread, and "StopPLC()"... Well you get the picture. The library compiles perfectly, not even warnings emerge and the thread also starts fine. The only thing that doesn't work is that the thread cannot acces the class that created it eventhough i pass it as a pointer as the lpArg parameter.

    The class SoftPLC has a bunch of flags indicating if the thread encountered an error , some functions that it needs to execute etc and is therefor quite large. Here is a snippet that is concerned:

    Code:
    .h File: (propperly exported etc)
    class DECLDIR CSoftPLC
    {
    protected:
    	int _nErrNo ;
    	int _nState;
    	int _nWDTtime;
    	int _nCycleTime;
    	int _nActualCycleTime;
    
    	//Threading items
    	bool _bRunThread;       <-- if this goes low the thread should stop(normally)
    	DWORD ThreadID;
    	HANDLE _hProcThread;
                    static DWORD _ThreadProc(LPVOID lpArg);
    public:
    	CSoftPLC(void);
    	int StartPLC(void);
    	int StopPLC(void);
    	void Dispose(void);
    	virtual ~CSoftPLC(void);
    };
    
    .cpp file:
    #pragma region Public Routines
    	int CSoftPLC::StartPLC(void)
    	{
    		this->_bRunThread = true;	
    		this->_hProcThread = CreateThread(NULL, 0x100,
                                                     (LPTHREAD_START_ROUTINE)CSoftPLC::_ThreadProc,
                                                     (LPVOID)this,
                                                     0, 
                                                     &ThreadID);
    		if( this->_hProcThread = NULL)
    		{
    			return 1;
    		}
    		return 0;
    	}
    
    	int CSoftPLC::StopPLC(void)
    	{
    		if(this->_hProcThread)
    		{
    			this->_bRunThread = false;
    			return 0;
    		}
    		return 1;
    	}
    #pragma endregion
    	
    #pragma region PLC Proces
    	DWORD CSoftPLC::_ThreadProc(LPVOID lpArg)
    	{
    		//Variables
    		CSoftPLC* myPLC = (CSoftPLC*)lpArg;
    		myPLC = (CSoftPLC *)lpArg;
    		unsigned int i = 1;
    		while( (myPLC->_bRunThread) && (i > 0))
    		{
    			myPLC->_nState |= RUNNING;	      //Set flag running
    			cout << "blabla:" << i;
    			i++;
    		}
    		myPLC->_nState &= ~RUNNING;				//Reset flag running
    		return NULL;
    	}
    #pragma endregion
    I see the problem of the thread not beïng allowed acces to the private members of the object creating it (and passing itself as a parameter) as the ThreadStart requires a "static" type function. Is there a way that the thread can access these members whithout making them public? Those members need to be and stay protected if possible and are only accessable with functions.

    T.Y.I.A.

    Crash.

  2. #2
    Join Date
    Nov 2010
    Posts
    30

    Re: Start thread within a object, and have acces to it aswell

    Hrrrm even if _bRunThread is public it is completely ignored...

  3. #3
    Join Date
    Nov 2003
    Posts
    1,902

    Re: Start thread within a object, and have acces to it aswell

    Code:
    this->_hProcThread = CreateThread(NULL, 0x100,
                                      (LPTHREAD_START_ROUTINE)CSoftPLC::_ThreadProc,
    Just pass in 0 for the stack size and let the OS do it's thing.
    Never cast a function pointer parameter. If the compiler rejects it, then it's wrong.

    >> this->_bRunThread = false;
    This is unsynchronized access by multiple threads to the same memory location - which is bad. You can protect access using a critical section, or use a Win32 Event to signal the thread that it's time to exit. (Don't be tempted to slap "volatile" on it, as that keyword has nothing to do with multi-threading and will only prevent the compiler from performing optimization.)

    If multiple thread access the same memory location, and at least of them is writing, then you must provide synchronization using the primitives provided by your threading library.
    http://msdn.microsoft.com/en-us/libr...8VS.85%29.aspx

    >> Is there a way that the thread can access these members whithout making them public?
    _ThreadProc is member of the class, and therefore can access public, private, and protected members. Because it's static, it doesn't have a "this" pointer, and therefore needs a instance of the class to access - which is provided via lpArg.

    gg

  4. #4
    Join Date
    Nov 2010
    Posts
    30

    Re: Start thread within a object, and have acces to it aswell

    Ty Codeplug for the swift response, I understand that it needs some sync clauses :P but I was just testing out threads with C++ as I have never used it there. (I do a lot with vb.net and c# but as this is a performance critical application I wanted to programm it in C++)

    Correct me if I am wrong:

    Eventhough the variable isn't synclocked, the thread should still be able to reach it even if there is garbage written in there? (may that be dangerous or not)

    I understand that the pointer cast here is wrong or I shouldn't do that:

    Code:
    (LPTHREAD_START_ROUTINE)CSoftPLC::_ThreadProc,
    May I then assume that placing "WINAPI" or __stdcall in the headerfile is acceptable? Else it would be impossible to create a threadstart "OK" function?.

    Code:
    static DWORD __stdcall _ThreadProc(LPVOID lpArg);
    The I didn't know the static keyword story like you explained it funcioned like that, I was alway's was under the impression it would then become a new entity on it's own Ty for that

    I'm reading up on the Syncobject for the api, bit more work then synclock :P

  5. #5
    Join Date
    Nov 2003
    Posts
    1,902

    Re: Start thread within a object, and have acces to it aswell

    >> thread should still be able to reach it even if there is garbage written in there?
    Nope. There are no "visibility" guarantees with unsynchronized access. The threads may never see what others have written. Just think of it as "undefined behavior" - you could dig into why your particular compiler/OS/architecture does what it does, but in the end you just don't do it on any platform.

    >> May I then assume that placing "WINAPI" or __stdcall in the headerfile is acceptable?
    Since you're using CreateThread(), you should use WINAPI: http://msdn.microsoft.com/en-us/libr...8VS.85%29.aspx

    A common technique used is to just have your static "_ThreadProc" do nothing but call a non-static, normal member function of the class , eg. "return myPLC->ThreadProc()". Then you don't have to type "myPLC->" for every non-static member access.

    gg

  6. #6
    Join Date
    Nov 2010
    Posts
    30

    Thumbs up Re: Start thread within a object, and have acces to it aswell

    I certainly agree with the last part, the PLC process is cut up in a bunch of functions( 7 to be exact), even where it to only maintain readability.

    Everything works now, the thread now reacts to the stop command. I still have to figure out how the critical section realy works in it's behaviour.

    Ty for the help CodePlug.

  7. #7
    Join Date
    Nov 2010
    Posts
    30

    Re: Start thread within a object, and have acces to it aswell

    Good lord, a critical section makes the performance drop by almost 1700&#37;!?!

  8. #8
    Join Date
    Nov 2003
    Posts
    1,902

    Re: Start thread within a object, and have acces to it aswell

    What if I said: "performing 3/1 is ten times slower than 3/0"?

    Comparing correct to broken is pointless. We can't even assume the "correct" part, since we haven't seen any code or how you profiled.

    Effective and efficient design of multi-threaded applications is not something learned "in 21 days"

    gg

  9. #9
    Join Date
    Nov 2010
    Posts
    30

    Re: Start thread within a object, and have acces to it aswell

    In fact it's not even in there at all! hahaha :P

  10. #10
    Join Date
    Nov 2010
    Posts
    30

    Red face Re: Start thread within a object, and have acces to it aswell

    I must stand corrected, I forgot how dubious doubles are in C++ and how they never make sense :P, The performance drop wasn't 3 ms (or 1700% in my case) but more in the lines of 0.04 uSecs which is just a factor 100000 smaller. Small details :P

    So performance drop by critical section is more in the lines of 0.017% which is a very acceptable drop .

    (for me ofc. And it realy makes sense now, I had a semi heartattack when I saw the previous performance calculation. It almost wanted me to abort what I was doing and go back to vb.net :P

    I migrated to C++ to increase performance significantly as .net has a lot of unececary overhead, couldn't get the cycletime get under 100ms which was acceptable for that simple machine but the next one will be a lot bigger and more complex.)

    The multi timer module I designed now runs on a 50ms clock with an acuracy of 0.0001 of a ms which makes me love c++ again :P.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured