Search Using 2 threads - c++

'Is the threading correct in this code ?
I am searching a specific key in an array using 2 threads, one thread searches in first half of the array and second thread in second half of the array.'
I have created a struct named as Parameters which I fill with my parameters and pass it to the thread.
I made two Parameters objects to pass to two different threads.
Both have same array and same key, but starting point and ending point are different for both parameters because one thread has to search in first half and the other one has to search in second half.
starting point and ending point are set accordingly.
#include <pthread.h>
#include<unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include<stdlib.h>
#include <iostream>
using namespace std;
#define len 5
struct Parameters{
int start;
int end;
int*arr;
int key;
};
void* search(void* param)
{
Parameters *pm = (Parameters*) param;
int s = pm->start;
int e = pm->end;
int *A = pm->arr;
int k = pm->key;
bool flag = false;
for(int i= s; i<e ;i++){
if(A[i] == k){
flag = true;
}
}
pthread_exit( (void*) flag);
}
int main(int argc,char* args[])
{
pthread_t id[2];
int A[len] ;
cout<<"Enter "<<len<<" elements \n";
for(int i=0;i<len;i++){
cin>>A[i];
}
Parameters p;
p.arr = A;
p.start = 0;
p.end = len/2;
p.key = 7;
pthread_create(&id[0],NULL,&search,&p);
Parameters p2;
p2.arr = A;
p2.start = len/2;
p2.end = len;
p2.key = 7;
pthread_create(&id[1],NULL,&search,&p2);
bool *found = new bool(false);
for(int i=0;i<2;i++){
pthread_join(id[i], (void**)found);
}
if(*found==true){
cout<<"Found\n";
}
else{
cout<<"Not found\n";
}
return 0;
}

Related

segmentation fault pushing back to vector in shared memory

I working on a program that simulates travel agents booking flights in parallel. It spins up a process for each agent and works against an array of Plane objects held in shared memory.
I'm getting a segmentation fault when I try to push a row of seats back to the plane. The method to parse the input file calls a SetSeats() method on Plane objects. Each Plane contains a vector<map<char, Seat>> (each index of the vector is a row, each key of each map is the letter of a seat on that row). When I call SetSeats() it goes fine through adding seats to the first map, i.e. the first row of seats. It throws the segfault when I try to push the map back to the seats vector.
I saw something online about pushing back custom classes to vectors needing deconstructors, so I added them to Seat.h and Plane.h.
Code for the main program:
#include <iostream>
#include <map>
#include <vector>
#incluce <string>
#include <fstream>
#include "Seat.h"
#include "Plane.h"
void ParseInputFile(ifstream &inFS, int numPlanes, int &numAgents);
int shmid;
int *timer;
int numPlanes, numAgents;
struct sembuf *ops;
Plane *sharedPlanes;
map<string, Plane*> planes;
using namespace std;
int main(int argc, char *argv[])
{
ifstream inFS;
// code to get an input file from command line arguments and get number of planes from it
// set up shared memory segment
long key = XXX; // just a long integer
int nbytes = 1024;
shmid = shmget((key_t)key, nbytes, 0666 | IPC_CREAT);
if (shmid == -1)
{
printf("Error in shared memory region setup.\n");
perror("REASON");
exit(2);
}
// initialize global variables
sharedPlanes = new Plane[numPlanes];
timer = new int;
ops = new sembuf[1];
// attached shared pointers to shared memory segment
sharedPlanes = (Plane*)shmat(shmid, (Plane*)0, 0);
timer = (int*)shmat(shmid, (int*)0, 0);
*timer = 0;
inFS.open(inputFile);
ParseInputFile(inFS, numPlanes, numAgents); // breaks in here
// the rest of main()
}
void ParseInputFile(ifstream &inFS, int numPlanes, int &numAgents)
{
string line = "";
bool foundNumberOfPlanes = false;
bool foundPlanes = false;
bool foundNumberOfAgents = false;
bool lookingForAgent = false;
bool foundAgent = false;
int planeNo = 0;
int agentNo = 0;
int opNo = 0;
map<string, Operation> ops;
vector<Request> agentRequests;
while (getline(inFS, line))
{
if (!CommonMethods::IsWhitespace(line))
{
// code to read first line
if (foundNumberOfPlanes && !foundPlanes)
{
// parse a line from the input file to get details about the plane
Plane *plane = &sharedPlanes[planeNo];
unsigned int rows = xxx; // set based on the plane details
unsigned int seatsPerRow = xxx; set based on the plane details
plane->SetSeats(rows, seatsPerRow); // this is the method where I get the seg fault
// finish defining the plane
continue;
// the rest of the method
}
}
}
}
Code for Plane.h:
#pragma once
#include <iostream>
#include <string>
#include <map>
#include <tuple>
#include <vector>
#include "Seat.h"
#include "Exceptions.h"
#include "ReservationStatus.h"
#include "CommonMethods.h"
using namespace std;
class Plane
{
private:
vector<map<char, Seat>> seats;
unsigned int numberOfRows, numberOfSeatsPerRow;
public:
Plane(unsigned int numberOfRows, unsigned int numberOfSeatsPerRow);
Plane() {}
void SetSeats(unsigned int numberOfRows, unsigned int numberOfSeatsPerRow);
};
void Plane::SetSeats(unsigned int numberOfRows, unsigned int numberOfSeatsPerRow)
{
//cout << "Clearing old seats" << endl;
if (!seats.empty())
{
//cout << "Seats not empty" << endl;
for (int i = 0; i < (int)seats.size(); i++)
{
//cout << "checking row " << i << endl;
if (!seats.at(i).empty())
{
//cout << "Row " << i << " not empty" << endl;
seats.at(i).clear();
}
}
}
cout << "Rows: " << numberOfRows << ", Seats: " << numberOfSeatsPerRow << endl;
this->numberOfRows = numberOfRows;
this->numberOfSeatsPerRow = numberOfSeatsPerRow;
for (unsigned int i = 0; i < this->numberOfRows; i++)
{
map<char, Seat> row;
for (unsigned int j = 0; j < this->numberOfSeatsPerRow; j++)
{
Seat seat;
seat.RowNumber = i + 1;
seat.SeatLetter = j + 'A';
//cout << "Inserting seat " << seat.RowNumber << seat.SeatLetter << endl;
row.insert(pair<char, Seat>(seat.SeatLetter, seat));
}
if (!row.empty())
{
cout << "inserting row " << (i + 1) << endl;
seats.push_back(row);
}
}
}
void Plane::ProcessWaitAny(int t)
{
while (!WaitingList.empty())
{
bool booked = false;
string pass = WaitingList.front();
WaitingList.pop();
for (unsigned int j = 0; j < numberOfRows; j++)
{
if (booked)
break;
for (unsigned int k = 0; k < numberOfSeatsPerRow; k++)
{
Seat *s = &seats.at(j)[k + 'A'];
if (!s->IsBooked)
{
Reserve(s, pass);
booked = true;
string seatNo = to_string(j);
seatNo += (k + 'A');
cout << "Passenger " << pass << " booked into seat " << seatNo << " at time " << t << endl;
break;
}
}
}
if (!booked)
return;
}
}
Code for Seat.h
#pragma once
#include <iostream>
#include <string>
#include <queue>
using namespace std;
struct Seat
{
string Passenger = "";
bool IsBooked = false;
unsigned int RowNumber;
char SeatLetter;
queue<string> WaitingList;
};
I have made a minimum working example of your problem:
#include <vector>
#include <sys/shm.h>
#include <iostream>
class Bar {
public:
Bar() {};
std::vector<int> vec;
};
int main() {
int shmid;
Bar* a = new Bar();
a->vec.push_back(1);
// set up shared memory segment
long key = 0x123455; // just a long integer
int nbytes = 1024;
shmid = shmget((key_t)key, nbytes, 0666 | IPC_CREAT);
if (shmid == -1)
{
printf("Error in shared memory region setup.\n");
perror("REASON");
exit(2);
}
a = (Bar*)shmat(shmid, (Bar*)0, 0);
a->vec.push_back(2);
}
The problem is your wrong usage of shmat. The pointer sharedPlane just points to some unitialized shared memory. You have to make sure that the address provided by key is 'right'. To do this, do the following:
Your other process, call Plane * other_process_sharedPlane = new Plane();. Remove the line sharedPlanes = new Plane[numPlanes]; from your main programm.
In your main process, set key to the value of other_process_sharedPlane
Then you can call shmget and shmadd

C++ recursive backtracking

I am trying to do recursive backtracking to find a path from point 0 to point 8. I have defined the paths but its goes 0 1 2 and them stops. Can anyone help?
#include <iostream>
#include <vector>
using namespace std;
vector< vector<int> > roads;
void find_path(int Point = 0) {
cout << Point;
int rds = roads.size();
for(int i = 0; i < rds; i++) {
find_path(roads[Point][i]);
}
}
main() {
roads.resize(8);
//VNESUVANJE PATISTA
roads[0].push_back(1);
roads[0].push_back(3);
roads[1].push_back(2);
roads[3].push_back(4);
roads[3].push_back(6);
roads[4].push_back(5);
roads[4].push_back(7);
roads[7].push_back(8);
find_path();
return 0;
}
I did some changes i think now it works properly.
#include <iostream>
#include <vector>
using namespace std;
vector< vector<int> > roads;
int path_finded = 0; //Added new variable to know if path is finded.
void find_path(int Point = 0) {
if(Point == 8) { //Checks if the point where we are is 8 and if it is stops the whole thing and chages path_finded to 1
path_finded = 1;
return;
}
int rds = roads[Point].size();//changed roads.size to roads[Point].size so it gives the size of the possible roads from the point where we are.
for(int i = 0; i < rds; i++) {
find_path(roads[Point][i]);
}
return;
}
main() {
roads.resize(8);
//VNESUVANJE PATISTA
roads[0].push_back(1);
roads[0].push_back(3);
roads[1].push_back(2);
roads[3].push_back(4);
roads[3].push_back(6);
roads[4].push_back(5);
roads[4].push_back(7);
roads[7].push_back(8);
find_path();
if(path_finded == 1) cout << "RABOTI"; //prints if it works.
return 0;
}

Calling two Queue class function in a loop

I have problem with this code of mine. Whenever i call two function of the class, and in those class, there is if-else statement, and print the output on screen, it will only run the if clause of the two functions and not the else. How can i fix this?
For example:
This is my Queue.h file:
#ifndef QUEUE_H
#define QUEUE_H
class Queue {
private:
//private variables
int arr_size;
char *arr;
int head;
int tail;
int count;
public:
Queue(int); //constructor
//functions
int enqueue(char);
int dequeue(char&);
};
#endif
This is my Queue.cpp file:
#include <iostream>
#include "Queue.h"
using namespace std;
Queue::Queue(int size) {
//initializing
arr_size = size;
arr = new char[size];
for (int i = 0; i < arr_size; i++) {
arr[i] = NULL;
}
head = 0;
tail = 0;
count = 0;
}
int Queue::enqueue(char value) {
if (count<arr_size) //if array is not full, execute below
{
arr[tail++] = value; //pass value of first-to-last element in array
count++; //counting the input value
cout << "\nEnqueue Value: "<< arr[tail-1];
return 0;
}
else {
tail = 0;
cout << "\nArray is full. Value cannot be write: " << value;
return -1;
}
}
int Queue::dequeue(char &read_val) {
if (count !=0) { //if array has elements, execute below
read_val = arr[head]; //pass-by-reference the value of first-to-last element in array to parameter of function
cout <<"\nDequeue Value: "<<read_val;
arr[head] = NULL;
count--;
if (head++ == arr_size) {
head = 0;
}
return 0;
}
else if (count ==0) {
cout << "\nArray is empty. Cannot be dequeue";
return -1;
}
}
And this is what my Source file:
#include "Queue.h"
#include <iostream>
using namespace std;
int main() {
int n;
cout << "Please enter the desired size of the array: ";
cin >> n;
char read_val = NULL;
Queue myqueue(n);
char arr[] = "Hello World, this is ELEC3150";
int size = sizeof(arr)-1;
int count = 0;
for (int i = 0; i < 5; i++) {
myqueue.enqueue(arr[count]);
count++;
myqueue.dequeue(read_val);
}
If i enter the size of the array to be less than 5, it must print the error message saying the array is full in the enqueue function and the array is empty in the dequeue function but did not.

Why does my code have an "Apple Mach-O Linker Error?"

I get this error when i build the program: Apple Mach-O Linker (ld) Error Linker Command failed with exit code 1. Usually when I try to fix this error, its because the file with the main function is #include-ing a file more than once. However, I do not believe that that is the case this time. I am also notified by X Code that the duplicate symbol _passed in: ranker.o and olympic.o.
//competitor.h
#ifndef __Olympic_Lab__competitor__
#define __Olympic_Lab__competitor__
#include <iostream>
using namespace std;
class Competitor {
char* name = nullptr;
int laneAssignment;
float time;
public:
Competitor(char n[], int lane);
~Competitor();
void setTime(float f);
char* getName(){ return name; }
int getLane(){ return laneAssignment; }
float getTime(){ return time; }
void print(){ cout << name << endl; }
};
#endif
//competitor.cpp
#include "competitor.h"
Competitor::Competitor(char n[], int lane){
name = n;
laneAssignment = lane;
}
Competitor::~Competitor(){
//does nothing for now
}
void Competitor::setTime(float t){
time = t;
}
//ranker.h
#ifndef __Olym__ranker__
#define __Olym__ranker__
#include <vector>
#include "competitor.h"
using namespace std;
int passed = 0;
class Ranker {
bool boolean = true;
public:
vector<Competitor*> rv;
Ranker(int lanes);
~Ranker();
int addList(Competitor* c);
Competitor* getLane(int lane);
Competitor* getFinish(int finish);
int getFilled();
};
#endif
//ranker.cpp
#include "ranker.h"
Ranker::Ranker(int lan){
rv.resize(lan - 1);
for(int i = 0; i <= rv.size(); i++){
rv[i] = nullptr;
}
}
Ranker::~Ranker(){
for(int i = 0; i <= rv.size(); i++){
delete rv[i];
}
}
int Ranker::addList(Competitor *c){
if(c != NULL && passed <= 4){
rv[passed++] = c;
return passed - 1;
}
return 0;
}
Competitor* Ranker::getLane(int lane){
for(int i = 0; i <= rv.size(); i++){
if(rv[i]->getLane() == lane && rv[i] != NULL){
return rv[i];
}
}
return rv[0];
}
Competitor* Ranker::getFinish(int finish){
if(boolean){
Competitor *temp = nullptr;
int highestIndex;
for(int i = rv.size(); i >= 0; i--){
highestIndex = i;
for(int j = i; j >= 0; j--){
if(rv[j] != nullptr && rv[highestIndex] != nullptr){
if(rv[j]->getTime() > rv[highestIndex]->getTime())
highestIndex = j;
}
}
temp = rv[i];
rv[i] = rv[highestIndex];
rv[highestIndex] = temp;
}
delete temp;
temp = *new Competitor*;
boolean = false;
}
return rv[finish - 1];
}
int Ranker::getFilled(){
int filled = 0;
for(int i = 0; i <= rv.size(); i++){
if(rv[i] != NULL){
filled++;
}
}
return filled;
}
//olympic.h
#ifndef _Olympic_Lab__olympic__
#define _Olympic_Lab__olympic__
#include "ranker.h"
#endif
//olympic.cpp
#include "olympic.h"
int main(){
const int lanes = 4;
Ranker rank(lanes);
Competitor* starters[4];
starters[0] = new Competitor("EmmyLou Harris", 1);
starters[1] = new Competitor("Nanci Griffith", 2);
starters[2] = new Competitor("Bonnie Raitt", 3);
starters[3] = new Competitor("Joni Mitchell", 4);
starters[0]->setTime((float)12.0);
starters[1]->setTime((float)12.8);
starters[2]->setTime((float)11.0);
starters[3]->setTime((float)10.3);
for(int i = 0; i < lanes; i++){
rank.addList(starters[i]);
}
cout << "Competitors by lane are:" << endl;
for(int i = 1; i <= lanes; i++)
rank.getLane(i)->print();
cout << "Rankings by finish are:" << endl;
for(int i = 1; i <= lanes; i++)
rank.getFinish(i)->print();
for(int i = 0; i < lanes; i++){
delete starters[i];
}
}
It would be appreciated if someone could assist me in finding exactly what causes this error. Thanks!
If you declare a variable in a header it will be duplicated in every file that includes the header.
So int passed = 0; in ranker.h is going to give you a lot of grief. ranker and olympian both have allocated a different passed and the linker now has no clue which one is the real passed.
So what you probably want is
extern int passed;
in ranker.h to declare that passed will exist at some point, if it doesn't yet, so it doesn't need to be allocated. The compiler will happily carry on and allow you to use passed.
And then in ranker.cpp, declare
int passed = 0;
to allocate passed and satisfy the linker. Now you have only one passed and anyone who includes ranker.h can see and use it.
If you want more than one passed, you have to do something else so that they don't share the same name and scope, but this doesn't look like your goal.
Off topic: resist the urge to put using namespace std;in a header file. It can lead to future problems that can be very hard to debug. More here: Why is "using namespace std" considered bad practice?

Create a randomly connected set of nodes?

I'm trying to write a function, generate_labyrinth(), that creates a fixed number of randomly connected nodes. Each node is connected with three other nodes.
Here is what I have now:
labyrinth.h:
#ifndef LABYRINTH_H
#define LABYRINTH_H
// node
class Room {
public:
Room ()
: room_number(0), left_door(nullptr),
center_door(nullptr), right_door(nullptr) { }
// data member
int room_number;
// pointers to other nodes
Room* left_door;
Room* center_door;
Room* right_door;
};
//=================================================
class Labyrinth {
public:
Labyrinth (int s) : size(s) { generate_labyrinth (); }
private:
// number of nodes
int size;
// root node
Room* entrance;
// Helper functions
int random_number (int from, int to);
int random_number_without_i (int min, int max, int i);
// Initialiazation function
void generate_labyrinth ();
};
#include "labyrinth.cpp"
#endif
labyrinth.cpp:
// Class Labyrinth member implementations
int Labyrinth::random_number (int min, int max) {
static bool seed_initialized = false;
if (!seed_initialized) {
seed_initialized = true;
srand((unsigned int) time(NULL));
}
return rand() % (max - min + 1) + min;
}
int Labyrinth::random_number_without_i (int min, int max, int i) {
int res = random_number(min, max);
while (res == i){
res = random_number(min, max);
}
return res;
}
void Labyrinth::generate_labyrinth () {
// create "size" number of nodes
entrance = new Room[size];
// initialize Room (node) data members
for (auto i = 0; i < size; ++i) {
entrance[i].room_number = i;
}
// connect each room with three others
int first_room = 1;
int last_room = size - 1;
for (int i = 1; i < size; ++i) {
// avoid connecting a room with itself
int left_goes_to = random_number_without_i (first_room, last_room, i);
int center_goes_to = random_number_without_i (first_room, last_room, i);
int right_goes_to = random_number_without_i (first_room, last_room, i);
entrance[i].left_door = (&entrance[left_goes_to]);
entrance[i].center_door = (&entrance [center_goes_to]);
entrance[i].right_door = (&entrance [right_goes_to]);;
}
// TEST IF NODES POINT TO EACH OTHER
for (auto i = 0; i < size; ++i) {
if (entrance[i].left_door == nullptr || entrance[i].center_door == nullptr ||
entrance[i].right_door == nullptr) {
std::cout <<"Uninitialized pointer value\n";
}
}
getchar();
}
main:
#include <iostream>
#include <time.h>
#include "labyrinth.h"
//=================================================
int main()
{
int cave_size = 20;
Labyrinth cave(cave_size);
}
It appears that after the node initialization in generate_labyrinth () the three pointers, left_room, center_room, right_room remain uninitialized, i.e. the output I get is :
Uninitialized pointer value
Questions:
Why aren't the pointers in the nodes initialized?
Is there another way to generate a randomly connected set of nodes?
Note: I'm not using an insert() function as the number of nodes is fixed and determined during the construction of the data structure.
You generate connections for first_room to last_room, which are rooms 1 to size-1.
// connect each room with three others
int first_room = 1;
int last_room = size - 1;
for (int i = 1; i < size; ++i) {
But when you check the connections you start with room 0 (probably supposed to be the entrance itself).
// TEST IF NODES POINT TO EACH OTHER
for (auto i = 0; i < size; ++i) {