Problem with thread synchronization and multithread processing.

Posted on 1998-07-13
Last Modified: 2010-04-10
First a little background:
I am currently working on a program that waits for data from users via the internet.Currently , it immedialtely processes the information using a thread. I am adding a feature that allows the user to process the information at a time delay instead of immediatey. To do this I created a thread that simply sleeps for the length of the time delay, afterwhich the ProcessData thread is started. I used a critical section as a means of synchronizing the threads (this was necessary because if they were not synchronized I got a C++ runtime error).

The problem that I am having now is that the process waits to deal with the data that is being sent by the user until after the delay from a previous user has been completed. I am currently using WaitForMultipleObjects which  is leading to the problem. Using WaitForSingleObject(DelayThread,INFINITE) and this leads to the same  problem. If I don't have a wait at all I get a C++ runtime error.

Here is my question:
How can I have the program process infromation from one source at a delay and still have it process information from another source that is not at a delay WITHOUT the second set of information having to wait until after the delay thread has been completed for the first set of infromation?

I hope this makes sense.
Question by:delicia071398
LVL 22

Expert Comment

ID: 1167653
>> How can I have the program process infromation from one source at a
>> delay and still have it process information from another source that is
>> not at a delay WITHOUT the second set of information having to
>> wait until after the delay thread has been completed for the first set of
>> infromation?

It is not clear why this problem is occuring.  Why do you think you have to wait?  

Is it that the sleeping (waiting) thread is supposed to handle both sets of data, and is sleeping for one so it doesn't "see" the one that it doesn't need to sleep for?

Is it that there is one set of data (not two) and both forms of processing must occur in the one set?

Or is there something else?


Author Comment

ID: 1167654
If I do not have a WaitForXXXObject(s) I get a C++ runtime error that I have traced back to the call to DelayThread.Which at that time would sleep for the delay time and then call another function the started the ProcessDataThread.

I then redesigned the program so that the the first thread (Thread1) would sleep (and that is it) without calling the function that starts ProcessDataThread(Thread2).Thread2 is supposed to handle both sets of data but Thread1 is not. I use a series of if statements that determine whether or not the data is to be delayed if it is not the _beginthread(Thread1) is bypassed.

As a  sidebar the design for the program is such that each piece if data submited by the user is to be delayed (if necessary) otherwise be processed immediately.There are at any given time any number of users that can be sending data to the program via an application extention (dll) that receives information from the internet.This data may/may not have a time delay. The time delay from one set of data sent to the prgram from the Dll should not affect the processing of another set of data that is sent to the program from that same Dll. The program is designed to run "infinitely" and continually waits for messages from the internet.

Expert Comment

ID: 1167655
The design you describe requires a separate thread for each pice of data which requires a delay. The basic plan would be:

- thread1 is in a loop looking for messages

- if a message comes in which is to be processed immediately, thread1 processes it

- if a message comes in which needs to be delayed, thread1 creates a new thread threadN (where N gets larger as there are simultaneous requests which need delays)

- each threadN sleeps the required time, then wakes up and processes the data itself (without calling thread1). When done, each threadN terminates itself.

The reason this is necessary is if the basic delay mechanism is for a thread to sleep, then either each new piece of data needs its own thread or else it has to wait for the previous delay to be complete so the shared thread is again available. There's no other way.

Having said all that, that's the easiest way to modify your present design to make it work, but it's probably not how I'd do it. Creating a new thread all the time has significant overhead, and you have to be careful to lock common resources with Critical Sections. (One critical section protecting all your data processing sounds feasible, though, since all threads do the same thing).

The other way to do it, and to remain a single-threaded app with all the simplicity that brings, is to maintain your own list of pieces of data awaiting processing. This scenario would work as follows:

- thread is in a loop looking for messages

- if a message comes in which is to be processed immediately, thread processes it

- if a message comes in which needs to be delayed, thread adds it to an array of pending messages along with the current time (obtained from GetTickCount).

- before going back into its message loop, thread always looks into the array to see if any entries are ready to run. This is done by calling GetTickCount to get the current time and seeing which if any of the array entries' time delays have passed. Those who are ready are processed and removed from the array.

- If there are entries in the array, before we go back looking for new messages we need to start a timer, with the time set to the delay for the next array entry which should run. Only one timer is ever used, though - if we already started the timer but haven't received notification yet then no need to do anything here. The timer doesn't actually directly time the delays, it is there to wake up the thread so it can check its array.

Let me know if you need clarification... if what I said helps I'll repost it as an answer. Good luck!
Live: Real-Time Solutions, Start Here

Receive instant 1:1 support from technology experts, using our real-time conversation and whiteboard interface. Your first 5 minutes are always free.


Expert Comment

ID: 1167656
Hello Delicia!
I suggest that you establish two queues for the information processing. One queue would be the delay queue, the other would be the immediate queue.
Data entered into the delay queue is associated with a time stamp.
Both queues should be monitored for explosion prevention (for example, requests are not admitted for length of queue exceeding 20).
The thread polls both queues. If the immediate queue is non empty, all requests need to be processed.
The Delay queue is monitored, and using the time stamp, requests are served "when ripe".
Note, that this mechanism also allows you to balance both queues with the introduction of queue balancing policy: For example, no more than x immediate requests are served before the delay queue is polled; Delayed requests that have not been served when due may be entered in front of the immediate queue.
Good luck, Roni

Author Comment

ID: 1167657

Your answer to the question was great. I used the array to store the messages and that alleviated the problem without having to deal with the overhead of continually creating new threads.

I need clarification on the use of GetTick Count though I have never used it before. Am I correct in saying that the count is represented in milliseconds? and is returned as a DWORD? Also how would I know which message is to be sent next . Would I have to loop through the array to find the next message to go that i snot one of the messages whose delay has expired?

Accepted Solution

alamo earned 100 total points
ID: 1167658
Glad it helped you!

GetTickCount() is my preference for a quick easy timestamp... yes it's milliseconds since Windows was booted, returned in a DWORD. It's not a good timestamp if you need precision in your delays, the value is in milliseconds but is only updates every 10ms or so, and sometimes falls behind if the system is busy.

DWORD dwNow = GetTickCount();
if (dwNow - timestamp) >= delaytime) etc.

[Note that you shouldn't say if (dwNow <= timestamp+delaytime) because the DWORD overflows every 50 days or so and the comparison will fail... the one I gave you will still work.]

As to which message to send next... if all messages have the same delay, you can just look at the end of the array where the oldest message is and check its timestamp (it's functioning as a queue). If however different message have different delays, you will have to check each entry in the array to find which entries' delay has expired and thus are ready to be processed.

Featured Post

Gigs: Get Your Project Delivered by an Expert

Select from freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely and get projects done right.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
What does std::atomic give me? 7 123
C Language combined operators 28 109
C++ standard library based binary archive format 6 98
How can i compile this github project?? 2 82
Introduction This article is the first in a series of articles about the C/C++ Visual Studio Express debugger.  It provides a quick start guide in using the debugger. Part 2 focuses on additional topics in breakpoints.  Lastly, Part 3 focuses on th…
IntroductionThis article is the second in a three part article series on the Visual Studio 2008 Debugger.  It provides tips in setting and using breakpoints. If not familiar with this debugger, you can find a basic introduction in the EE article loc…
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.

808 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question