• Advertisement
Sign in to follow this  

Threading Data Sharing(Solved)

This topic is 4252 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Back with more threading problems: Okay I have two threads , each are both basically two loops. They are both operating on the same data list. Now, each element in the list has a critical section like so: me[x]->Edit(); //enter critical section // do stuff to me me[x]->DoneEdit(); // leave the problem is I think that Thread1 has not sent it's me[x] back into memory, even after it leaves the critical section. And while Thread2 is operating on it, Thread1 writes to memory. How can I make sure that both these threads can operate on the same data? Without locking out the whole list? Thanks again [Edited by - MetaKnight on June 1, 2006 2:13:37 PM]

Share this post


Link to post
Share on other sites
Advertisement
Try making m[x] volatile by using the volitile keyword. This will keep the compiler from doing some optimizations like you describe

Share this post


Link to post
Share on other sites
Hmmm, I kinda doubt making it volatile is going to solve his problem. In fact I doubt it has anything to do with one of the threads not having written its data back to memory, but it's hard to see what might be causing this unless you post the relevant code here. I'd be interested to see the actual loops as well as the implementations of the Edit() and DoneEdit() methods.

Share this post


Link to post
Share on other sites
Quote:
Original post by MetaKnight
How can I make sure that both these threads can operate on the same data? Without locking out the whole list?


Your threads are not changing the list itself, only the elements contained therein, right? If so, mutex-protecting the whole list isn't going to do anything for you since you've already given the individual list elements mutex protection.

Share this post


Link to post
Share on other sites
According to this that's exactly what volatile would do (in the given example). Other than that though I have no other ideas, I'm not really a multithreaded programmer.

Share this post


Link to post
Share on other sites
Quote:
Original post by MetaKnight
me[x]->Edit(); //enter critical section
// do stuff to me
me[x]->DoneEdit(); // leave


This is one of the most important uses of the RAII idiom.

class Locker {
public:
Locker(Me& me)
: m_me(me)
{ m_me.Edit(); }

~Locker()
{ m_me.DoneEdit(); }

private:
Me& m_me;
};

// somewhere in code
{
Locker lock(*me[x]);
// .. do something with me
} // guaranteed critical section release

Share this post


Link to post
Share on other sites
Quote:
Original post by perfectly_dark
According to this that's exactly what volatile would do (in the given example). Other than that though I have no other ideas, I'm not really a multithreaded programmer.



From the article you posted:

Quote:

In short, data shared between threads is conceptually volatile outside a critical section, and non-volatile inside a critical section.


There you have it. If you're correctly using mutex-protection, there is no way your variable can somehow get corrupted by another thread. Shared data may very well be volatile in nature outside of critical sections, but who cares? If you're in any way accessing shared data outside a critical section then you're doing something that you MUST not do, and your program is simply incorrect. IMHO.

Share this post


Link to post
Share on other sites
okay I took out all the weird parts of my code and ran this, and it still has the same problem so here is the data for each thread:

this is what edit and done-edit look like

gameNode::gameNode()
{
InitializeCriticalSection(&mySection);
}
void gameNode::Edit()
{
EnterCriticalSection(&mySection);
}
void gameNode::DoneEdit()
{
LeaveCriticalSection(&mySection);
}




this is what the first thread basicaly looks like

gameNode *gameRunner = NULL;

for(list<gameNode*>::iterator iter = gameList.begin();iter != gameList.end();iter++)
{
gameRunner = (*iter);
gameRunner->Edit();
gameRunner->Run();
gameRunner->DoneEdit();
}



and the other thread looks the same except insted of ->Run is ->Draw


Now when I try to make
gameNode *gameRunner = NULL;
into
volatile gameNode *gameRunner = NULL;


but then each funtion gets an error like so:

error C2662: 'gameNode::DoneEdit' : cannot convert 'this' pointer from 'volatile gameNode' to 'gameNode &'


error C2662: 'gameNode::Edit' : cannot convert 'this' pointer from 'volatile gameNode' to 'gameNode &'

error C2662: 'gameNode::Run' : cannot convert 'this' pointer from 'volatile gameNode' to 'gameNode &'


Ive never had to use volatile before, I have always issumed that Critial section took care of this for me.



Share this post


Link to post
Share on other sites
Quote:
There you have it. If you're correctly using mutex-protection, there is no way your variable can somehow get corrupted by another thread. Shared data may very well be volatile in nature outside of critical sections, but who cares? If you're in any way accessing shared data outside a critical section then you're doing something that you MUST not do, and your program is simply incorrect. IMHO.


Ah, I understand now. As I said, I'm not really a multithreaded programmer [grin]

Share this post


Link to post
Share on other sites
MetaKnight, the code you've posted looks fine to me. Each thread is properly acquiring / releasing a lock on the mutex before doing stuff with a list element, which is how it should be. The problem must be elsewhere. What exactly are the symptoms of your problem?

Quote:
Original post by MetaKnight
Ive never had to use volatile before, I have always issumed that Critial section took care of this for me.


That's because it does. Most programmers won't ever have to mess with 'volatile' unless they're writing some low level device driver or something. In your case, volatile won't change a thing at all ... except maybe stop the compiler from doing its job by optimizing the code.

Share this post


Link to post
Share on other sites
Although this presumably has no bearing on the actual problem, you probably should have used volatile like so:

GameNode * volatile gameRunner = NULL;


jfl.

Share this post


Link to post
Share on other sites
The symptom is that when my object is moving ( Run() is changing the objects position and oreienting it in space) the object shakes and sometimes goes back to prevoius positions.

Say is how Thread2 is now:

gameNode *gameRunner = NULL;

for(list<gameNode*>::iterator iter = gameList.begin();iter != gameList.end();iter++)
{
gameRunner = (*iter);
gameRunner->Edit();
gameRunner->Draw();
gameRunner->DoneEdit();
}




if I do this, and comment out the ->Run() from Thread1

gameNode *gameRunner = NULL;

for(list<gameNode*>::iterator iter = gameList.begin();iter != gameList.end();iter++)
{
gameRunner = (*iter);
gameRunner->Edit();
gameRunner->Run(); // now moved from Thread1 to here
gameRunner->Draw();
gameRunner->DoneEdit();
}




So serializtion fixes it, I know that the threading is what is causing the problem

Share this post


Link to post
Share on other sites
Hmmm, this may be a silly question but since your program involves drawing stuff on the screen, is the thread that does the drawing your main thread? Because AFAIK generally only the main thread of an application is supposed to draw things on the screen (other threads may do this, too, but it normally involves locking some GUI mutex or something like that). Just trying to rule out all potential sources of trouble as I still don't see any errors in your code.

P.S. Also, do both your loops run roughly at the same speed? In a given amount of time, do you expect them to run roughly the same number of times? Have you taken any steps to prevent your first thread from updating the position of your objects 1000 times a second but your second thread only drawing the objects 50 times a second?

Share this post


Link to post
Share on other sites
Make sure your pointer has as local a scope as possible.

for(list<gameNode*>::iterator iter = gameList.begin();iter != gameList.end();iter++)
{
(*iter)->Edit();
(*iter)->Draw();
(*iter)->DoneEdit();
}

Share this post


Link to post
Share on other sites
Quote:
Original post by Red Ant
Hmmm, this may be a silly question but since your program involves drawing stuff on the screen, is the thread that does the drawing your main thread? Because AFAIK generally only the main thread of an application is supposed to draw things on the screen (other threads may do this, too, but it normally involves locking some GUI mutex or something like that). Just trying to rule out all potential sources of trouble as I still don't see any errors in your code.

P.S. Also, do both your loops run roughly at the same speed? In a given amount of time, do you expect them to run roughly the same number of times? Have you taken any steps to prevent your first thread from updating the position of your objects 1000 times a second but your second thread only drawing the objects 50 times a second?


Well the main thread is just a dos console, but the drawing thread has the window and directx objects. Also if I move everything to the drawing thread it works perfectly.

Also yes, by using events both threads only go only once. If the Game thread is fast, it'll wait for the draw thread to finish.

Share this post


Link to post
Share on other sites
Quote:
Original post by Bregma
Make sure your pointer has as local a scope as possible.

for(list<gameNode*>::iterator iter = gameList.begin();iter != gameList.end();iter++)
{
(*iter)->Edit();
(*iter)->Draw();
(*iter)->DoneEdit();
}



Just tried it and It did not seem to work.
Oh yes, and just to let anyone know, the first thread is the only thread that actuly edits the data. The second thread only reads and draws the objects.

Share this post


Link to post
Share on other sites
Ah found it! When someone sugested that it might be somewhere else, I kept looking around and it was a multithreading problem but it was the Camera for the Thread2. The camera was getting the pos of the object from the list, and I was using the Edit()/DoneEdit(), but the object position changes, or sometimes the camera gets the last position of the object and that's what caused the shaking.


Thread 1 | Thread 2
Player Run(1) |
| Setup Camera to Player(1)
Loop |
Player Run(2) |
| Draw Player(2)



Thanks very much for everyone that posted

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement