• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 292
  • Last Modified:

Need input on how to arrange a project with multiple threads

Greetings:

I have a Form Application that runs three threads.  I started the project by creating three group boxes which represent each thread.  Each group box displays a few data fields.  Each group box is activated by a 'View' menu that kicks off the thread.  Thus, the Form may display data from all three threads or any combination.

I'm now at the point where I can see the need for one additional thread but this thread would not be to display any data.  This additional thread (call it thread_4) would only serve to store data from each of the other threads running - if in fact they were running.

Of the three threads that display data, we can say that there is one which is most important (call it thread_1).  If thread_1 is not running, the fourth thread (responsible for storing data) will not store anything.  If the thread_1 is running, thread_4 will create a queue and order that queue by the contents of thread_1.  Thread_4 will store an object in the queue that contains data from each thread.  Thus, at a minimum, the queue would hold an object for every item declared by thread_1... if the other threads were running, their data would be included in each object of the queue.

The logic that determines how the object is filled isn't so important right now as much as what the object looks like:

struct GlobalDataObject {
         thread_1  *thread_1_data;  // determines order in the queue
         thread_2  *thread_2_data;
         thread_3  *thread_3_data;
}

This is the general idea of what I'm trying to accomplish.  Additional points for calification would be:

Form1 would create a total of 4 threads at the max
Thread_4 handles all signaling and waits for all threads to exit.
GlobalDataObject is a notification queue which handles all notifications between threads.
The queue is a vector<Notification> protected by a mutex,
Notification is an enum.
Thread_4 is derived from GlobalDataObject
The threads use signals to set stop conditions and signal when they are exiting.

Hence - I need help arranging this kind of setup.  If more details are needed, you can refer to the following question:

http:Q_21860993.html

0
John500
Asked:
John500
  • 11
  • 6
  • 6
  • +1
2 Solutions
 
DanRollinsCommented:
>> This additional thread (call it thread_4) would only serve to store data ..

I think this statement indicates a conceptual problerm.  Threads don't "store data" -- they process sequences of instructions.

I think that you should create an object that is not associated with any new thread.  That object is used to record the data.  For example, let's call this an "event logging" object (even if that is not what it does, I think the concepts are similar).  

Now each thread's instructions include calls to the logging object to log events.  It knows what to log and what to ignore (e.g., if thread_1 is not operating, then it knows to ignore events logged by threads 2 and 3.)  It knows any special actions to take when certain events are logged.  You can provide a View that accesses its functions to display info about the events that have been logged.

If you need to, for instance, off-load the logged event from memory to disk, you can do that periodically... eg, whenever there are 1000 events saved, or every few seconds as triggered by a windows timer, or whatever.   There is no need to have a separate thread of execution to do that.

-- Dan
0
 
John500Author Commented:
Dan,

Ok, yes.  You are right this is what I'm trying to do.  But instead of logging events, I'm building a queue that is ordered by thread_1 notification.  When thread_1 notifies thread_4 that it has new data, thread_4 should help to manage a queue.  Somewhere between thread_1 notification and thread_4's acknowledgement, a queue has to be created and ordered.

Where do I begin.  I noticed you provided input to this same question but located here:

http:Q_21853899.html

I asked for this to be deleted because of the inactivity.  I'm sure this inactivity is due in part to the fact that I haven't been wording the question well.  This is yet a third attempt to present the facts more abstractly.  I think you hit the nail on the head.

It's been almost four days since my request to delete so you don't need to respond there unless you want to say "go ahead and delete the question."

Standing by
0
 
Knut HunstadCommented:
Since I'm the one to recommend you beeing a little less detailed, I will this time go the opposite way :-)

If you now describe:

- which of your objects you think of as Thread_1... Thread_4 (I am guessing Thread_4 is Tower?)
- can there be more than 1 of any of the thread types?
- what is the "index" in the queue, that Thread_1 notifies about?
- where are you planning to let Thread_1 objects be created?
- Is Thread_4 simply logging notifications or also handling events and sending notifications back to one or more threads?

then it might be easier coming with concrete suggestions. The problem for us trying to help you, is separating the real demands to the application from your thoughts about how to solve it.
0
Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

 
DanRollinsCommented:
I've read a couple of these Qs, and the impression I formed is that you are getting bogged down with details without having formed the broader-stroke plan.

For instance, what if you didn't have all of these separate threads of execution?  Multi-threading adds thick levels of complexity to what could otherwise be a very simple system.  

For instance, in real life, the Air Traffic Controller (in the Tower) is not constantly bombarded with Wind speed/direction readings.  Imagine that he just pressed a button to see what they are.  The parallel is that he sends a message to the Wind-recording object and it tells him the current settings.

Also, in real life, we do things sequentially... sometimes several things queue up, but as long as we are processing events normally, we keep a handle on things.  Think about driving a car... you look in the rear-view mirror, then you look at the speedometer, then you adjust the radio, then you turn the steering wheel slightly... you don't do all of these things at the same time.  Nevertheless, you are getting them all done.

A "polling" scenario may be much easier to handle.  Check the wind.  Check the radar.  Check the list of incoming aircraft ... then cycle back around to check the wind.  Write these objects in simple single-threaded fashion.  The computer runs fast enough that you can cycle through polling and updating all of these objects in a few milliseconds (effectively instantaeoulsy) -- and you'll avoid the complexity of doing all kinds of special stuff to avoid problems if several things happen "at once."

Use a pencil and paper to draw a picture of the system.  Draw the objects with arrow pointing to which ones send data to where.  Once your design is firm and clear in your head, then start coding up the simplest possible version of those objects.  You can add complexity, such as multi-tasking later on.

-- Dan
0
 
John500Author Commented:
Guys - thanks !

Khun writes:

>> The problem for us trying to help you, is separating the real demands ...
Gotcha

>> which of your objects do you think of as Thread_1... Thread_4 (I am guessing Thread_4 is Tower?)
Yes, thread_4 is the Tower

>> can there be more than 1 of any of the thread types?
No, never.  Three threads read sockets from a network and report on the data.  The data is sent from a simulator and can be summed up easily this way:

thread_1       aircraft data, most importantly line-up for landing or take-off.  Therefore this thread is used to order the
                    queue or queues.  Just one for now will do (landing)
thread_2       radar data - i.e. speed and distance
thread_3       wind data - spead and direction

- where are you planning to let Thread_1 objects be created?

Right now all 3 threads above are started from the 'View' drop down menu.  I need to keep this design because the application needs to be robust enough to test reciept of any transmission or any combination.  On the other hand, if the user wants to see all the data, that option is there.  Lastly, if the user wants to test launch & recovery the tower class will allow for that - see what I mean ?  The tower is there if needed but it is not mandatory.

- Is Thread_4 simply logging notifications or also handling events and sending notifications back to one or more threads?
That's where you guys come in.  I need a method whereby I can achieve the above results.  A method that won't resulut in collisions with resources.  Look at it this way --> these threads are already in place and storing data for display.  Their own containers have already been established.  The tower will enable me to implement a global container where each thread can deposit its data, or as Dan states, it would be available for polling.

Dan writes:
>> ... that you are getting bogged down with details without having formed the broader-stroke plan.
This is true.

>> For instance, what if you didn't have all of these separate threads of execution?
As you see now, I can't go that way

>> Imagine that he just pressed a button to see what they are.
I'm with you here but this can still be the approach regardless

>>  we do things sequentially... sometimes several things queue up
right, that should be the case here.  For now just the one queue but I can duplicate later

>>  A "polling" scenario may be much easier to handle.  
If this is possible with my requirements, that would be the ticket most likely

>> Draw the objects with arrow pointing to which ones send data to where
We might all agree that I've accomplished this necessary objective by virtue of my explanation.  The difficult point thus far has been for me to communicate my requirement without clouding the issue with all the extra 'stuff' I've been adding --> like menu code.

Gentleman, what shall we do ?

(o o)
   l
  ~


0
 
Knut HunstadCommented:
Like Dan, I am starting to get problems accepting your starting point! You don't really seem to need threads here! If you are willing to let go of that, let us know! I am sorry, but I can't quite make out if you are trying to tell that the 3 threads are already working and you don't want to change that or maybe you just want to use threads for excersise or whatever.

My interpretation of what you write is:

- you already have 3 threads collecting data from sockets and displaying it in Form1, in unordered fashion.
- all data are related to specific aircrafts.
- you want a "tower" that receives the same data from all threads and sorts it so you can make another display where all types of information is presented aircraft by aircraft.

If this is the case, I would at least implement the tower functionality in the main application, no need for an extra thread for that. The main application already is getting the data from the threads, so all you need is a container to put it into so you can sort it. The container would be a class with e.g.:

StoreRadarInfo(Aircraft, RadarInfo);
StoreWindData(Aircraft, WindData);
StoreAircraftData(Aircraft, AircraftData);

each of them creating a new aircraft if the aircraft doesn't exist already.

Question: [the tower can also initialize "launch & recovery"]. What does that mean? A message through a socket to the simulator, which in turn sends back messages through sockets to the other 3 threads? Or does it mean messages directly to the other threads, to simulate a reception of a message from the threads socket?
0
 
John500Author Commented:
>> You don't really seem to need threads here!
I do because all the data I've mentioned is traveling through the network from other systems/simulators which are capable of transmitting such data - i.e --> aircraft line-up, radar, wind

The first requirement of my Panel (or Form) is to display this data.  It gives the user a visual, something to judge, to see, to feel comfortable about in terms of the systems which are transmitting.  That is, my panel does in fact collect the data, and the data is in fact being transmitted correclty.  We know it is correct because if we pick up the phone and say, "hey Joe - are transmitting Wind data that is 50 knots at 360 degrees ?"  Joe says, "Yep".

This was my first requirement.  To show I could write code that would collect the data from three different sources.  This requires three separate threads.

>> I can't quite make out if you are trying to tell us that the 3 threads are already working
It's a done deal, as in months gone by.  Sorry for not making that clear.   I want to bring it to the next level by creating launch and recovery decision capability - or a tower.  It will be based on three simple factors:

>> you want a "tower" that receives the same data from all threads and sorts it so you can make another display
Yes, I want to have one more GroupBox that shows a GO/NOGO status along with the aircraft side number.  The GO/NOGO status refers to whether the plane can land

thread_1       aircraft data, most importantly line-up for landing or take-off.  Therefore this thread is used to order the
                    queue or queues.  Just one for now will do (landing)
thread_2       radar data - i.e. speed and distance
thread_3       wind data - spead and direction

>> -all data are related to specific aircrafts
thread_1       can introduce multiple aircraft with the data it collects and this data primarily provides line-up along with
                    aircraft side number
thread_2       provides the radar information along with aircraft side number
thread_ 3      provides wind regardless of aircraft.  It is a constant in terms of constantly being transmitted regardless

>> so all you need is a container to put it into so you can sort it
I like the idea of just needing another container but I don't think the updates to that container will be without collision.  Hence I need a mutex or a way to avoid dead-lock.  The data from each socket/thread is being collected constantly.  Once the thread is on, it's reading from the network non-stop.  This means that any container accessed by the threads and the tower thread will compete.

>> each of them creating a new aircraft if the aircraft doesn't exist already.
No, definitely not.  I contend one should be responsible for this.  I feel it should be the tower... but the tower gets its cue from thread_1 because thread_1 is the only one with such information

>> Question: [the tower can also initialize "launch & recovery"]. What does that mean?
It means that because thread_1 holds launch & recovery information, the tower can perform such decisions because it can gather from every other thread to determine if conditions permit.

>>  ... A message through a socket to the simulator
No.  Think of my Panel as a receiver only.  It only receives data from three threads.  With this information it can make a decision for launch or recovery and present it to the screen.  It is a decision support system/tool.  It does not transmit anything.  That means nothing from within itself or external.  But in order to make that decision it must be able to share information.

Thanks for your questions !!



0
 
Knut HunstadCommented:
Dan (or others): feel welcome to comment, whether you agree or not! I think he (and I!) would appreciate second opinions!

How do your threads communicate with the form:

A. The thread receives a pointer to a group box and updates the controls directly.
B. The application/form receives data from the threads and updates the controls itself.

I have been assuming that B is the case. If so, then the application already has the data and you only need a container in the application for the queue, no new thread.

When I reread the question, I am starting to suspect you have situation A? In that case, wouldn't the following do:

- Create a mutex for each group box
- lock the mutex whenever updating the group box
- in the application, poll each group box regularly (locking the mutex when reading), read the contents of the controls and arrange the queue (as a container in the application)

Maybe even better would be to add signals, so that each thread sets a signal when changing anything. In that way, the application could wait passively for something to change before reading the controls.
0
 
John500Author Commented:
Khun,

>>  How do your threads communicate with the form:
It is case 'B' .  The Form receives data from the threads and updates the controls itself to each respective group box

>>  If so, then the application already has the data and you only need a container in the application for the queue, no new thread.

If we assume this to be true, thread_1 would be responsible for creating the queue since it contains aircraft line-up data.  It would stuff an 'AircraftObject' into the queue for each new aircraft:

struct AircraftObject {
       int        AircraftSideNumber;                // thread_1 creates object based on each new value
       int        AircraftLineup;                        // thread_1 updates position in queue based on conditions
       float      RadarDistance;                      //  thread_2 updates this member
       int         RadarAircraftSideNumber;      //  thread_2 updates this member
       float      WindDirection;                       //  thread_3 updates this member
       float      WindSpead;                           //  thread_3 updates this member
}

However, at some point thread_1 would have to check the values of the other members to make a decision on whether the landing was ok.  These checks done are:

1)  aircraft side number for thread_1 and thread_2 indicate the same aircraft based on radar distance
     if the aircraft was waved off for landing (based on side number or wind) the aircraft would be moved to the tail of the queue
2)  Wind is within limits

As thread_1 attempted to check the other members, the other threads would be in the process of updating their own members since this happens constantly.  Hence the dead-lock !  Do see now why I've anticipated this dead-lock?  Sooner or later a resource/container is going to be under conflict because the data _must_ be shared for decision making.

The scenario I've presented is very basic in the sense that there are only two checks.  In a real airport there are more concerns but I'm using only two conditions for now.  Those conditions again are:

1)  thread_1 and thread_2 have to agree in terms of aircraft side number and distance or lineup
2)  thread_3 needs to reveal that wind is within limits

If either of these conditions are unacceptable, the aircraft is waved off and put at the back of the queue.  Therefore, knowing these constraints, do you still agree there is a way to avoid mutex code ?  I don't see how.


0
 
Knut HunstadCommented:
I have reread everything a few more times, and I _do_ think you are complicating things unnecessarily!

Why let Thread_1 create objects? As it is, it reports the data it reads to the application. Let the application deal with creating Aircraft objects and arranging the queue. There is no need for any of the threads to know about each other, is there? The application can be the Tower, since it gets all the information.

My english isn't quite adequate to make good formulations here, sorry about that! I'll try to rephrase a little to maybe make you understand what I mean:

A. you have a system with 3 input-only threads, doing nothing but reading from a socket and reporting the data to the main application, right?
B. you now want to not only display the raw data, but collect data about the same objects (Aircraft) together and present them in an orderly fashion

If I'm right this time, then try to realize that all you are trying to do is rearranging data the application already has collected, which at this point has nothing to do with the threads! No need to make that more complex than creating a data structure and some algorithms in the application. When a thread has new information, the application receives it (in some way you haven't described, but I can't see that it is important, since this part already works) and puts it into it's own data structures, which no thread needs to access.

Yes, I know I'm repeating myself, but either I am not quite understanding what you mean or you don't see what I mean :-) Just trying to help...
0
 
John500Author Commented:
...  you are correct in all points above.  I definitely feel as though you are up to speed with where I'm at.  I'm all hears and would like to know how the main application can do what you say.

If I understand you correclty, we might consider the main application to be like a bank.  All three threads are depositors.  When they deposit their money/data, the bank puts it into the appropriate place using it's own logic.  I just don't see how this is done without running into a dead-lock at some point.

The way Form1 currently accesses data from the other threads is through global arrays.  Each thread has it's own .cpp.  I felt it was best to arrange the project this way.  Otherwise I would have had one HUGE Form1.cpp with routines from each thread -->  a mess.   Hence, Form1 currently only handles all Form1 objects and launches each thread when the menu item dictates.

Once the threads are kicked off, the data from those threads is accessed using extern:

--------------------------------------------------

Form1.cpp
----------------

extern string AircraftArray[3];   // holds all aircraft data
extern string RadarArray[3];    // holds all radar elements
extern string WindArray[3];      // holds all wind elements

Aircraft.cpp
---------------

string AircraftArray[3];

Radar.cpp
--------------
string RadarArray[3];  

Wind.cpp
--------------
string WindArray[3];      

--------------------------------------------------

You see then, I still anticipate a conflict when Form1.cpp attemts to access any of these arrays to do its job of creating an AircraftObject or accessing the radar and  wind arrays for possible updates.

What am I missing and I do hope I'm missing something   :- )


0
 
Knut HunstadCommented:
Or I'm misunderstanding something :-)

You are already accessing those arrays, to put the values of them into the controls on the form, right?

If that works, there is no reason you shouldn't be able to use the same values to create new, internal objects in the main application, based on the contents of those arrays.

But I have one concern with your setup: I can't see that the string class is totally thread safe. The documentation states:

---- From Standard C++ Library Reference
For writes to the same object, the object is thread safe for writing from one thread when no readers on other threads
----

and

----
From one thread at a time when no writers on other threads.
----

which sounds to me like it isn't thread safe at all?

My recommendation would therefore be to surround all read/write operations to these arrays with mutexes.

I am guessing that you maybe had the feeling there was some mutex needed somewhere, and with this setup you where right (or you could maybe find a thread safe string class)?

When those mutexes are in place, I hope you feel more confident about accessing the arrays from the main application and rearranging the info any way you like?

Just for the record, I still think you might have ended up with a simpler program just polling the sockets, like Dan suggested...
0
 
DanRollinsCommented:
Here is one "high-level" way to approach a complex system:  

You look at the tasks that need to be performed and then you imagine you have a "black box" that does each task for you.  In other words, you don't "sweat the details" at that level of the design.

In this case, you need several "black boxes"

  * Something that tells you if the wind is too high or wrong direction
  * Something that keeps a list of aircraft as they enter the airspace
  * Something that checks aircraft status for special conditions
  * Something that logs everything for post-mortem analysis

You start with the idea that the "black box" just does its job.  The details of, for instance, how it knows the wind speed and direction, how often it gets updated, how its data is displayed, etc... are just not part of the equation early on.

I think you are seeing data-access collisions and designing with that as the starting point.  But that is the sort of detail that comes into play later on, when the rest of the system works.  

For instance, in the *first round of coding,* you don't implement a complex queue for tracking real-time windspeed.  Rather, your windspeed "black box" always returns "5 mph, NE."  You write the rest of the system with the assumption that it will return varying data, but for the early work, you can bypass that.

Likewise, in the aircraft status-checking "black box" you assume that at any time, any part of the system can ask about any aircraft and find its current status.  You don't, at this stage, worry about whether the status is currently being updated.

=-=-=-=-=-=-=-=
Eventually you get around to coding the inner workings of each "black box."   There probably will come a point where you need to start working with mutexes and so forth, but it will probably be a lot easier to do that you currently think.  For instance, you usually won't need a mutex to prevent obtaining the windspeed.  It either is up to date, or it is about to be updated and that's not really relevant ... you just want to know what it was the last time it was updated.

=-=-=-=-=-=-=-=-=
I've designed a number of real-time multithreaded apps, and I can tell you this:
  * Often you probably don't need as many threads as you think
  * Data collisions end up being quite easy to avoid, and coding to avoid them
     is easy to do later on in the programming cycle.
  * The trickiest problems will probably end up revolving around the U/I.
     It's important to decouple your data handling from the U/I... just provide
     functions that get the "current status" at any time and update the U/I at
     timed intervals (even 500ms is "instantaneous" to a human viewer).

-- Dan
0
 
AndyAinscowCommented:
One point to bear in mind.
Just because the data is coming from somewhere else doesn't mean you need a thread to retrieve the data.
A thread is usually used to do a complex, cpu intensive task and let the main thread of the app remain responsive.
0
 
John500Author Commented:
I've heard all points and need to know if the following schema sounds good.

If I have a global queue and each thread has a pointer to the queue, then each thread can deposit it's information to that queue each time it does a read from the socket.  The pseudo code would look something like this:

struct AircraftObject{
         thread_1  *thread_1_data;  // creates queue, orders queue, deposits aircraft side number data & line-up
         thread_2  *thread_2_data;  // deposits radar data
         thread_3  *thread_3_data;  // deposits wind data
}

for{;;}  // infinite thread

{
thread_1  (aircraft info)
-----------------------------

1)  check the menu item flag for 'aircraft info' to see whether the aircraft info socket should be read
      i.e.  if(menuItem1->Checked) ...
2)  if aircraft info flag is checked, read the socket
     if not, do not read the socket or update display
3)  if the socket has been read, determine if a queue has been created
        If not, create it and deposit first AircraftObject structure in queue
        If so, determine where this aircraft should be placed within the queue based on 'line-up' information

thread_2  (radar info)
---------------------------

1)   check the menu item flag for 'radar info' to see whether the radar info socket should be read
      i.e.  if(menuItem2->Checked) ...
2)  if radar info flag is checked, read the socket
     if not, do not read the socket or update display
3)  if the socket has been read, determine if the queue has been created
          If not, do nothing but update the panel display with radar information
          If so, update head structure/item of the queue and _only_ the head item

thread_3  (wind info)
---------------------------

1)   check the menu item flag for wind info' to see whether the wind info socket should be read
      i.e.  if(menuItem3->Checked) ...
2)  if wind info flag is checked, read the socket
     if not, do not read the socket or update display
3)  if the socket has been read, determine if the queue has been created
          If not, do nothing but update the panel display with wind information
          If so, update head structure/item of the queue and _only_ the head item

thread_1  (aircraft info)
-----------------------------
1)  If the first item in the queue has acceptable wind and radar shows a distance for 'landing', remove item
     If the first item in the queue has unacceptable wind or radar shows a confliicting side number move item to the tail

}

Notice with this design, the application only has _one_ thread.  This thread ensures that a sequence of events has to take place.  That is, there wouldn't be any conflict or dead-lock on the queue or structure members because the thread reads each socket sequentially.

The way I have it now, each thread is running concurrently.  Does this look like an acceptable method ?  The only problem I see here is that there may be times when data is updated slowly because the call to 'ReadSocket()' doesn't always return quickkly.  Sometimes the socket will hand until data is received.  However, this may be a good thing because it easily reflects the truth - namely, data is not coming in for some reason.

Comments ?  Am I correct that it would _impossible_ for a dead-lock to occur under this kind of set-up ?

Thanks
0
 
John500Author Commented:
I forgot to correct the opening remark of the last post:

>> If I have a global queue and each thread has a pointer to the queue

Should read, -->  if I have one thread and a global queue able to be accessed by each .cpp using extern .......
0
 
Knut HunstadCommented:
This looks good, _except_ for your remark about ReadSocket hanging! If you can not poll the sockets without risking that the application hangs, then that may be a valid reason to use threads anyway, IMHO.

I would recommend looking into the ReadSocket function, to see if there really is no way to just check a socket and always return immediately either with data or with a "no data available"-value.
0
 
DanRollinsCommented:
Another handy concept:

The Queues should always exist... your program just maintains them and examines them.  A queue may be empty, but it is conceptually cleaner to create the empty queue right away (at startup) rather than check for its existence with each loop of the polling logic.

At some later point, you may provide a separate thread of execution to read a socket and populate a queue (and at that time remove that logic from the round-robin processing of the main thread).  In that case, a thread will be associated with a queue.  But the conceptual foundation is the queue itself -- not the thread that may or may not exist to maintain it.

-- Dan
0
 
John500Author Commented:
>> I would recommend looking into the ReadSocket function, to see if there really is no way to just check a
>> socket and always return immediately

I'm going to find out.  If the answer comes up 'no',  I'd like to continue with my original idea of a mutex.  I'd rather build this thing the most optimal way than vise-versa.

I'd rather finish this question from a mutex standpoint or any other clever way that allows for:

1)  multiple threads
2)  queue
3)  a mutex or any other clever way to avoid collisions

Given all the  previous dialog, what is the suggested 'code' approach?  I use the word 'code' because we have discussed various methods and it appears a mutex is reasonable.  Otherwise, I'd need to know the actual 'clever' approach that doesn't require the mutex.

Any suggestions, or is the mutex the answer ?
0
 
DanRollinsCommented:
One issue you will confront is that some data must be "atomic"  
For instance, in the process of adding a new wind measurement, you will add an empty record, then set the speed and then the direction.  It is possible that a concurrently-executing thread may fetch that record at a point where only the speed is set--- the direction will be zero or some random number.  

The first thing you do is narrow down the places in the program where that can happen.  Make a single sequence of code that adds and sets wind data queue items and another single place in the program that obtains wind data.  Then I think the easiest technique is to use a CCriticalSection.  Instantiate it as a member of your queue-handling object.  At the point where you are adding to the queue, start with a m_CritSect.Lock() and after setting both speed and direction, call m_CritSect.Unlock().  And when you access queue data FROM ANOTHER THREAD, do the same.  Note that you don't need to lock and unlock all over the lace... just when another thread will access data that might be in the process of being changed.

In the wind-handling logic, I would try hard to arrange so that NO other threads actually accesses the queue itself.  They would access a variable that held the current values.   So the only place a Critical Section would need to be locked would be at the point where a new queue entry had been added and if that data was different from before, the "current value" variables were being updated.

In the queue handler (CWindInfo):
    add an item to the queue
    set it with the speed and direction (x.m_nSpeed and x.m_nDir)
    compare to m_curSpeed and m_curDirection
    if different...
        m_CritSect.Lock();   // prevent GetCurData from reading partial data
           m_nCurSpeed=  x.m_nSpeed;
           m_nCurDir=  x.m_nDir;
        m_CritSect.Unlock(); // both items are there; now it's ok for GetCurData to access

In the code that displays wind data (CMyView):
    pcWindInfo->GetCurData( nSpeed, nDir );

In the code that accesses wind data:
void CWindInfo::GetCurData( int& nSpeed, int& nDir )
{
     m_critSection.Lock();   // pause if m_nCurXxxx is being updated, then continue
     nSpeed= m_nCurSpeed;
     nDir=      m_nCurDir;
     m_critSection.Unlock();  
}
0
 
John500Author Commented:
Sorry to be away from this question for so long.  I wanted to wait until I could respond accurately.... seems everything else has been a prioity.

>> One issue you will confront is that some data must be "atomic"  
understood

>> The first thing you do is narrow down the places in the program where that can happen
I believe I have a method to reduce this possibility

>> Make a single sequence of code that adds and sets wind data queue items
Instead, I'm thinking the queue should be the item that has the mutex placed upon it.  When _any_ thread is able to access the queue to provide its own updates, it will __only__ make updates to the head item.  I repeat, every thread will _only_ make updates to the head item.

When the AircraftInfo thread gets its chance to access the queue, it will check to see if all data is available to make a decision for landing.  If all data within the head of the queue checks good, this item (aircraft) will be considered as landed.  If not, the AircraftInfo thread will either cycle back around hoping for more info next time or send this aircraft to the tail of the queue before releasing the queue.

This is the basic approach I want to use.  I just wish it were possible to have multiple threads and somehow incorporate a method that cycles through each thread's data as though there were only one thread.  That is, my post dated:

Date: 05/30/2006 07:15AM EST

... explains how I'd do this if there were only one thread.  There would be no chance of a lock on the queue because one thread reads three separate sockets in turn - i.e. -->  1) aircraft  2) radar 3) wind  

At any rate, I'd like to start coding this stuff if there are no serious objections.  I apprecieate the code sample above Dan.  However, I'm having trouble following based on the use of variable names.  For instance can you tell me what each element of this statement means:

m_nCurSpeed=  x.m_nSpeed;

I'm guessing the following:

m_  = mutex
n     =  ?
CurSpeed  =  current speed
x     =  ?
m_  =  mutex
n     =  ?
Speed  =   wind speed value from thread

The little things will throw my simple brain off.  Thanks.

0
 
DanRollinsCommented:
I use what some might consider obsolete naming conventions.  It may be easier if you just use a b c etc.

m_  this is a class data member variable (as opposed to an auto or global)
   nXxxx  this is a number
   sXxxx this is a string
0
 
John500Author Commented:
Dan,

I want to start coding and I want to place a mutex on the queue as I mention in the previous post.  What is the first thing I need to do from your stand point ?  Can you take a look at the following link:

http:Q_21860993.html

This post has my entire Form1.h along with other proposed code I would use to implement a mutex.  Please take a look at that code and tell me how much of the code _outside_ Form1.h I should attempt to use or how much I should try to compile.  I'd like to get something going !  I'm guessing we don't need the Tower class & thread if I allow the AircraftInfo thread to manage the queue.  Or, we could have a Tower class and thread - either way, I don't care.

I'll give you 350 points from that question and 150 to Khun for suggesting I start a new question (this one).  

Whatever code you think is suitable, post that code here in your next response.  Try to make it free from errors - assume that I'm void of understanding because chances are - I am.  In other words, if you feel the AirportObject class code looks good, post the code and tell me where it belongs - i.e. --> it's own header file along with some declaration in Form1.h and a definition in Form1.cpp - whatever goes with it.

I need to see the _entire_ affect throughout my project for whatever code you thing I should start compiling.  Otherwise, I know I'll leave something out and we would then get bogged down on little stupid questions which I would keep asking rather than knocking out whole sections of code at a time.

I imagine there will be three or four more parts to knock out.  I'll split points again on this question (1 part) for your next post.  After that I'm guessing I'll open up two more questions at 500 a piece to finish this entire question out.

1)  next post - part 1 - addressing AirportObject class
2)  new question - part 2 - addressing issues dealing with queue code ( I think I have it, just need some feed-back)
3)  new question - part 3 - addressing notification issues that allow the mutex to work properly
4)  new question 'possibly' - part 4 - for clean-up or bugs

Standing by, thanks
0
 
John500Author Commented:
Thanks guys.  You were right !

I didn't need threads and there was plenty of time to monitor the individual sockets one by one before making the final decision as to a landing or wave-off.  Especially considering how fast a thread runs !  The time it takes for one iteration of a loop to check all conditions is so quick, the thread could iterate thousands of times before a landing took place from an aircraft one mile away on approach ........

Also, how about taking a look at the new question below that relates to this project.  I want to use the a queue from previous project but for some reason it isn't working.  I've provided all the necessary code to copy and paste so that the problem can be duplicated during run time.  

Thanks again.

http:Q_21900565.html
0

Featured Post

Upgrade your Question Security!

Add Premium security features to your question to ensure its privacy or anonymity. Learn more about your ability to control Question Security today.

  • 11
  • 6
  • 6
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now