Question

Please fill in the YOUR CODE HERE blocks for trainLine.cpp and provide a sample output. The...

Please fill in the YOUR CODE HERE blocks for trainLine.cpp and provide a sample output. The other answers to this question are incorrect and do not complie so please do not copy/paste from them.

Four trains of varying speeds run north-and-south on their own tracks. They visit different the two stations at either end: northTerminal after going north and southTerminal after going south.

Because each train runs on its own track, they will not collide on the tracks. However, both station can only handle one train at a time. So if two trains are ever at the same station at the same time then there will be a CRASH.

More specifically, it is not the actual Station instance that should be locked, rather, it is the act of arrive()-ing and leave()-ing the Station that should be locked.

Each train is implemented with its own thread. Please make the trains run both safely and on time.

Note: Besides the C++ code in Station.h and trainLine.cpp, this program requires you to give short answers for (b), (d) and (f) in the comments. Be sure these answers are clearly labeled!

Making the Train Line multi-threaded

Right now not much will happen. Therefore, please finish the following:

Finish main() to make and join the Threads.
I already have created NUM_TRAINS for you. They are in trainArray[].
Please make 'NUM_NORTHERNLY_TRAINS' threads (tidArray[0] to tidArray[NUM_NORTHERNLY_TRAINS-1]) run 'initiallyNorthernly()'. Each thread should get a pointer to its own Train instance (trainArray[0] to trainArray[NUM_NORTHERNLY_TRAINS-1], this is an array of POINTERS to trains, not trains themselves).

Please make 'NUM_SOUTHERNLY_TRAINS' threads (tidArray[NUM_NORTHERNLY_TRAINS] to tidArray[NUM_TRAINS-1]) run 'initiallySouthernly()'. Each thread should get a pointer to its own Train instance (trainArray[NUM_NORTHERNLY_TRAINS] to trainArray[NUM_TRAINS-1], this is an array of POINTERS to trains, not trains themselves).

Then, please wait for the trains to finish. Please recycle their memory by getting the pointers to them and doing a delete() on them.
Finish initiallyNorthernly().
In a loop NUM_LOOPS times, make the Train passed to the function:
arrive() at northTerminal
leave() from northTerminal
do pause() on the Train object
arrive() at southTerminal
leave() from southTerminal
pause() on the Train object
The function must point to the Train it used.
Finish initiallySouthernly().
In a loop NUM_LOOPS times, make the Train passed to the function:
arrive() at southTerminal
leave() from southTerminal
do pause() on the Train object
arrive() at northTerminal
leave() from northTerminal
do pause() on the Train object
The function must point to the Train it used.
STOP! Now your program is multi-threaded. How does it behave?
Run it like this once to make sure it runs:

$ ./trainLine 1
      
then run it 20 times:
$ ./trainLine 1 | grep CRASH
$ ./trainLine 2 | grep CRASH
$ ./trainLine 3 | grep CRASH
$ ./trainLine 4 | grep CRASH
$ ./trainLine 5 | grep CRASH
$ ./trainLine 6 | grep CRASH
$ ./trainLine 7 | grep CRASH
$ ./trainLine 8 | grep CRASH
$ ./trainLine 9 | grep CRASH
$ ./trainLine 10 | grep CRASH
$ ./trainLine 11 | grep CRASH
$ ./trainLine 12 | grep CRASH
$ ./trainLine 13 | grep CRASH
$ ./trainLine 14 | grep CRASH
$ ./trainLine 15 | grep CRASH
$ ./trainLine 16 | grep CRASH
$ ./trainLine 17 | grep CRASH
$ ./trainLine 18 | grep CRASH
$ ./trainLine 19 | grep CRASH
$ ./trainLine 20 | grep CRASH
      
What do you notice?
Please answer this in the top comment in trainLine.cpp

Making the Station instances thread-safe

Make your program thread-safe my adding a pthread_mutex_t to class Station.
Initialize it in the constructor.
Get rid of it in the destructor (~Station()).
Use it in both arrive() and leave(). Important: You a locking the act of both arrive()-ing and leave()-ing, not the Station itself!
STOP! Now your program is thread safe. How does it behave?
Run it like this once to make sure it runs:

$ ./trainLine 1
      
then run it 10 times:
$ ./trainLine 1
$ ./trainLine 2
$ ./trainLine 3
$ ./trainLine 4
$ ./trainLine 5
$ ./trainLine 6
$ ./trainLine 7
$ ./trainLine 8
$ ./trainLine 9
$ ./trainLine 10
      
What do you notice?
Please answer this in the top comment in trainLine.cpp

Making the Train Line functional

Make your program functional by adding a pthread_cond_t to class Station.
Initialize in the constructor.
Get rid of in the destructor (~Station()).
Use it in both arrive() and leave().
STOP! What is the minimum number of conditions that you need? How does it behave?
Run it like this once to make sure it runs:

$ ./trainLine 1
      
then run it 20 times:
$ ./trainLine 1 | grep CRASH
$ ./trainLine 2 | grep CRASH
$ ./trainLine 3 | grep CRASH
$ ./trainLine 4 | grep CRASH
$ ./trainLine 5 | grep CRASH
$ ./trainLine 6 | grep CRASH
$ ./trainLine 7 | grep CRASH
$ ./trainLine 8 | grep CRASH
$ ./trainLine 9 | grep CRASH
$ ./trainLine 10 | grep CRASH
$ ./trainLine 11 | grep CRASH
$ ./trainLine 12 | grep CRASH
$ ./trainLine 13 | grep CRASH
$ ./trainLine 14 | grep CRASH
$ ./trainLine 15 | grep CRASH
$ ./trainLine 16 | grep CRASH
$ ./trainLine 17 | grep CRASH
$ ./trainLine 18 | grep CRASH
$ ./trainLine 19 | grep CRASH
$ ./trainLine 20 | grep CRASH
      
What do you notice?
Please answer this in the top comment in Station.h

Sample output

When the trainLine starts, it should say something like:

$ ./trainLine
Thomas the Tank-Engine leaving the trainyard.
Engine No. 9 leaving the trainyard.
California Zephyr leaving the trainyard.
Tokaido Shinkansen leaving the trainyard.
Thomas the Tank-Engine arriving at North Station
California Zephyr arriving at South Station
Thomas the Tank-Engine leaving North Station
California Zephyr leaving South Station
Engine No. 9 arriving at North Station
Tokaido Shinkansen arriving at South Station
Engine No. 9 leaving North Station
Tokaido Shinkansen leaving South Station
. . .
When the trainLine ends, it should say something like:

. . .
Engine No. 9 arriving at North Station
Engine No. 9 leaving North Station
Thomas the Tank-Engine arriving at North Station
Thomas the Tank-Engine leaving North Station
Engine No. 9 arriving at South Station
Engine No. 9 leaving South Station
Thomas the Tank-Engine arriving at South Station
Thomas the Tank-Engine leaving South Station
Thomas the Tank-Engine going back to the trainyard
Engine No. 9 going back to the trainyard
California Zephyr going back to the trainyard
Tokaido Shinkansen going back to the trainyard
$
/*-------------------------------------------------------------------------*
*---                                   ---*
*---       Train.h                           ---*
*---                                   ---*
*---   This file declares a class that implements a Train object.   ---*
*---                                   ---*
*---   ----   ----   ----   ----   ----   ----   ----   ----   ---*
*---                                   ---*
*---                                   ---*
*-------------------------------------------------------------------------*/

class   Train
{
// I. Member vars:
// PURPOSE: To hold the name of '*this' Train.
std::string   name_;

// PURPOSE: To hold the time it takes '*this' Train to go from one
//   Station to another (in microseconds).
int       pauseTimeUsecs_;

public :
// PURPOSE: To initialize '*this' Train to have name 'newName' and to have
//     transit time between platforms 'newPauseTimeUsecs'. Also notes to
//   std::cout that '*this' Train is leaving the trainyard. No return
//   value.
Train       (const std::string&   newName,
       int            newPauseTimeUsecs
       )
{
name_       = newName;
pauseTimeUsecs_   = newPauseTimeUsecs;
std::cout << getName() << " leaving the trainyard.\n";
}

// PURPOSE: To release resources. Also notes to std::cout that '*this'
//     Train is arriving back at the trainyard. No parameters. No return
///   value.
~Train   ()
{
std::cout << getName() << " going back to the trainyard\n";
}

// PURPOSE: To return the name of '*this' Train. No parameters.
const std::string&
       getName   ()
           const
{ return(name_); }

// PURPOSE: To make '*this' Train wait while it transits between platforms.
//   No parameters. No return value.
void       pause   ()
           const
{
usleep(pauseTimeUsecs_);
}

};


/*-------------------------------------------------------------------------*
*---                                   ---*
*---       Station.h                       ---*
*---                                   ---*
*---   This file declares a class that implements a Station   ---*
*---   object at which Train objects arrive, pause, and then leave.   ---*
*---                                   ---*
*---   ----   ----   ----   ----   ----   ----   ----   ----   ---*
*---                                   ---*
*---                                   ---*
*-------------------------------------------------------------------------*/

class Station
{
// I. Member vars:
// PURPOSE: To hold the name of '*this' Station.
std::string       name_;

// PURPOSE: To point to the Train object currently at '*this' Station
//   (if there is one).
Train*       trainPtr_;

public :
// IV. Constructor(s), assignment op(s), factory(s) and destructor:
// PURPOSE: To initialize '*this' Station to have name 'newName' and
//   and no Train. No return value.
Station       (const std::string&   newName
           )
{
name_   = newName;
trainPtr_   = NULL;
}

// PURPOSE: To release resources. No parameters. No return value.
~Station       ()
{
}

// PURPOSE: To return the name of '*this' Station. No parameters.
const std::string&
       getName   ()
           const
{
return(name_);
}

// PURPOSE: To return a pointer to the Train object currently at '*this'
//   Station (if there is one).
Train*   getTrainPtr
           ()
           const
{
return(trainPtr_);
}

// PURPOSE: To let '*newTrainPtr' arrive at '*this' Station. No return
//   value.
void       arrive   (Train*   newTrainPtr
           )
{
while (getTrainPtr() != NULL)
{
std::cout << getTrainPtr()->getName()
       << " is at " << getName()
       << ", "   << newTrainPtr->getName()
       << " must wait.\n";
usleep(10) + rand() % 10;
}

std::cout << newTrainPtr->getName() << " arriving at " << getName() << "\n";

if (getTrainPtr() != NULL)
std::cout << newTrainPtr->getName() << " and "
       << getTrainPtr()->getName() << " CRASHED at "
       << getName() << std::endl;

trainPtr_   = newTrainPtr;

usleep(10 + rand() % 10);
}

// PURPOSE: To let the Train object currently at '*this' Station leave.
//   Returns pointer to departing Train.
Train*   leave   ()
{
while (getTrainPtr() == NULL)
{
std::cout << "No train at " << getName() << "!\n";
usleep(10 + rand() % 10);
}

Train*   toReturn   = getTrainPtr();

std::cout << toReturn->getName() << " leaving " << getName() << "\n";

usleep(10 + rand() % 10);
trainPtr_ = NULL;

return(toReturn);
}

};


/*-------------------------------------------------------------------------*
*---                                   ---*
*---       trainLine.cpp                       ---*
*---                                   ---*
*---   This file defines code the implements 2 Station instances,   ---*
*---   and some number of Train objects that transit between them.   ---*
*---                                   ---*
*---   ----   ----   ----   ----   ----   ----   ----   ----   ---*
*---                                   ---*
*---                                   ---*
*-------------------------------------------------------------------------*/

// Compile with: $ g++ trainLine.cpp -o trainLine -lpthread -g

#include <cstdlib>
#include   <string>
#include   <iostream>
#include <unistd.h>
#include <pthread.h>
#include "Train.h"
#include "Station.h"

const int   NUM_TRAINS       = 4;
const int   NUM_NORTHERNLY_TRAINS   = NUM_TRAINS / 2;
const int   NUM_SOUTHERNLY_TRAINS   = NUM_TRAINS - NUM_NORTHERNLY_TRAINS;
const int NUM_LOOPS       = 16;
const char*   TRAIN_NAME_ARRAY[NUM_TRAINS]
                   = { "Thomas the Tank-Engine",
                   "Engine No. 9",
                   "California Zephyr",
                   "Tokaido Shinkansen"
                   };
const int   TRAIN_TRANSIT_TIME_MSECS[NUM_TRAINS]
                   = { 10000,   // Thomas
                   10000,   // Engine no. 9
                   5000,   // CA Zephyr
                   1000   // Bullet train
                   };

Station       northTerminal("North Station");
Station       southTerminal("South Station");

// PURPOSE: To make the Train object pointed to by 'vPtr' do 'NUM_LOOP' times:
//   * arrive at 'northTerminal'
//   * leave at 'northTerminal'
//   * pause
//   * arrive at 'southTerminal'
//   * leave at 'southTerminal'
//   * pause
//   Returns a pointer to the Train it used.
void* initiallyNorthernly (void* vPtr)
{   
// YOUR CODE HERE
}   
  

// PURPOSE: To make the Train object pointed to by 'vPtr' do 'NUM_LOOP' times:
//   * arrive at 'southTerminal'
//   * leave at 'southTerminal'
//   * pause
//   * arrive at 'northTerminal'
//   * leave at 'northTerminal'
//   * pause
//   Returns a pointer to the Train it used.
void* initiallySouthernly (void* vPtr)
{   
// YOUR CODE HERE
}   


int main (int       argc,
       char*       argv[]
       )
{
if (argc > 1)
srand(strtol(argv[1],NULL,10));

pthread_t tidArray[NUM_TRAINS];
Train*   trainArray[NUM_TRAINS];

for (int i = 0; i < NUM_TRAINS; i++)
trainArray[i] = new Train(TRAIN_NAME_ARRAY[i],TRAIN_TRANSIT_TIME_MSECS[i]);

int trainInd   = 0;

// Please make 'NUM_NORTHERNLY_TRAINS' threads (tidArray[0] to
// tidArray[NUM_NORTHERNLY_TRAINS-1]) run 'initiallyNorthernly()'.
// Each thread should get a pointer to its own Train instance
// (trainArray[0] to trainArray[NUM_NORTHERNLY_TRAINS-1], this is
// an array of POINTERS to trains, not trains themselves).
for (trainInd = 0; trainInd < NUM_NORTHERNLY_TRAINS; trainInd++)
// YOUR CODE HERE

// Please make 'NUM_SOUTHERNLY_TRAINS' threads
// (tidArray[NUM_NORTHERNLY_TRAINS] to tidArray[NUM_TRAINS-1]) run
// 'initiallySouthernly()'. Each thread should get a pointer to its own
// Train instance (trainArray[NUM_NORTHERNLY_TRAINS] to
// trainArray[NUM_TRAINS-1], this is an array of POINTERS to trains, not
// trains themselves).
for ( ; trainInd < NUM_TRAINS; trainInd++)
// YOUR CODE HERE

// Leave this loop here. I want to make sure you get the Train pointers
// back from initiallyNorthernly and initiallySouthernly().
for (int i = 0; i < NUM_TRAINS; i++)
trainArray[i] = NULL;

// Wait for all Train threads. Also, get the pointers to the Train objects
// and delete() them because they were created by 'new'
// YOUR CODE HERE

return(EXIT_SUCCESS);
}

0 0
Add a comment Improve this question Transcribed image text
Request Professional Answer

Request Answer!

We need at least 10 more requests to produce the answer.

0 / 10 have requested this problem solution

The more requests, the faster the answer.

Request! (Login Required)


All students who have requested the answer will be notified once they are available.
Know the answer?
Add Answer to:
Please fill in the YOUR CODE HERE blocks for trainLine.cpp and provide a sample output. The...
Your Answer:

Post as a guest

Your Name:

What's your source?

Earn Coins

Coins can be redeemed for fabulous gifts.

Similar Homework Help Questions
ADVERTISEMENT
Free Homework Help App
Download From Google Play
Scan Your Homework
to Get Instant Free Answers
Need Online Homework Help?
Ask a Question
Get Answers For Free
Most questions answered within 3 hours.
ADVERTISEMENT
ADVERTISEMENT
ADVERTISEMENT