🔒 Locked
Thread Inter-Syncronization
Advertisement
Original Post
Ok, here is my problem: - A is a Socket Data Receiving Thread - B is processing Data, and Sending it out to a Client - A must signal B that data has arrived - B is allways alive, so geting some sort of signal from A is relatively simple using some sort of Mutex or something - Problem comes when 1) A must know that B has processed its data and 2) A cannot continue until B as processed its data. But I do not want to have A busy waiting for B, I would like to find a way to block the A thread, have a blocking wait, instead of a busy wait, where A sits in a loop asking "has B processed the data, can I continue?". Any ideas?
Use a semaphore, or implement something like:
Where Thread::yield is a function that sleeps the current thread.
bool waitBool(bool evaluate){ while (!evaluate) { Thread::yield(); }};Where Thread::yield is a function that sleeps the current thread.
Hi,
Are you on a windows system? If you are, then I would recommend asynchronous I/O or I/O Completion ports... MSDN has good articles on them...
If you're not, have a look at the boost thread library.. they have some good synch objects... They have one that is really good that I used to help with the reader/writer problem that you are describing...
Are you on a windows system? If you are, then I would recommend asynchronous I/O or I/O Completion ports... MSDN has good articles on them...
If you're not, have a look at the boost thread library.. they have some good synch objects... They have one that is really good that I used to help with the reader/writer problem that you are describing...
Quote:
Original post by vetroXL
Hi,
Are you on a windows system? If you are, then I would recommend asynchronous I/O or I/O Completion ports... MSDN has good articles on them...
If you're not, have a look at the boost thread library.. they have some good synch objects... They have one that is really good that I used to help with the reader/writer problem that you are describing...
Thanks for the reply.
Yes, this is a Windows 2000/XP Project, and also for PDAs (WinCE). I really don't have the time nor the energy to go into boost for this, and any solution I find must work on both platforms...
@kuphryn: Could you please elaborate? Where would GDNet be without single-word replies...
Ahh, well then Boost is out of the question if you're on a PDA system... I would recomend looking up Asynchrousouse I/O or I/O Completion ports.. you'll have to decide which one works best for you situation... but they both have built in notification schemes to help with synch issues...
I use I/O completion ports if I have to build a large scalable server... but Asycnh I/o is fine if you have less then 64 simultaneous clients (sp) or if you writting a client.
I use I/O completion ports if I have to build a large scalable server... but Asycnh I/o is fine if you have less then 64 simultaneous clients (sp) or if you writting a client.
Quote:
Original post by vetroXL
Ahh, well then Boost is out of the question if you're on a PDA system... I would recomend looking up Asynchrousouse I/O or I/O Completion ports.. you'll have to decide which one works best for you situation... but they both have built in notification schemes to help with synch issues...
I use I/O completion ports if I have to build a large scalable server... but Asycnh I/o is fine if you have less then 64 simultaneous clients (sp) or if you want a client.
Nope, not a solution either, I've already built a whole system around this design, so I'm not going to go in another direction at the first sight of trouble, eheh...
I just need a way to block A, and have B unblock A.
Well, as you know I've just completed the threaded part of my resource loader, and it uses Boost::Condition for exactly what you want.
If you're not willing to use Boost for this, you can always see how they've implemented it. The Boost::Thread library seems pretty small, so it shouldn't be that hard.
Other than that, the term you need to search for is 'conditional variable'.
If you're not willing to use Boost for this, you can always see how they've implemented it. The Boost::Thread library seems pretty small, so it shouldn't be that hard.
Other than that, the term you need to search for is 'conditional variable'.
Quote:
Original post by vetroXL
wow! tough customer ;)
Have tried an event based system like this?
Lock( DWORD dwTimeWait = INFINITE )
{
WaitForSingleObject( m_hLock, dwTimeWait );
ResetEvent( m_hLock );
}
UnLock()
{
SetEvent( m_hLock );
}
Thanks VetroXL, I've worked with Threads and mutexes before, but I don't yet have experience with Events. Are Events used to signal other Threads? What API calls should I be looking at?
Rate++ [wink]
Hi,
They are used for those purposes exactly, light weight signal objects...
CreateEvent is what is used above, they are Manual reset events, not Auto reset events... (btw I use that in production code on a distributed-parallel-warfare-simulaiton-system )
You can also use OpenEvent to open exsiting events...
THe semantics are the same as the mutuxes...
Tthanks for the Rate++
They are used for those purposes exactly, light weight signal objects...
CreateEvent is what is used above, they are Manual reset events, not Auto reset events... (btw I use that in production code on a distributed-parallel-warfare-simulaiton-system )
You can also use OpenEvent to open exsiting events...
THe semantics are the same as the mutuxes...
Tthanks for the Rate++
You shouldn;t have A waiting on B at all. You should have A waiting on its socket and posting the data it reads to a work queue. B needs to be waiting on the work queue.
A would be structured like this.
B would be structured like this.
Granted, you need to have an additional mutex guarding your queue so you can enqueue/unqueue multiple data packets without deadlock, but that's the idea. Each thread has one and only one loop invariant on which it will block while the invariant does not hold, and those invariants are different. Anything else is just inviting either deadlock or starvation.
A would be structured like this.
loop forever wait for data to appear on socket read socket into buffer grab queue mutex enqueue data signal queue-not-empty condition ungrab queue mutex end loopB would be structured like this.
grab queue mutex loop forever wait on queue-not-empty condition unqueue data process data end loopGranted, you need to have an additional mutex guarding your queue so you can enqueue/unqueue multiple data packets without deadlock, but that's the idea. Each thread has one and only one loop invariant on which it will block while the invariant does not hold, and those invariants are different. Anything else is just inviting either deadlock or starvation.
actually sounds more like a producer-consumer problem. i'd use a mutex to control access to shared data and multiple events to signal B has finished processing and B can process data. A can only continue when it has the mutex and B has finished processing (which is what I think you want).
A
-
1.) A (the producer) waits for the mutex.
2.) if the buffer is full or has enough data to be processed, then you release the mutex and wait until B has signaled the finished processing event.
3.) Repeat 1 and 2 until you have both the mutex and "B has finished processing" event.
4.) Produce more data.
5.) If there's enough data from B to consume, pulse a "B can process" event.
B
-
1.) B (the consumer) waits for the mutex.
2.) If there is nothing or not enough to consume, release the mutex and wait for the "B can process" event.
3.) Otherwise, if there is data to consume, process it, release the mutex, and pulse the "B has finished processing" event.
A
-
1.) A (the producer) waits for the mutex.
2.) if the buffer is full or has enough data to be processed, then you release the mutex and wait until B has signaled the finished processing event.
3.) Repeat 1 and 2 until you have both the mutex and "B has finished processing" event.
4.) Produce more data.
5.) If there's enough data from B to consume, pulse a "B can process" event.
B
-
1.) B (the consumer) waits for the mutex.
2.) If there is nothing or not enough to consume, release the mutex and wait for the "B can process" event.
3.) Otherwise, if there is data to consume, process it, release the mutex, and pulse the "B has finished processing" event.
Topic Locked
This topic has been locked by a moderator. New replies are not allowed.
Sign in to reply to this topic.
Advertisement