I am trying to develop a code which generates N threads into a loop. Each thread generates 40 random numbers and pick from them the highest. Afterwards, I have to choose the highest number from all. However, when I return the highest value of each thread (b) it is empty, this is the code I am using:
class rdm_thr
{
public:
rdm_thr()
{
}
void rdmgen()
{
default_random_engine generator;
double rdm;
b=0;
normal_distribution<double> normal(0, 1);
for(int i=0; i<40; i++)
{
rdm = normal(generator);
if(rdm>b)
b = rdm;
}
}
};
void main()
{
vector<boost::thread *> z;
vector<rdm_thr> o;
boost::function<void()> th_func;
for (int i = 0; i < 2; i++)
o.push_back(rdm_thr());
for (int i = 0; i < 2; i++)
{
th_func = boost::bind(&rdm_thr::rdmgen, &o[i]);
boost::thread thr(th_func);
z.push_back(&thr);
}
for (int i = 0; i < 2; i++)
{
z[i]->join();
}
}
Is there another way to do it?
You could change your class logic as such:
class rdm_thr
{
public:
rdm_thr() {}
void rdmgen()
{
...
}
void join() { t.join(); }
void start()
{
t = boost::thread(boost::bind(&rdm_thr::rdmgen, this));
}
private:
boost::thread t;
// could also be pointer type and 'new/delete' would have to be used in that event
};
#define TSZ 2
void main()
{
std::vector<rdm_thr*> o;
int i = 0;
for (; i < TSZ; i++) {
o.push_back(new rdm_thr());
o.back()->start();
}
for (i = 0; i < TSZ; i++) {
o[i]->join();
delete o[i]; //clean up
}
}
And if you didn't want to change your class logic, you could do the following in your main function:
#define TSZ 2
void main()
{
std::vector<boost::thread *> z;
std::vector<rdm_thr *> o;
int i = 0;
for (; i < TSZ; i++) {
o.push_back(new rdm_thr());
z.push_back(new boost::thread(boost::bind(&rdm_thr::rdmgen, o.back())));
}
for (i = 0; i < TSZ; i++) {
z[i]->join();
delete z[i];
delete o[i];
}
}
I don't have access to a compiler right now so I can't verify 100%, but as your asking more on theory, the above code is to help illustrate alternative ways of achieving similar results.
I hope that can help
Related
This is my class to print data
class PrintData
{
int data[20];
public:
void setData(int dataValue[])
{
for( int i = 0 ; i < 20; i++)
data[i] = dataValue[i];
}
void Print()
{
for (int i = 0; i < 20; i++)
std::cout << data[i];
std::cout << std::endl;
}
};
This is the main function
int number[20] ;
void updateNumber()
{
for (int i = 0; i < 1000; i++) {
// std::this_thread::sleep_for(std::chrono::milliseconds(1000));
for (int k = 0; k < 20; k++)
number[k] = k;
// after one iteration it should wait and after the print.Print() is executed than it should again update the data
}
}
int main()
{
PrintData print;
std::thread t(&updateNumber);
while (true)
{
// if upDateNumber has updated all the numbers than only than only set the number
print.setData(number);
print.Print();
}
return 0;
}
After iteration has finished in the thread it should wait for the print.setData(number) function to execute , once this function has executed it should again update the data.
if print.setData(number) is called and the thread is still not finished updating the array than print.setData(number) should not update the data.
A simple example of a producer consumer problem involving conditional variables would be something like that:
#include <thread>
#include <mutex>
#include <iostream>
#include <condition_variable>
#include <vector>
#include <unistd.h>
#define MAX_SIZE 2
struct Task
{
std::condition_variable m_cond;
std::mutex m_lock;
Task(){}
};
std::vector<int> m_data;
Task m_producer;
Task m_consumers[MAX_SIZE];
std::mutex m_lock;
static bool s_Busy = false;
static void producer(void)
{
for(;;)
{
size_t input=0;
std::unique_lock<std::mutex> lock{m_lock};//{m_producer.m_lock};
if (!s_Busy) {
std::cout << "Enter a number: ";
std::cin >> input;
std::cout << "Producer waiting..." << std::this_thread::get_id() << "\r\n";
m_producer.m_cond.wait(lock);
}
s_Busy = true;
if (m_data.size() < input) {
for (size_t i=0; i < input; ++i){
m_data.push_back(i);
}
}
for (int i=0; i < MAX_SIZE; ++i) {
m_consumers[i].m_cond.notify_one();
}
lock.unlock();
}
}
static void consumers(void)
{
for(;;)
{
std::unique_lock<std::mutex> lock{m_lock};
if (!s_Busy) {
std::cout <<"Consumers waiting....!" << std::this_thread::get_id() << "\r\n";
for (int i=0; i < MAX_SIZE; ++i) {
m_consumers[i].m_cond.notify_all();
}
}
if (!m_data.empty()) {
std::cout << "Remove: " << m_data.at(0) << std::endl;
m_data.erase(m_data.begin());
usleep(1);
}
s_Busy = false;
m_producer.m_cond.notify_one();
lock.unlock();
}
}
int main()
{
std::vector<std::thread> cnsmrs;
std::thread usr{producer};
for (int i=0; i < MAX_SIZE; ++i)
cnsmrs.push_back(std::thread{consumers});
usr.join();
for(int i=0 ; i < MAX_SIZE; ++i)
cnsmrs.at(i).join();
return 0;
}
You can play with different logic and implementation.
I hope this help you: (semaphore is a self implementation of Qt's QSemaphore)
#include <thread>
#include <mutex>
#include <condition_variable>
#include <iostream>
class semaphore
{
public:
semaphore(int n = 0) : m_n(n)
{
}
public:
void acquire(int n = 1)
{
std::unique_lock <std::mutex> lk(m_buf_mut);
while (m_n < n) {
m_cv.wait(lk);
}
m_n -= n;
}
void release(int n = 1)
{
{
std::unique_lock <std::mutex> lk(m_buf_mut);
m_n += n;
}
m_cv.notify_all();
}
bool tryAcquire(int n = 1)
{
std::unique_lock <std::mutex> lk(m_buf_mut);
if (m_n >= n) {
m_n -= n;
return true;
}
return false;
}
private:
std::mutex m_buf_mut;
int m_n;
std::condition_variable m_cv;
};
class PrintData
{
int data[20];
public:
void setData(int dataValue[])
{
for( int i = 0 ; i < 20; i++)
data[i] = dataValue[i];
}
void Print()
{
for (int i = 0; i < 20; i++)
std::cout << data[i];
std::cout << std::endl;
}
};
int number[20] ;
void updateNumber(semaphore *freeSem, semaphore *usedSem)
{
for (int i = 0; i < 1000; i++) {
// std::this_thread::sleep_for(std::chrono::milliseconds(1000));
//
freeSem->acquire();
for (int k = 0; k < 20; k++)
number[k] = k;
usedSem->release();
// after one iteration it should wait and after the print.Print() is executed than it should again update the data
}
}
int main()
{
PrintData print;
semaphore freeSem(1);
semaphore usedSem(0);
std::thread t(&updateNumber, &freeSem, &usedSem);
while (true)
{
// if upDateNumber has updated all the numbers than only than only set the number
usedSem.acquire();
print.setData(number);
print.Print();
freeSem.release();
}
return 0;
}
I'm working on a coding assignment for a C++ class. When I run my program I seem to be dealing with a memory leakage issue, which is weird since I am NOT explicitly allocating any memory in my code. I ran the program under gdb, and it seems as though the program crashes when running the destructor for a Deck object. I tried stepping through the code, but I when I do so I end up in a host of .h files related to vectors. Then suddenly, it stops. I tried going to a TA for some help, but they seem to be as perplexed as I am on the issue.
# include <stdlib.h>
# include <time.h>
# include <iostream>
# include <vector>
# include <stdio.h>
using namespace std;
//function signatures
float bustProbability (const int);
class Deck
{
public:
//data members
vector <int> cardArray;
vector <int> wasteCards;
//constructor
Deck();
//methods
void shuffleDeck();
void populateDeckWithCards();
void removeCopyCards();
int dealCard();
int remainingCards();
void showCards();
};
void Deck::removeCopyCards() {
for (unsigned int i = 0; i < wasteCards.size(); i++) {
bool removedCopy = false;
for (unsigned int j = 0; j < cardArray.size() && removedCopy == false; j++) {
if (cardArray[j] == wasteCards[i]) {
cardArray.erase (cardArray.begin() + j - 1);
removedCopy = true;
}
}
}
}
int Deck::dealCard() {
if (remainingCards() > 0) {
int tmp = cardArray.back();
wasteCards.push_back(tmp);
cardArray.pop_back();
return tmp;
}
else {
populateDeckWithCards();
removeCopyCards();
shuffleDeck();
//shuffle method
int tmp = cardArray.back();
cardArray.pop_back();
return tmp;
}
}
void Deck::populateDeckWithCards() {
//populate regular cards into array
for (int i = 2; i <= 10; i++) {
for (int j = 0; j < 4; j++) {
cardArray.push_back(i);
}
}
//populate J, Q, K into array
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) {
cardArray.push_back(10);
}
}
//populating array with Aces... treating them as special case '100'
for (int i = 0; i < 4; i++) {
cardArray.push_back(100);
}
return;
}
void Deck::showCards() {
for (unsigned int i = 0; i < cardArray.size(); i++) {
cout << cardArray[i] << endl;
}
}
Deck::Deck() {
wasteCards.clear();
cardArray.clear();
populateDeckWithCards();
shuffleDeck();
}
void Deck::shuffleDeck() {
int n = cardArray.size();
for(int a = n-1; a > 0; a--) {
int min = 0;
int max = a;
int j = min + rand() / (RAND_MAX / (max-min + 1) + 1);
int tmp = cardArray[a];
cardArray[a] = cardArray[j];
cardArray[j] = tmp;
}
return;
}
int Deck::remainingCards() {
return cardArray.size();
}
class Player {
public:
//data members
vector <int> playerHand;
//constructor
Player();
//methods
bool isBust();
int count();
void hit(Deck&);
void stand();
bool muckHand();
void showHand();
};
Player::Player() {
playerHand.clear();
}
void Player::showHand() {
for (unsigned int i = 0; i < playerHand.size(); i++) {
cout << playerHand[i] << endl;
}
return;
}
int Player::count() {
int handCount = 0;
for (unsigned int i = 0; i < playerHand.size(); i++) {
if (playerHand[i] != 100)
handCount += playerHand[i];
else {
if (playerHand[i] == 100) {
if ((handCount) > 11) {
handCount += 1;
}
else
handCount += 10;
}
}
}
return handCount;
}
bool Player::isBust() {
if (count() > 21)
return true;
else
return false;
}
void Player::hit(Deck& d) {
playerHand.push_back(d.dealCard());
}
void Player::stand() {
return;
}
bool Player::muckHand() {
playerHand.clear();
return true;
}
float bustProbability (const int threshHold) {
int threshHoldReached = 0;
Deck myDeck;
Player myPlayer;
Player dealer;
for (int i = 0; i < 10000; i++) {
myPlayer.hit(myDeck);
dealer.hit(myDeck);
myPlayer.hit(myDeck);
dealer.hit(myDeck);
while (myPlayer.count() < threshHold) {
myPlayer.hit(myDeck);
}
if (!(myPlayer.isBust())) {
++threshHoldReached;
}
myDeck.wasteCards.clear();
myPlayer.muckHand();
dealer.muckHand();
}
float bustFraction = float(threshHoldReached)/float(10000);
return bustFraction;
}
int main () {
cout << "blackjack simulation" << endl;
srand((unsigned int)time(NULL));
cout << bustProbability(19);
return 0;
}
I'm incredibly sorry for just posting my code, but I've spend 4 days on this issue, and I can't even begin to figure out what the problem is.
There is at least the line
cardArray.erase (cardArray.begin() + j - 1);
which seems to be dubious in case of j = 0
I am trying to pass into each thread a struct and have each thread print out the value within the struct and show that it is unique per thread.
My problem is that each thread prints out the same value even though i change the value right before passing it in.
const int NUM_THREADS = 2;
struct number
{
int uniqueNumber;
};
void* showUniqueNumber(void* numberStruct);
int main()
{
pthread_t threadID[NUM_THREADS];
number* numberPtr = new number();
for(int i=0; i < NUM_THREADS; i++)
{
numberPtr->uniqueNumber = i;
pthread_create(&threadID[i], NULL, showUniqueNumber, (void*)numberPtr);
}
for(int i=0; i < 5; i++)
{
pthread_join(threadID[i], NULL);
}
return 0;
}
void* showUniqueNumber(void* numberStruct)
{
number* threadPtrN = (number*)numberStruct;
cout << threadPtrN->uniqueNumber << endl;
return (void*)0;
}
It's because it's the same object. You can do this:
pthread_t threadID[NUM_THREADS];
number numbers[NUM_THREADS];
for(int i = 0; i < NUM_THREADS; i++)
{
numbers[i].uniqueNumber = i;
pthread_create(&threadID[i], NULL, showUniqueNumber, numbers + i);
}
I'm trying put my map render (console, ASCII) to one function, but it don't compile.
It should be look like this:
struct tiles {
unsigned is_visible : 1;
//...
} tile[y][x];
void render_map(const tiles (tile&)[y][x]) {
for (int i = 0; i < y; i++) {
if (tile[y].is_visible == 0) {
//...
}
}
}
int main() {
render_map(tile);
//...
}
I try to do as in this answer: C++ pass an array by reference. (const tiles (tile&)[y][x])
Thanks to all, now it's work!
struct tiles {
unsigned is_visible : 1;
//...
} tile[y][x];
void render_map(const tiles (&tile)[y][x]) {
for (int i = 0; i < y; i++) {
for (int j = 0; j < x; j++) {
if (tile[i][j].is_visible == 0) {
//...
}
}
}
}
int main() {
render_map(tile);
//...
}
And i'll think about using vector.
Sorry for such stupid question :)
You could so something like this:
struct Tiles {
unsigned is_visible : 1;
//...
};
const int x = 5;
const int y = 5;
Tiles tiles[x][y];
void render_map(const Tiles tile[x][y]) {
for (int i = 0; i < y; i++) {
if (tile[y].is_visible == 0) { // tile is a 2d array, not a 1D, thus error
//...
}
}
}
int main() {
render_map(tiles);
//...
}
However, since this is C++, I don't see why you don't use a std::vector.
Also read this answer.
With a std::vector, you could do this for example:
void print_vector(std::vector< std:: vector<Tiles> >& v) {
for(unsigned int i = 0; i < v.size(); ++i)
for(unsigned int j = 0; j < v.size(); ++j)
j += 0;
}
int main() {
std::vector< std:: vector<Tiles> >v;
v.resize(2); // make space for two vectors of tiles
Tiles t;
t.is_visible = 0;
v[0].push_back(t);
v[1].push_back(t);
print_vector(v);
return 0;
}
I'm writing a genetic algorithm for which I'm creating a "crossover" operator as a class object that is passed the two parent "chromosomes" Because the input and therefore the output chromosomes are variable lengths, my idea was two divide the input chromosomes and place in a sort of storage class variable, then resize the input chromosomes, and then finally refill the input chromosomes. I'm getting a bad_alloc error, however. If someone could spot my error I'd very much appreciate the help.
Thanks! My class code is below. Note that "plan_vector" is a 2d vector of int types.
#include <iostream>
#include <vector>
#include <eo>
class wetland_vector : public std::vector<int> {
public:
wetland_vector() : std::vector<int>(1, 0) {
}
};
std::istream& operator>>(std::istream& is, wetland_vector& q) {
for (unsigned int i = 0, n = 1; i < q.size(); ++i) {
is >> q[i];
}
return is;
}
std::ostream& operator<<(std::ostream& os, const wetland_vector& q) {
os << q[0];
for (unsigned int i = 1, n = 1; i < q.size(); ++i) {
os << " " << q[i];
}
os << " ";
return os;
}
class wetland_vector_Init : public eoInit<wetland_vector> {
public:
void operator()(wetland_vector& q) {
for (unsigned int i = 0, n = q.size(); i < n; ++i) {
q[i] = rng.random(10);
}
}
};
class plan_vector : public eoVector<double, wetland_vector> {
};
int read_plan_vector(plan_vector _plan_vector) {
for (unsigned i = 0; i < _plan_vector.size(); i++) {
//Call function that reads Quad[1]
//Call function that reads Quad[2]
//etc
return 0;
}
return 0;
};
class eoMutate : public eoMonOp<plan_vector> {
int subbasin_id_min;
int subbasin_id_max;
int wetland_id_min;
int wetland_id_max;
bool operator() (plan_vector& _plan_vector) {
//decide which Quad to mutate
int mutate_quad_ID = rng.random(_plan_vector.size());
//decide which Gene in Quad to mutate
int mutate_gene_ID = rng.random(_plan_vector[mutate_quad_ID].size());
//mutation procedure if first slot in the Quad is selected for mutation
if (mutate_quad_ID = 0) {
_plan_vector[mutate_quad_ID][mutate_gene_ID] = rng.random(subbasin_id_max);
}
//mutation procedure if second slot in the Quad is selected for mutation
if (mutate_quad_ID = 1) {
_plan_vector[mutate_quad_ID][mutate_gene_ID] = rng.random(subbasin_id_max);
}
//note: you'll need to add more for additional wetland characteristics
return true;
};
public:
void set_bounds(int, int, int, int);
};
void eoMutate::set_bounds(int a, int b, int c, int d) {
subbasin_id_min = a;
subbasin_id_max = b;
wetland_id_min = c;
wetland_id_max = d;
}
double evaluate(const plan_vector& _plan_vector) {
int count = 0;
for (int i = 0; i < _plan_vector.size(); i++) {
for (int j = 0; j < _plan_vector[i].size(); j++) {
count += _plan_vector[i][j];
}
}
return (count);
}
class eoQuadCross : public eoQuadOp<plan_vector> {
public:
std::string className() const {
return "eoQuadCross";
}
plan_vector a1;
plan_vector a2;
plan_vector b1;
plan_vector b2;
bool operator() (plan_vector& a, plan_vector& b) {
int cross_position_a = rng.random(a.size() - 1);
int cross_position_b = rng.random(b.size() - 1);
for (int i = 0; i < cross_position_a; i++) {
a1.push_back(a[i]);
}
for (int i = cross_position_a; i < a.size(); i++) {
a2.push_back(a[i]);
}
for (int i = 0; i < cross_position_b; i++) {
b1.push_back(b[i]);
}
for (int i = cross_position_b; i < b.size(); i++) {
b2.push_back(b[i]);
}
int size_a = b2.size() + a1.size();
int size_b = a2.size() + b1.size();
a.resize(size_a);
b.resize(size_b);
for (int i = 0; i < b2.size(); i++) {
a.push_back(b2[i]);
}
for (int i = 0; i < a1.size(); i++) {
a.push_back(a1[i]);
}
for (int i = 0; i < a2.size(); i++) {
b.push_back(a2[i]);
}
for (int i = 0; i < b1.size(); i++) {
b.push_back(b1[i]);
};
//Return bool
return true;
}
};
int main() {
unsigned int vec_size_min = 1;
unsigned int vec_size_max = 10;
unsigned int pop_size = 100;
//BEGIN COPY PARAMETRES
const unsigned int MAX_GEN = 100;
const unsigned int MIN_GEN = 5;
const unsigned int STEADY_GEN = 50;
const float P_CROSS = 0.8;
const float P_MUT = 0.5;
const double EPSILON = 0.01;
double SIGMA = 0.3;
const double uniformMutRate = 0.5;
const double detMutRate = 0.5;
const double normalMutRate = 0.5;
//END COPY PARAMETERS
rng.reseed(1);
//Create population
wetland_vector_Init atom_init;
eoInitVariableLength<plan_vector> vec_init(vec_size_min, vec_size_max, atom_init);
eoPop<plan_vector> pop(pop_size, vec_init);
//Create variation operators
eoMutate mutate;
mutate.set_bounds(1, 453, 1, 4);
eoQuadCross crossover;
eoDetTournamentSelect<plan_vector> select(3);
eoSGATransform<plan_vector> transform(crossover, .5, mutate, .2);
//Create fitness function
eoEvalFuncPtr<plan_vector> eval(evaluate);
//Evaluate initial population and cout
apply<plan_vector > (eval, pop);
std::cout << pop << std::endl;
//Set GA for execution and execute
eoGenContinue<plan_vector> GenCount(5);
eoSGA<plan_vector> gga(select, crossover, .5, mutate, .1, eval, GenCount);
gga(pop);
//cout final population and end
std::cout << pop << std::endl;
std::cout << "The End" << std::endl;
}
a1.~vector();
a2.~vector();
b1.~vector();
b2.~vector();
You shall not destruct the vectors manually, otherwise the next time you try to access them (upon next call to the operator ()) you get undefined behavior.
Why do you call vector destructor manually?? You should let C++ call that for you. If you want to clear the vector use clear member function