Author Topic: Just a teeny tiny problem with C++ multi threading, help?  (Read 2012 times)

0 Members and 1 Guest are viewing this topic.

Offline PsychoRebellious

  • Peasant
  • *
  • Posts: 130
  • Cookies: -6
    • View Profile
    • My Rantings
Just a teeny tiny problem with C++ multi threading, help?
« on: December 13, 2014, 12:13:59 pm »
These days I am studying c++'s allegro library 4.4.2 and trying to make a solar system type of thing where there's a god particle and then peasantparticles (The two classes are derived from the particle class). Long story short the peasant particles are supposed to be created(an infinite number of them) at random locations(x,y cordinates) and start moving in a random direction and IF they come in the gravitational field of Godparticle they start revolving around it.
All done except that when one peasant gets in gravitational field the program stops creating any more particles because
if(infield())  revolve_around();
so here's the loop of infinite revolutions the next particle will never be created so I gave mutlithreading a thought that I should put each particle's revolution in a different thread so they keep revolving and the program's execution still completes. I looked for the pthread library of c++. It's pretty simpe

pthread thread1; // create a thread
pthread_create(&thread1,NULL, dowhatever(),NULL);
the problem with it that dowhatever() function has to be a function with the following syntax

void* dothis(void*);

I don't find a solution to this since the function shouldnt be the function of a class so i cant simply pass particle1.revolvearound() to pthread_create

If i create a non-class function then how am I going to tell it which object's revolvearound function im talking about without passing the object as an argument ?


Offline madf0x

  • Knight
  • **
  • Posts: 172
  • Cookies: 50
    • View Profile
Re: Just a teeny tiny problem with C++ multi threading, help?
« Reply #1 on: December 13, 2014, 12:34:51 pm »
Posting some code might help.

C++ isn't my forte, but maybe you'll be lucky and Xires will pop in to dump wisdom all over you like warm maple syrup bath in the middle of a snowstorm.

Sounds to me though like you need a bit better state management. Instead of simply revolving each particle by itself infinitely, try recording some of the particle's state as a member or whatever of the object. Then as the program cycles each pass of your main loop(which I imagine you have for this kind of project), have a check for particles that are revolving and have the advance to the next state of revolution(im assuming you have more planned for revolutions other than simply whether or not its revolving a god particle, if not your code just got a whole lot simpler).

There may be a better way to do it, and almost certainly some optimization that can go into implementation of such code, but in essence thatd be what I would have first tried in your situation.

Offline PsychoRebellious

  • Peasant
  • *
  • Posts: 130
  • Cookies: -6
    • View Profile
    • My Rantings
Re: Just a teeny tiny problem with C++ multi threading, help?
« Reply #2 on: December 13, 2014, 01:06:59 pm »
header file
Code: [Select]

#include <allegro.h>
#include <string>
struct field{
//origin cordinates and extreme cordinates plus the radius
int x,y,radius,color;


};


class particle{
public:
int x;
int y;
int radius;
int color;
BITMAP*bmp;
//int mass;




int  getx(){return this->x;}
int  gety(){return this->y;}
int getradius(){return this->radius;}
particle(BITMAP*bmp,int x,int y,int radius, int color);
void draw(void);





};

class godparticle: public particle{
private:
int pull;

public:
field gfield;
//constructor
godparticle(BITMAP*bmp,int x,int y,int radius,int color):particle(bmp,x,y,radius,color){
this->gfield.x=x;
this->gfield.y=y;

this->gfield.radius=radius+50;
this->gfield.color=color+1;
}
// godparticle(){}
void draw();

};

class peasantparticle:public particle{
public:
//int formovedirection;
//godparticle formovegodparticle;
peasantparticle(BITMAP*bmp,int x, int y, int radius, int color):particle(bmp,x,y,radius,color){}//ends here constructor
//haha cant believe im actually commenting shit s
int check_surrounding(BITMAP* bmp,godparticle p,int x,int y);
int update_position(int x,int y);
int move(int direction,godparticle p);
void revolve_around(godparticle p);
//void revolve_call(BITMAP*bmp,int x,int y, int color);
void draw();
//for mutlithreading
void* threadfunction(void*){

}
//haha
};




functions.cpp

Code: [Select]

//okay for class particle now
#include <math.h>
#include "particles.h"



void revolve_call(BITMAP*bmp,int x,int y, int color){



putpixel(bmp,x,y,color);
rest(1);
putpixel(bmp,x,y,color);
//rest(5);
}



particle::particle(BITMAP*bmp,int ox,int oy,int radius,int color){
//this->mass=mass;
this->x=ox;
this->y=oy;
this->radius=radius;
this->bmp=bmp;
this->color=color;

}


void particle::draw(){
circlefill(this->bmp,this->x,this->y,this->radius,this->color);
}

//Oh god more whitespace, HI MOM

void peasantparticle::draw(){particle::draw();}
int peasantparticle::move(int direction,godparticle p){
//0 for left 1 for right
int halt=0;
if(direction){
while(x+radius!=SCREEN_W||halt!=1){
if(check_surrounding(bmp,p,x,y)==1)halt=1;
circlefill(bmp,x,y,radius,0);

x+=radius;
circlefill(bmp,x,y,radius,color);
rest(50);
if(x==SCREEN_W-radius)halt=1;
}//while ends
return 1;
}//direction right

else {
while(x-radius!=0){
check_surrounding(bmp,p,x,y);
circlefill(bmp,x,y,radius,0);

x-=radius;
circlefill(bmp,x,y,radius,color);
rest(50);
}

}
}


//revolve_around

void peasantparticle::revolve_around(godparticle p){
int x,y,radius;
x=p.x;y=p.y;radius=p.gfield.radius;
// do_circle(this->bmp,x,y,radius,this->color,revolve_call);
for(double angle=1;angle<=360;angle++){
int xcor,ycor;
xcor=x+( (radius)*cos(angle) );
ycor=y+( (radius)*sin(angle)  );
int r=this->radius;

circlefill(bmp,xcor,ycor,r,this->color);
rest(50);
circlefill(bmp,xcor,ycor,r,0);

}//set done

}
//another function goes here



//check_surrounding a stupid function

int peasantparticle::check_surrounding(BITMAP*bmp,godparticle p,int x,int y){
if(sqrt(   (float)    (p.x - this->x)*(p.x - this->x)   +  (p.y - this->y) *(p.y - this->y)     )<(p.gfield.radius+this->radius)){
circlefill(bmp,x,y,radius,0);
revolve_around(p);
return 1;
}//end if
else{return 0;}
}
//for god particle a more stupid function


void godparticle::draw(){
particle::draw();
circle(this->bmp,this->gfield.x,this->gfield.y,this->gfield.radius,this->gfield.color);
}

//a supid function




main.cpp

Code: [Select]
//c++ Allegro chasingstars

#include <pthread.h>
#include "particles.h"
#include <allegro.h>
#include <math.h>
#include <stdlib.h>
int main(){

//initialize stuff and set grahpics
allegro_init();
install_keyboard();
set_gfx_mode(GFX_AUTODETECT_WINDOWED,640,480,0,0);
install_timer();
srand(time(NULL));
//variables
pthread_t t1,t2,t3;
godparticle higgs(screen,200,300,50,1);
higgs.draw();

peasantparticle body1(screen,0,100,20,9);
body1.draw();
body1.move(1,higgs);
peasantparticle body2(screen,0,200,20,13);
body2.draw();
body2.move(1,higgs);
peasantparticle body3(screen,SCREEN_W-10,400,10,2);
body3.draw();
body3.move(0,higgs);



while(!key[KEY_ESC]);

return 0;
}


END_OF_MAIN()



Offline HTH

  • Official EZ Slut
  • Administrator
  • Knight
  • *
  • Posts: 395
  • Cookies: 158
  • EZ Titan
    • View Profile
Re: Just a teeny tiny problem with C++ multi threading, help?
« Reply #3 on: December 13, 2014, 02:06:08 pm »
You can't use a class' function because each and every object created has a hidden pointer. And pthread_create() has nooo idea what that pointer is. So you need to create a function like so, to pass the this pointer to the calling function (pthread).
Quote
class classname
{
public:
void *function1(void)
{
do something();
}
static void *function2(void* context)
{
return ((classname *)context)->function1();
}
};

That being said, I would HIGHLY advise against infinite threads, I would say instead spawn a static # of threads and when a particle enters the god particle's field, increment a var of some sort then start again, up to a given point. Infinity is just a dangerous thing to mess around with. It is much better in many cases to have a low thread count, and have each thread deal with a few more things.
« Last Edit: December 13, 2014, 04:49:43 pm by HTH »
<ande> HTH is love, HTH is life
<TurboBorland> hth is the only person on this server I can say would successfully spitefuck peoples women

Offline PsychoRebellious

  • Peasant
  • *
  • Posts: 130
  • Cookies: -6
    • View Profile
    • My Rantings
Re: Just a teeny tiny problem with C++ multi threading, help?
« Reply #4 on: December 13, 2014, 04:42:52 pm »
You can't use a class' function because each and every object created has a hidden pointer. And pthread_create() has nooo idea what that pointer is. So you need to create a function like so, to pass the this pointer to the calling function (pthread).
That being said, I would HIGHLY advise against infinite threads, I would say instead spawn a static # of threads and when a particle enters the god particle's field, increment a var of some sort then start again, up to a given point. Infinity is just a dangerous thing to mess around with. It is much better in many cases to have a low thread count, and have each thread deal with a few more things.


Code: [Select]
static void *function2(void* context)
{
return ((C *)context)->function1();
}
Ugh? The type conversion for?? I don't get this

and you are right that infinity is a terrible idea but I don't find any other way of having infinite revolutions without the infinite going thread. Or maybe I should just have the revolving particle eventually crash in the godparticle?  ;D

Offline HTH

  • Official EZ Slut
  • Administrator
  • Knight
  • *
  • Posts: 395
  • Cookies: 158
  • EZ Titan
    • View Profile
Re: Just a teeny tiny problem with C++ multi threading, help?
« Reply #5 on: December 13, 2014, 04:48:57 pm »
Thats my bad. It should have been (Classname *). Long night haha. I edited it for you, well i will right after this.

Does that make it clearer for you? If not let me know and I'll try and explain it better, but basically the use of context lets you pass thread what it expects, a pointer to a function. But in this case the function for that specific object. Not te generic one as you were attemptin to do. Just choose a large enough number of particles that it seems infinite and use the method i described in my previous post. It will serve you a lot better i promise.
« Last Edit: December 13, 2014, 04:51:27 pm by HTH »
<ande> HTH is love, HTH is life
<TurboBorland> hth is the only person on this server I can say would successfully spitefuck peoples women

Offline PsychoRebellious

  • Peasant
  • *
  • Posts: 130
  • Cookies: -6
    • View Profile
    • My Rantings
Re: Just a teeny tiny problem with C++ multi threading, help?
« Reply #6 on: December 14, 2014, 01:55:14 pm »
Thats my bad. It should have been (Classname *). Long night haha. I edited it for you, well i will right after this.

Does that make it clearer for you? If not let me know and I'll try and explain it better, but basically the use of context lets you pass thread what it expects, a pointer to a function. But in this case the function for that specific object. Not te generic one as you were attemptin to do. Just choose a large enough number of particles that it seems infinite and use the method i described in my previous post. It will serve you a lot better i promise.

Sorry, I was in a hurry. I am going to try this out and edit the previous code and let you know if that works

Offline PsychoRebellious

  • Peasant
  • *
  • Posts: 130
  • Cookies: -6
    • View Profile
    • My Rantings
Re: Just a teeny tiny problem with C++ multi threading, help?
« Reply #7 on: December 15, 2014, 01:23:59 pm »
Thank youuuu!!! I gave it a thought and indeed multithreading shouldn't be applied here! I just changed the main loop and pretty much all the program so that with every iteration the position is changed.
here' the code (of a different program that actually works)


basebat.h
Code: [Select]
#ifndef basebat
#define basbat
#include <allegro.h>
class basebat{
private:
BITMAP*bmp;

int color;
int x1,x2,y1,y2;
public:
//int getwidth(){return width;}
//int getheight(){return height;}

//constructor
basebat(BITMAP*bmp,int x1,int y1,int x2,int y2, int color);
//draw function

void draw(void);

void moveleft(void);
void moveright(void);
void movedown(void);
void moveup(void);
};




class raindrop{

public:

// private:
int x;
int y;
int radius;
int color;
BITMAP * bmp;

raindrop(BITMAP* bmp, int x, int y,int radius,int color);
void draw(void);
void fire();
void updateposition(int x,int y);

};




#endif;



functions.cpp
Code: [Select]

#include "basebat.h"
//#include "raindrop.h"
#include <allegro.h>

basebat::basebat(BITMAP*bmp,int x1,int y1,int x2,int y2,int color){
this->x1=x1;
this->y1=y1;
this->x2=x2;
this->y2=y2;
this->color=color;
this->bmp=bmp;


}


void basebat::draw(void){

rectfill(bmp,x1,y1,x2,y2,color);
}



void basebat::moveleft(void){
if(x1!=0){
rectfill(bmp,x1,y1,x2,y2,0);
x1 -=1;x2-=1;
rest(1);
rectfill(bmp,x1,y1,x2,y2,color);
}

}

void basebat::moveright(void){
if(x2!=640){
rectfill(bmp,x1,y1,x2,y2,0);
x1+=1;x2+=1;
//rest(1);
rectfill(bmp,x1,y1,x2,y2,color);
}
}

void basebat::moveup(void){
if(y1!=0){
rectfill(bmp,x1,y1,x2,y2,0);
y1-=1;y2-=1;
rectfill(bmp,x1,y1,x2,y2,color);
}
}

void basebat::movedown(void){
if(y2!=480){
rectfill(bmp,x1,y1,x2,y2,0);
y1+=1;y2+=1;
rectfill(bmp,x1,y1,x2,y2,color);
}
}

///////////////////////////////
//raindrop
raindrop::raindrop(BITMAP * bmp,int x,int y, int radius,int color){
this->x=x;
this->y=y;
this->radius=radius;
this->color=color;
this->bmp=bmp;


}

void raindrop::draw(void){
circlefill(bmp,x,y,radius,color);
}

void raindrop::updateposition(int x,int y){


circlefill(bmp,this->x,this->y,radius,0);
this->x=x,this->y=y;
circlefill(bmp,this->x,this->y,radius,color);

}



//void raindrop::fire(void){


//}

main.cpp
Code: [Select]
#include <allegro.h>
#include "basebat.h"
int main(){
allegro_init();
install_keyboard();
set_gfx_mode(GFX_AUTODETECT_WINDOWED,640,480,0,0);
int x=mouse_x;int y=mouse_y;
basebat bat(screen,(640/2)-50,450,(640/2)+30,480,5);
bat.draw();
int dropx=640/2;int dropy=200;
raindrop drop(screen,dropx,dropy,15,3);
drop.draw();
int drop2x=dropx-200;
int drop2y=dropy-150;
raindrop drop2(screen,dropx-200,dropy-60,14,4);
drop2.draw();
int d1dir=1;
int d2dir=1;
int score=0;
while(!key[KEY_ESC])
{
textprintf_ex(screen,font,0,0,6,0,"Total score %d",score);
if(key[KEY_RIGHT])bat.moveright();
if(key[KEY_LEFT])bat.moveleft();
if(key[KEY_DOWN])bat.movedown();
if(key[KEY_UP])bat.moveup();


//if it has reached rock bottom direction becomes zero
if(getpixel(screen,drop.x,drop.y+drop.radius+1)!=0)d1dir=0;
if(getpixel(screen,drop2.x,drop2.y+drop2.radius+1)!=0)d2dir=0;
//now check if the drops have reached the screen height on top direction
if(drop.y+drop.radius<=0){d1dir=1;score+=1;};
if(drop2.y+drop2.radius<=0){d2dir=1;score+=1;};
if(d1dir==1){
dropy+=1;
drop.updateposition(dropx,dropy);
}
if(d2dir==1){
drop2y+=1;
drop2.updateposition(drop2x,drop2y);

}


//if direction becomes zero travel top
if(d1dir==0){
dropy-=1;
drop.updateposition(dropx,dropy);
}
if(d2dir==0){
drop2y-=1;
drop2.updateposition(drop2x,drop2y);

}

}

while(!key[KEY_ESC]);
allegro_exit();
return 0;

}
END_OF_MAIN()

Offline PsychoRebellious

  • Peasant
  • *
  • Posts: 130
  • Cookies: -6
    • View Profile
    • My Rantings
Re: Just a teeny tiny problem with C++ multi threading, help?
« Reply #8 on: December 15, 2014, 01:35:19 pm »
and by the way that multi threading still didn't go well! Since the pthread is a C library it's not made for passing class instantiations anyway, right? So instead of messing things up I should look for some multithreading library thats for C++ and not C. Does that ring a bell?

Offline Xires

  • Noob Eater
  • Administrator
  • Knight
  • *
  • Posts: 379
  • Cookies: 149
    • View Profile
    • Feed The Trolls - Xires
Re: Just a teeny tiny problem with C++ multi threading, help?
« Reply #9 on: December 16, 2014, 01:03:06 am »
I hate to say it, but you might have an easier time with boost.  Learning how to properly use pthreads with C++ is still a good idea, though.  There are several articles on how to use pthreads with C++ so it shouldn't be difficult to google.  Still, boost may resolve some of your issues.
-Xires