[SOLVED] C++ data structure software EEEN30052 Concurrent Systems 2019-20 Assignment

$25

File Name: C++_data_structure_software_EEEN30052_Concurrent_Systems_2019-20_Assignment.zip
File Size: 706.5 KB

5/5 - (1 vote)

EEEN30052 Concurrent Systems 2019-20 Assignment
1. Introduction
This assignment is concerned with simulating some aspects of a simple embedded computer system. You may choose between two versions: A1 or A2. Each is worth a different percentage of the overall coursework mark: A1 is a simplified version of the assignment and is worth 45%, while A2 is the full version and is worth 90%. In addition there are two questions based on the coursework which must be answered during the assessment. These questions are worth 10%, thus the maximum mark available for A1 is 55%, and the maximum available for A2 is 100%.
The system shown below in Figure 1 is responsible for gathering environmental data via a single analogue-to-digital converter (ADC), and transmitting it to another computer system via one of three communications links. The software in the embedded system consists initially of six threads, each of which is responsible for gathering data on different input channels, temporarily storing it, and then transmitting it to the other computer system in blocks. In order to acquire data, each thread must gain sole access to the ADC, configure it to sample from a specific channel, and sample the channel. In order to transmit a block of data, a thread must gain access to one of the communications links. Having gained access, it sends its block of data, and then releases the link. Each thread may use any communications link, but once it has gained access to a particular link, no other thread should be allowed to use that link until it is released.
Analogue input channels
ADC Threads
Link Access Communications links
Figure 1
If you choose to do A2 you should start by implementing A1, but you will not be required to demonstrate it or upload a copy (of A1). If you choose A1 you do not need to attempt A2, or demonstrate/upload it. However, in both cases your program should print out messages clearly indicating the identity of the calling thread and what action it is performing.
1

2. A1 worth 45% of total coursework marks
Write a C++ program that creates six threads where each thread is identified by an integer and has a reference to an object of class ADC, which is described below. Each thread executes the following sequence 50 times:
Request use of the ADC by calling the requestADC() method of the ADC object. This call passes an integer argument representing the channel to be sampled. The ADC has several channels (initially six), each represented by an instance of AdcInputChannel. Assume that each thread uses a unique AdcInputChannel. The thread should print out its identity when the call is successful.
Request a sample from the ADC by calling sampleADC(). This returns a double value on the basis of the channel that was selected by the requestADC() call. To start with, simply make the sampleADC() method return a value that is twice the channel number passed in the call to requestADC().
Print out its identity together with the sample value obtained from the ADC.
Call releaseADC() to enable other threads to use the ADC, printing out its identity once more.
Delay for a random time between 0.1 and 0.5 second.
A function called run() will be used to implement the above. Objects of class ADC have a reference to an instance of class Lock, to help ensure mutually exclusive access to the ADC. Hence when a thread wishestoaccesstheADCitcallsrequestADC(),whichinturncallsthelock() methodoftheLock object. If the ADC is not currently in use, it will be locked and the thread will be allowed to proceed to use the ADC. However, if the ADC is in use, then the thread calling requestADC() should be suspended until the ADC has been relinquished by the using thread calling releaseADC(), which in turn calls the unlock() method of the Lock object. Thus threads are suspended and resumed- in requestADC() and releaseADC(), depending on the result of the call to the Lock objects lock() method.
The main program should create six threads and one object of class ADC. Initially the ADC has six AdcInputChannels (it is recommended to use a vector rather than an array for this purpose). It should initiate execution of the threads and should not terminate until all threads have terminated. To help you get started the following is a partially-complete skeleton of the program:
//comment: authors name, ID, and date.
//pre-processor directives: #include #include .
using namespace std;
//global constants:
int const MAX_NUM_OF_CHAN = 6;
int const MAX_NUM_OF_THREADS = 6;
int const DATA_BLOCK_SIZE = 20;
//number of AdcInputChannels
continued..
2

//global variables:
.
//function prototypes: (if used)
.
class AdcInputChannel {
public:
AdcInputChannel(int d) //constructor
: currentSample(d) {} //constructor syntax for currentSample=d
//used to request a sample from the sample channel:
double getCurrentSample() {
.
} private:
int currentSample;
}; //end class AdcInputChannel
class Lock {
public:
Lock() //constructor : open(true) {}
//returns a flag to indicate when a thread should be blocked:
bool lock() {
.
}
void unlock() {
.
} private:
bool open;
}; //end class Lock
class ADC {
public:
//constructor: initialises a vector of ADCInputChannels //passed in by reference: ADC(std::vector & channels)
:adcChannels(channels) {}
void requestADC(int c) {
.
}
double sampleADC() {
.
}
void releaseADC() {
.
}
continued..
3

private:
Lock theADCLock;
int sampleChannel; std::vector & adcChannels; std::mutex ADC_mu; //mutex
}; //end class ADC
//run function executed by each thread:
void run(ADC& theADC, int id) {
.
//vector reference
//to store the sampled data: (for part A2 only)
double sampleBlock[DATA_BLOCK_SIZE] = {0.0}; //initialise all elements to 0
for (i=0; i<50; i++) { //replace with ‘i adcChannels; for (int i = 0; i < MAX_NUM_OF_CHAN; i++) {…. //each AdcInputChannel is initialised with a different value }// Instantiate the ADC:….//instantiate and start the threads:std::thread the_threads[MAX_NUM_OF_THREADS]; //array of threads for (int i = 0; i < MAX_NUM_OF_THREADS; i++) {//launch the threads:…. }//wait for the threads to finish:….cout << “All threads terminated” << endl;return 0; }4The code is incomplete in a number of different senses, and you must modify it in order to complete A1. You are free to include any additional methods/functions/variables/constants, as you think necessary. Note that a solution that is poorly commented, or that does not calculate and use the delay period correctly, will lose marks (see the marking sheet).Part of an example output is shown below:Notes on the Program2.1 Thread ‘Identity’Obtaining the ‘id’ value of a thread in C++11 is done with std::this_thread::get_id()-however this returns an object not an integer, and although this can be passed to coutfor printing (e.g. cout << std::this_thread::get_id() << endl;), unfortunately there’s no simple way to cast it to an int.For example, if you create say, three threads, and printed out their ids, you might get 234Ideally, we want to be able to associate a known integer ‘id’ with each thread so we can identify them as’thread 0′, thread 1′, etc..One solution is to create a std::map of thread ‘ids’ v. integers, e.g. thread ‘id’ int value20 31 42..etc. 5To associate the thread ‘id’ with an integer value in a map, the following might be helpful:std::mutex mu; //declare a mutexstd::unique_lock map_locker(mu); //lock the map via the mutex. //insert the threadID and id into the map: threadIDs.insert(std::make_pair(std::this_thread::get_id(), id)); map_locker.unlock(); //were done, unlock the map.
A recommended way to search the map by thread id is to use an interator, e.g.:
std::map ::iterator it
= threadIDs.find(std::this_thread::get_id());
if (it == threadIDs.end()) return -1; //thread id NOT found else return it->second; //thread id found, return the
//associated integer note the syntax. It might be useful to put the search code in a separate function.
You will need the following preprocessor directive in order to use a map:
#include

For more info about maps, with more examples, see e.g.:

C++ : Map Tutorial Part 1: Usage Detail with examples


2.2 Creating a delay by generating random values.
One way to generate say, random integers, is to use a pseudo-random number generator, and seed it with a value. The code below shows one way of doing this (adapted from http://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution)
std::mt19937 gen(time(0)); //A Mersenne_twister_engine seeded by time(0). //time(0) gives the number of seconds elapsed since the start //of the world according to Unix (00:00:00 on 1st January 1970).
std::uniform_int_distribution<> dis(1, 1000); //generate a random integer //between 1-1000.
int n = dis(gen);
-the pseudo-random number is stored in n.
You will need the following preprocessor directives in order to use the above example code:
#include
#include
Note that only a single generator is necessary.
2.3 Vectors or Arrays?
In general in C++11 it is straightforward to create arrays of objects of classes from the standard library, such as std::thread, for example. However, arrays of objects of user-defined classes, such as AdcInputChannel, or Link, are more awkward to use. For such user-defined classes you may find std::vector much easier to handle, for example:
std::vector adcChannels; or std::vectorcommsLinks;
A tutorial is available here:
http://www.codeguru.com/cpp/cpp/cpp_mfc/stl/article.php/c4027/C-Tutorial-A-Beginners- Guide-to-stdvector-Part-1.htm
6

3. A2 worth 90% of total coursework marks
In A1 we were concerned with creating threads and being able to lock the ADC. In this version we extend the solution to include access to the communications links. In particular, the threads should request a Link from a LinkAccessController object. When one is available, the sample values that the thread has acquired can be transmitted. The Link object is used to copy this data to the Receiver object which stores the samples from each thread in a two-dimensional array. The row in which the data is stored corresponds to the threads identifier (id). The Receiver class provides a method to print out this two-dimensional array.
The main program should create and initiate all the threads, and should wait until they have all have terminated before calling the Receivers method that prints out its two-dimensional array.
Part A2 builds on A1 and requires the following additional classes:
LinkAccessController. As indicated above, there are three communications links that can be accessed simultaneously. The actual number is defined by an additional global constant:
int const NUM_OF_LINKS = 3;
A single instance of the LinkAccessController class, called lac, controls access to these links, ensuring that they can be used simultaneously. However, if all the links are in use and additional threads attempt to gain access to one, these latter threads should be suspended until one or more links become available. Threads should print out their identity, together with their actions, when accessing links: i.e. when they successfully acquire and release a link, and when (if) they are suspended. The partial code for class LinkAccessController is given below.
class LinkAccessController {
public:
LinkAccessController(Receiver& r) //Constructor
: myReceiver(r), numOfAvailableLinks(NUM_OF_LINKS) {
for (int i = 0; i < NUM_OF_LINKS; i++) { commsLinks.push_back(Link(myReceiver, i));} }//Request a comm’s link: returns an available Link.//If none are available, the calling thread is suspended. Link requestLink() {….return commsLinks[linkNum];}//Release a comms link:void releaseLink(Link& releasedLink) { ….}continued..7private:Receiver& myReceiver; //Receiver reference int numOfAvailableLinks;std::vector commsLinks;
std::mutex LAC_mu; //mutex
}; //end class LinkAccessController
Link. Instances of this class represent the communication links in the system. The partial code for Link
class is given below:
class Link {
public:
Link (Receiver& r, int linkNum) //Constructor : inUse(false), myReceiver(r), linkId(linkNum)
{}
//check if the link is currently in use
bool isInUse() {
return inUse;
}
//set the link status to busy
void setInUse() {
inUse = true;
}
//set the link status to idle
void setIdle() {
inUse = false;
}
//write data[] to the receiver
void writeToDataLink(int id, double data[]) { .
}
//returns the link Id
int getLinkId() {
return linkId;
}
private:
bool inUse;
Receiver& myReceiver; //Receiver reference int linkId;
}; //end class Link
Receiver. An instance of this class called theReceiver receives the sample blocks from the Link objects via calls to a method called receiveDataBlock(), which in turn writes them into an array called dataBlocks. Data from thread i is written to the ith row of dataBlocks. The method printBlocks prints out the contents of dataBlocks to ensure that the sample values have been transmitted correctly. The partial code for class Receiver is given below:
8

class Receiver {
public:
//constructor:
Receiver () { //syntax -no initialiser list, no :
//initialise dataBlocks:
for (i = 0; i < MAX_NUM_OF_THREADS; i++) {for (j = 0; j < DATA_BLOCK_SIZE; j++) {dataBlocks[i][j] = 0;}} }//Receives a block of doubles such that the data //is stored in index id of dataBlocks[][]void receiveDataBlock(int id, double data[]) {…. }// print out all itemsvoid printBlocks() { ….}private:double dataBlocks[MAX_NUM_OF_THREADS][DATA_BLOCK_SIZE];}; //end class Receiverrun function.The run function for each thread should be extended. The following steps should be added to the sequence given in version A1: Request access to a link. Once a link has been obtained delay for a random time between 0.1 and 0.5 second. The thread should print out its identity and transmit the data (sampleBlock) to the Receiver. Release the link, printing out its identity once more.A link can be obtained as follows: Link link = lac.requestLink();main function.The main function creates the following objects/data structures:int main() { theADC and inputADCInputChannels -as developed in part A1 of this assignment. lac-an object of class LinkAccessController. theReceiver-an object of class Receiver.//initialise the ADC channels:std::vector adcChannels;
continued..
9

for (int i = 0; i < MAX_NUM_OF_CHAN; i++) {…. //each AdcInputChannel is initialised with a different value}// Instantiate the ADC:….// Instantiate the Receiver:….// Instantiate the LinkAccessController:….//instantiate and start the threads:std::thread the_threads[MAX_NUM_OF_THREADS]; //array of threads for (int i = 0; i < MAX_NUM_OF_THREADS; i++) {//launch the threads:…. }//wait for the threads to finish:….// Print out the data in the Receiver:….cout << “All threads terminated” << endl;return 0; }Notes on the ProgramAs per A1, a solution that is poorly commented, or that does not calculate the delay period correctly will lose marks. You are also expected to use the global constants defined in the program in a consistent way throughout, otherwise you may also lose marks.4. Laboratory ArrangementsYour solution to the assignment (A1 or A2) will be demonstrated in Barnes Wallis on your final allocated lab for Concurrent Systems (please check your timetable for the actual date). Demonstration of your program at other times is not permitted. You will be expected to upload a copy of the program to Blackboard for marking during the demonstration. You will also be given fifteen minutes to answer two questions under “closed book” conditions; these questions are based on the coursework assignment, and are worth 10% in total.NOTE CAREFULLY: a learning objective of this assignment is to be able to explain how a concurrent program works. During the demonstration you will be asked simple questions about your program, for example the effect on the program of changing one or more of the constants or variables. Marks will be deducted if you cannot answer the questions that you are asked. continued..105. DeliverablesAn electronic copy of your program should be uploaded at the end of the final session. Programs without comments or with few comments will automatically receive low marks.6. PlagiarismThis is an individual assignment. Any plagiarism will be referred to the Director of Studies and penalties will be applied in accordance with University policy.11

Reviews

There are no reviews yet.

Only logged in customers who have purchased this product may leave a review.

Shopping Cart
[SOLVED] C++ data structure software EEEN30052 Concurrent Systems 2019-20 Assignment
$25