GIDForums  

Go Back   GIDForums > Computer Programming Forums > C++ Forum
User Name
Password
Register FAQ Members List Calendar Search Today's Posts Mark Forums Read

 
 
Thread Tools Search this Thread Rate Thread
  #1  
Old 29-Jun-2009, 14:31
Anonymous_guy Anonymous_guy is offline
New Member
 
Join Date: Nov 2007
Location: Victoria
Posts: 9
Anonymous_guy is on a distinguished road

Pthread Help


So this is the first time I've ever done ANYTHING with pthreads what so ever. I have an assignment that deals with them and I'm having quite a bit of trouble at the moment.


Essentially the program will take in a file such as:
Code:
W:9,7 w:3,2 e:13,3 e:12,5 W:15,2 w:11,10 e:7,1 E:1,7 w:14,9

Where the first letter represents the direction and priority. W being high priority west, and w being low priority west. Same for E and e. The first number represents the time it takes the train to load passengers (So the time the thread has to wait before it can see if the main track is empty.) The next number represents the time it takes to cross the main track.

The rules enforced by the automated control system are:
1. Only one train is on the main track at any given time.

2. Only loaded trains can cross the main track.

3. If there are multiple loaded trains, the one with the high priority crosses.

4. If two loaded trains have the same priority, then:

(a) If they are both traveling in the same direction, the train which finished loading first gets the clearance to cross. If they finished loading at the same time, the one appeared first in the input file gets the clearance to cross.
(b) If they are traveling in opposite directions, pick the train which will travel in the direction opposite of which the last train to cross the main track traveled.

So all in all, to the input given above the output would be:
Code:
Train 7 is ready to go East Train 7 is ON the main track going East Train 1 is ready to go West Train 6 is ready to go East Train 7 is OFF the main track after going East Train 1 is ON the main track going West Train 0 is ready to go West Train 1 is OFF the main track after going West Train 0 is ON the main track going West Train 5 is ready to go West Train 3 is ready to go East Train 2 is ready to go East Train 8 is ready to go West Train 4 is ready to go West Train 0 is OFF the main track after going West Train 4 is ON the main track going West Train 4 is OFF the main track after going West Train 6 is ON the main track going East Train 6 is OFF the main track after going East Train 5 is ON the main track going West Train 5 is OFF the main track after going West Train 3 is ON the main track going East Train 3 is OFF the main track after going East Train 8 is ON the main track going West Train 8 is OFF the main track after going West Train 2 is ON the main track going East Train 2 is OFF the main track after going East



Now after all that. Right now my program takes in the input file and creates an array of Trains. Each Train contains a number, priority, direction, loading and crossing times as well as a thread. I then sorted the array by loading times. But at this point I'm stuck and really have no idea what to do. ANY help is greatly appreciated.
CPP / C++ / C Code:
#include <pthread.h>
#include <string>
#include <iostream>
#include <fstream>
#include <queue>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

using namespace std;
#define DIGIT 10
#define W 1
#define w 2
#define E 3
#define e 4

class train{
	public:
	int loadingTime;
	int crossingTime;
	int number;
	int priority;
	
	
	train()
	{
		loadingTime = 0;
		crossingTime = 0;
		number = 0;
		priority = 0;
	};
	train(int lTime, int cTime, int num, int pri)
	{
		loadingTime = lTime;
		crossingTime = cTime;
		number = num;
		priority = pri;
	};
	
	int getLoading()
	{
		return loadingTime;
	}
	int getCrossing()
	{
		return crossingTime;
	}
	int getNumber()
	{
		return number;
	}
	int getPriority()
	{
		return priority;
	}
	string getDirection()
	{
		if(priority == 1 || priority == 2)
		{
			return "West";
		}
		else
		{
			return "East";
		}
	}
	
	
};


void BubbleSort(train *num, int numLength)
{
      int i, j, flag = 1;    
      train temp;           
      for(i = 1; (i <= numLength) && flag; i++)
     {
          flag = 0;
          for (j=0; j < (numLength -1); j++)
         {
               if (num[j+1].getLoading() < num[j].getLoading())      
              { 
                    temp = num[j];            
                    num[j] = num[j+1];
                    num[j+1] = temp;
                    flag = 1;               
               }
          }
     }
     return;
}



int main(int argc, char **argv)
{
	if(argc != 3)
	{
		cout<<"Please enter two paramaters, the name of the file followed by the number of trains."<<endl;
	}
	
	int numTrains = atoi(argv[2]);
	int i;
	int loadingTimes[numTrains];
	int crossingTimes[numTrains];
	char direction;
	int dirFlag = 0;
	char temp;
	int tempOnes = 0, tempTens = 0;
	
	train trainArray[numTrains];
	
	
	FILE *inFile;
	inFile = fopen(argv[1],"r");
	if (inFile == NULL) 
	{
		cout<< "Unable to open file"<<endl;
		exit(1);   // call system to stop
	}
	for(i = 0; i < numTrains; i++)
	{
		
		cout<<"Train number: "<<i<<endl;
		direction = getc(inFile);
		if(direction == 'e')
		{
			dirFlag = e;
			cout<<"East bound low priority"<<endl;
		}
		if(direction == 'E')
		{
			dirFlag = E;
			cout<<"East bound high priority"<<endl;
		}
		if(direction == 'w')
		{
			dirFlag = w;
			cout<<"West bound low priority"<<endl;
		}
		if(direction == 'W')
		{
			dirFlag = W;
			cout<<"West bound high priority"<<endl;
		}
		getc(inFile);
		temp = getc(inFile);
		tempTens = atoi(&temp);
		if((temp = getc(inFile)) == ',')
		{
			loadingTimes[i] = tempTens;
		}
		else
		{
			tempOnes = atoi(&temp);
			tempTens *= DIGIT;
			loadingTimes[i] = tempTens+tempOnes;
			getc(inFile);
			
		}
		tempOnes = 0;
		tempTens = 0;
		cout<<"Loading Time: "<<loadingTimes[i]<<endl;
		
		temp = getc(inFile);
		tempTens = atoi(&temp);
		if((temp = getc(inFile)) == '\n')
		{
			crossingTimes[i] = tempTens;
		}
		else
		{
			tempOnes = atoi(&temp);
			tempTens *= DIGIT;
			crossingTimes[i] = tempTens+tempOnes;
			getc(inFile);
		}
		tempOnes = 0;
		tempTens = 0;
		cout<<"Crossing Time: "<<crossingTimes[i]<<endl;
		
		train temp(loadingTimes[i], crossingTimes[i], i, dirFlag);
		trainArray[i] = temp;
	}
	BubbleSort(trainArray, numTrains);
	for(i = 0; i < numTrains; i++)
	{
		if (i == 0)
		{
			sleep(trainArray[i].getLoading());
		}
		else
		{
			sleep((trainArray[i].getLoading() - trainArray[i-1].getLoading()));
		}
		
		cout<<"Train "<<trainArray[i].getNumber()<<" is ready to go "<<trainArray[i].getDirection()<<"."<<endl;
	}
	

	
	
	return 0;
}
  #2  
Old 30-Jun-2009, 23:25
Mexican Bob's Avatar
Mexican Bob Mexican Bob is offline
Member
 
Join Date: Mar 2008
Location: Chicxulub, Yucatán
Posts: 226
Mexican Bob is a jewel in the roughMexican Bob is a jewel in the roughMexican Bob is a jewel in the rough

Re: Pthread Help


Other than including the pthreads header, you are STILL not doing ANYTHING with pthreads

You probably want to decide whether this is a C program or a C++ program. Currently, it is a rather poor mixture of both languages. Since the pthreads library is a C-centric API, I'd probably recommend sticking with C, unless this is specifically a C++ class and C++ is expected.

For example, we tend not to have public data in a class definition and if we do decide that it is useful, there is absolutely no "good" reason for accessor/mutator operations.

Perhaps you should take a moment to explain the objective. I'm guessing that we have to have all of the trains, load and then cross the main track and then presumably unload. Are these to run (based on priority) continuously until interrupted? From your narrative, is seems as if you want each train to run as a separate thread. Perhaps a restatement of the problem will add additional clarity?

Should we assume that you also want no "starving" of lower priority trains such that all trains are able to be loaded and eventually unloaded in some kind of manner that gives each thread the opportunity to run to completion on every pass through the priority queue? Do you want to use priority inversioning?

Another aspect for you to consider is that you may want to explain your design methodology. How do you expect to implement the objective through code versus what your code actually does. Obviously the code is a WIP (work-in-progress), so unless we have a better idea of what must be done and what design goals you hope/expect to achieve, the only thing that I can do is point out problems like mixing C and C++ and public data in a C++ class.

Also, if each line of your input file equals one train, then you do not need to ask the user for the number of trains...unless you want to constrain the system so that it can process a subset of the data file. Generally speaking, we do not want to ask the user for the number of "records" in a file, because how would the user know without opening the file in some manner, presumedly by using our program?


MxB
  #3  
Old 01-Jul-2009, 01:21
Anonymous_guy Anonymous_guy is offline
New Member
 
Join Date: Nov 2007
Location: Victoria
Posts: 9
Anonymous_guy is on a distinguished road

Re: Pthread Help


Quote:
Originally Posted by Mexican Bob
Other than including the pthreads header, you are STILL not doing ANYTHING with pthreads

You probably want to decide whether this is a C program or a C++ program. Currently, it is a rather poor mixture of both languages. Since the pthreads library is a C-centric API, I'd probably recommend sticking with C, unless this is specifically a C++ class and C++ is expected.

Yeah as I've played around with threads I've noticed there's a few subtle changes to making it work from C -> C++. I can easily change what I have not to C if overall it's easier.

Quote:
Originally Posted by Mexican Bob
For example, we tend not to have public data in a class definition and if we do decide that it is useful, there is absolutely no "good" reason for accessor/mutator operations.

Perhaps you should take a moment to explain the objective. I'm guessing that we have to have all of the trains, load and then cross the main track and then presumably unload. Are these to run (based on priority) continuously until interrupted? From your narrative, is seems as if you want each train to run as a separate thread. Perhaps a restatement of the problem will add additional clarity?
The problem it's self is that there is one main track, but 4 side tracks that lead to the main track, as depicted but the picture. The way it works is after the loading time is done, the train will be waiting its turn before it can cross. The order in which they cross (pending there's more then one train waiting) depends on the Priority and direction. Higher priorities of course have precedence over the lower priorities. If it comes to a case where there is more then one train of the same priority ready to go it follows:
4. If two loaded trains have the same priority, then:

(a) If they are both traveling in the same direction, the train which finished loading first gets the clearance to cross. If they finished loading at the same time, the one appeared first in the input file gets the clearance to cross.
(b) If they are traveling in opposite directions, pick the train which will travel in the direction opposite of which the last train to cross the main track traveled.
Quote:
Originally Posted by Mexican Bob
Should we assume that you also want no "starving" of lower priority trains such that all trains are able to be loaded and eventually unloaded in some kind of manner that gives each thread the opportunity to run to completion on every pass through the priority queue? Do you want to use priority inversioning?

I'm not sure what you mean by Priority Inversioning, but if there is only one low priority thread waiting in the queue, with other high priority threads, it will always leave last.
Quote:
Originally Posted by Mexican Bob
Another aspect for you to consider is that you may want to explain your design methodology. How do you expect to implement the objective through code versus what your code actually does. Obviously the code is a WIP (work-in-progress), so unless we have a better idea of what must be done and what design goals you hope/expect to achieve, the only thing that I can do is point out problems like mixing C and C++ and public data in a C++ class.
I think this is the main problem I have. I really don't know what I'm doing with Pthreads so I don't really know the best way to go about doing this.
Quote:
Originally Posted by Mexican Bob
Also, if each line of your input file equals one train, then you do not need to ask the user for the number of trains...unless you want to constrain the system so that it can process a subset of the data file. Generally speaking, we do not want to ask the user for the number of "records" in a file, because how would the user know without opening the file in some manner, presumedly by using our program?
I'm not sure why we need it, but it was said in the specs that the number of trains would be the second parameter passed in. I believe it's just to make it slightly easier for us.
  #4  
Old 02-Jul-2009, 11:16
Mexican Bob's Avatar
Mexican Bob Mexican Bob is offline
Member
 
Join Date: Mar 2008
Location: Chicxulub, Yucatán
Posts: 226
Mexican Bob is a jewel in the roughMexican Bob is a jewel in the roughMexican Bob is a jewel in the rough

Re: Pthread Help


After thinking about the problem for awhile, I *think* that each thread simply runs to completion.

Priority inversion occurs when a lower priority thread has a lock on a shared resource (the main track in this case) and a higher priority thread becomes ready to run, such as the loading time for a higher priority train has completed. Without priority inversioning, the lower priority thread/train can be suspended so that the higher priority thread/train can execute, but a deadlock occurs because the higher priority thread, which is ready to run, cannot achieve a lock on the shared resource. Therefore, the lower priority thread is elevated in priority to at least the same priority (or, often +1 higher) as the higher priority thread waiting for the resource. This allows the now as high or slightly higher (previously lower) priority thread to run to completion (or at least until it releases the lock) so that it releases the lock on the resource needed by other threads of higher priority.

It is difficult to tell that the other paths to the main track are "side tracks," because side tracks actually run parallel to the main track so that trains may pass each other. IMO it is a very crappy graphic that does nothing but add to the potential for further confusion. Nothing like so-so, missing and truly worthless requirements in the "real world." May as well get used to the fact!

For a good entry point into pthreads, see:

http://www.advancedlinuxprogramming....04-threads.pdf

If we begin a discussion about the design of the application, we probably should elect a language choice as the design capabilities of each language offer different features. OR we can discuss the design objectives and select the language that better meets those with the least amount of coding. Generally, I'd say that the "right language for the job" is preferred, but it may be such an easy problem that C is "good enough" and sharing the same language constraints as the pthreads API is helpful, too.

Of course, it is usually not terribly difficult to use many C-centric API from C++, but it is one of the reasons that we have const_cast.

What appears unclear in the problem is how the creation of threads expected to be performed? It appears that we create each of them as we read them from the file, immediately sleep them for the loading period and then let them have it the shared resource by attempting to acquire a lock on it.

What is less clear is how we go about handling priorities. My thinking (and it appears that you are thinking along the same lines with your inclusion of <queue>) is that we need to queue threads. However, we need to queue with attention to priority, which I don't think that you've associated in your code. What we need is not simply a queue, but a priority queue.

This is probably why the priority rules allow for capital letters to be the same priority and that arbitration among equal priorities is based on first-come, first-served and the various other rules supplied.

We also have to maintain statefulness of the heading of the most recent train to cross the main track so that we can fully implement the arbitration rules for equal priority, loaded trains ready to cross.

Therefore, it suggests a data structure and I would say that the organization, specification and maintenance of this data structure is critical to the design.

What is unclear is how loading is handled. Do we load immediately after we create the train? Do we prioritize loading too? Is is possible that trains can be loaded immediately after being created or must they wait their turn for some other resource? Do we immediately pqueue all trains and then run them as their priority levels indicate?

The subtlety of the requirements suggest that each train must begin loading on creation and that the period of loading begins once created. However, what implementation choice seems adequate and useful to facilitate this in some meaningful way?

I would think that I would want to see a call to an internal function named "load_train" (or similar) that would cause the thread/train to sleep for the duration of its loading time. We do not know the units of time from the requirements, but we can work with seconds quite easily.

Of course, this project is not particularly simple. It involves a number of challenging concepts including priority-based execution of multiple threads sharing a single exclusive-use resource. Significantly easier would be a single thread that reads in the data file and then processes it based on the priority queue contents. Since the resource is exclusive use, no two threads can be actively using the resource at a time any way.

I would evaluate the requirements to see if there are supposed to be a 1:1 relationship between trains and threads. If not a requirement, I'd simplify the design such that the main thread of execution is the only thread (or simply joins a created thread) that manages the priority queue.

I'd try to find out if the primary objective is to work with many threads or if resource access control and priority queuing are the desired goal.


MxB
 
 

Recent GIDBlogAccepted for Ph.D. program by crystalattice

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
pthread trick works with gcc 3.x.x, but not with 4.x.x at8 C++ Forum 6 23-Apr-2008 07:57
Problem using pthread kenkoh C Programming Language 2 26-Feb-2008 02:56
pthread doesn't work for me! ajaffres C++ Forum 1 10-Jun-2005 10:41

Network Sites: GIDNetwork · GIDWebHosts · GIDSearch · Learning Journal by J de Silva, The

All times are GMT -6. The time now is 04:37.


vBulletin, Copyright © 2000 - 2009, Jelsoft Enterprises Ltd.