Is using a const method from one object thread safe? - c++

I am not sure if this is a duplicate, I have looked through many posts but they do not seem to be close enough to my question.
I want to use a const method from one object to change other objects concurrently. The program basically needs me to move a particle under the influence of gravity and I want to run this in parallel for all particles. I made a physics class and in that class I have a const method to move a particle object.
Here are some example classes to understand me better.
/**
* Particle.h
*/
#ifndef __Particle__sim__
#define __Particle__sim__
class Particle {
private:
double height;
double velocity;
public:
const double getHeight() const;
const double getVelocity() const;
void setHeight(const double&);
void setVelocity(const double&);
};
#endif
/**
* Physics.h
*/
#ifndef __physics__sim__
#define __physics__sim__
#include <thread>
#include <vector>
#include "Particle.h"
class Physics {
private:
double gravity;
double timeStep;
void moveParticle(Particle&, const double) const;
public:
Physics(const double g, const double t);
void moveParticles(std::vector<Particle>&, const double) const;
};
#endif
/**
* Physics.cpp
*/
#include "Physics.h"
using namespace std;
Physics::Physics(const double g, const double t) : gravity(g), timeStep(t) {}
void Physics::moveParticle(Particle& particle, const double time) const {
// move particle under gravity
}
void Physics::moveParticles(vector<Particles>& particles, const double time) const {
vector<thread> threads;
threads.reserve(particles.size());
for (auto& p : particles) {
threads.push_back(thread(Physics::moveParticle&, this, std::ref(p), time));
}
for (auto& t : threads) {
t.join();
}
}
Here is essentially my main
/**
* main.cpp
*/
#include <vector>
#include "Physics.h"
#include "Particle.h"
using namespace std;
int main() {
vector<Particle> particles;
// insert 100,000 particles
Physics physics = Physics(-9.81, 0.01);
physics.moveParticles(particles, 5.0);
return 0;
}
So is physics.moveParticle(Particle&, const double) thread safe here?
Short & Sweet:
I want to use a method from one Physics object to make multiple threads to move all the Particles in my program and I am not sure if the const method I wrote is thread safe. I can't see why not but I can't justify it.

At first sight, this should be thread safe.
We need to see the implementation of Particle::setHeight to be absolutely sure. What if it did something like write to a global array? Which would be silly but we can't tell for sure.
However, your Particle looks very simple. What would be even more thread safe is to not mutate it at all. Make them immutable and create a new one with each calculation.
You can still change them by assigning the new Particle back to the old Particle.
However if you really want to get into threading, a great technique here is to have two world states: previous and next. These swap with each update step. Each update step reads from previous and writes into next. This lets other threads like graphics display read from previous without constantly locking on little things like Particles.
With that, a immutable Particle does not slow anything down at all. In fact, the compiler will rewrite the machine code for nextParticles[i] = updateParticle(prevParticles[i]) into direct assignments to its final position in memory. That's RVO or NRVO.

It looks thread-safe to me. In particular, if the only (non-immutable) data read or written by each of the spawned threads is the thread's own corresponding Particle object, then there is no shared data as far as the threads are concerned. (The Physics object itself is shared, of course, but since you are not modifying the Physics object during the sub-threads' lifetime, the Physics object is effectively immutable/read-only during the operation, and any read-only access to the Physics object by the spawned threads will not be a source of race conditions)

Related

Can you use different constants for class objects in C++?

I came across a class which sole purpose was to create blinking leds. He used the class for 2 objects which had a different blinking interval. I started thinking in how I could use constants but nothing came to me.
Is it possible to use a const int in combination with the constructor to use different constants for objects?
I am aware that a const int is to be initialized at the same place where it is declared, so I'd guess that the answer is 'no'
If not, are there workarounds to achieve the same thing? That is using different constants (so less memory usage) for different objects of the same type.
The used platform in question is the arduino IDE and an atmega328P.
May it perhaps be that the compiler recognizes that the variables are actually used as constants and treat them as such?
.h
class BlinkingLed
{
private:
int blPin;
short blinkInterval; // <-- the contant
bool blinking;
bool ledOn;
long lastTime;
public:
BlinkingLed(int, int);
void setBlinkInterval(int); // never used, should not exist
int getBlinkInterval(); // never used, should not exist
void setLedOn(bool);
bool getLedOn();
void attachPin();
void heartBeat();
};
.cpp
BlinkingLed::BlinkingLed(int aPin, int aBlinkInterval) // constructor
{
blPin = aPin;
blinking = false;
ledOn = false;
blinkInterval = aBlinkInterval; // <-- the contant
}
The objects are made with this line. The aki class needs 2 BlinkingLed objects.
AKI aki(new BlinkingLed(23,333), new BlinkingLed(22,667), 24); // Red blinks 90/minute, green 45/minute
This is the constructor of aki:
AKI::AKI(BlinkingLed *aRedLight, BlinkingLed *aGreenLight, int aBellPin)
{
redLight = aRedLight;
greenLight = aGreenLight;
bellPin = aBellPin;
}
The 333 and 367 are stored in variables and I want these to become constants to preserve memory space. How do I do that?
To summarize the discussion, and correct some of your wrong assumptions:
class BlinkingLed {
private:
const byte blPin; // This should definitely be const
const unsigned short blinkInterval; // <-- the desired constant (why?)
bool blinking;
bool ledOn;
unsigned long lastTime;
public:
BlinkingLed(byte pin, unsigned short interval)
: blPin(pin), blinkInterval(interval) {}
// void setBlinkInterval(int); // impossible for a const Interval
void init() {pinMode(blPin, OUTPUT);} // should not be done in a c'tor
void run(); // to be called as often as possible for a smooth heartbeat
unsigned short getBlinkInterval() {return blinkInterval;} // why not
void setLed(bool); // stops blinking
bool isLedOn();
void heartBeat(); // start blinking
};
BTW: data type int usually blames you for not thinking about it. :)

Why this code extremely slow?Any thing related to cache behavior?

I started to some data-oriented design experiment. I initially start doing some oop code and found some code is extremely slow, don't know why. Here is one example:
I have a game object
class GameObject
{
public:
float m_Pos[2];
float m_Vel[2];
float m_Foo;
void UpdateFoo(float f){
float mag = sqrtf(m_Vel[0] * m_Vel[0] + m_Vel[1] * m_Vel[1]);
m_Foo += mag * f;
}
};
then I create 1,000,000 of objects using new, and then loop over calling UpdateFoo()
for (unsigned i=0; i<OBJECT_NUM; ++i)
{
v_objects[i]->UpdateFoo(10.0);
}
it takes about 20ms to finish the loop. And strange things happened when I comment out float m_Pos[2], so the object looks like this
class GameObject
{
public:
//float m_Pos[2];
float m_Vel[2];
float m_Foo;
void UpdateFoo(float f){
float mag = sqrtf(m_Vel[0] * m_Vel[0] + m_Vel[1] * m_Vel[1]);
m_Foo += mag * f;
}
};
and suddenly the loop takes about 150ms to finish. And if I put anything before m_Vel, much faster. I try to put some padding between m_Vel and m_Foo or other places except the place before m_Vel....slow.
I tested on vs2008 and vs2010 in release build, i7-4790
Any idea how this difference could happen? Is it related to any cache coherent behavior.
here is whole sample:
#include <iostream>
#include <math.h>
#include <vector>
#include <Windows.h>
using namespace std;
class GameObject
{
public:
//float m_Pos[2];
float m_Velocity[2];
float m_Foo;
void UpdateFoo(float f)
{
float mag = sqrtf(m_Velocity[0] * m_Velocity[0] + m_Velocity[1] *
m_Velocity[1]);
m_Foo += mag * f;
}
};
#define OBJECT_NUM 1000000
int main(int argc, char **argv)
{
vector<GameObject*> v_objects;
for (unsigned i=0; i<OBJECT_NUM; ++i)
{
GameObject * pObject = new GameObject;
v_objects.push_back(pObject);
}
LARGE_INTEGER nFreq;
LARGE_INTEGER nBeginTime;
LARGE_INTEGER nEndTime;
QueryPerformanceFrequency(&nFreq);
QueryPerformanceCounter(&nBeginTime);
for (unsigned i=0; i<OBJECT_NUM; ++i)
{
v_objects[i]->UpdateFoo(10.0);
}
QueryPerformanceCounter(&nEndTime);
double dWasteTime = (double)(nEndTime.QuadPart-
nBeginTime.QuadPart)/(double)nFreq.QuadPart*1000;
printf("finished: %f", dWasteTime);
// for (unsigned i=0; i<OBJECT_NUM; ++i)
// {
// delete(v_objects[i]);
// }
}
then I create 1,000,000 of objects using new, and then loop over
calling UpdateFoo()
There's your problem right there. Don't allocate a million teeny things individually that are going to be processed repeatedly using a general-purpose allocator.
Try storing the objects contiguously or in contiguous chunks. An easy solution is store them all in one big std::vector. To remove in constant time, you can swap the element to remove with the last and pop back. If you need stable indices, you can leave a hole behind to be reclaimed on insertion (can use a free list or stack approach). If you need stable pointers that don't invalidate, deque might be an option combined with the "holes" idea using a free list or separate stack of indices to reclaim/overwrite.
You can also just use a free list allocator and use placement new against it while careful to free using the same allocator and manually invoke the dtor, but that gets messier faster and requires more practice to do well than the data structure approach. I recommend instead to just seek to store your game objects in some big container so that you get back the control over where everything is going to reside in memory and the spatial locality that results.
I tested on vs2008 and vs2010 in release build, i7-4790 Any idea how
this difference could happen? Is it related to any cache coherent
behavior.
If you are benchmarking and building the project properly, maybe the allocator is fragmenting the memory more when GameObject is smaller where you are incurring more cache misses as a result. That would seem to be the most likely explanation, but difficult to know for sure without a good profiler.
That said, instead of analyzing it further, I recommend the above solution so that you don't have to worry about where the allocator is allocating every teeny thing in memory.

C++ Vector read access violation Mylast returned 0x8

I really need help on this one cause I am extremely stuck and have no idea what to do.
Edit:
A lot of you guys are saying that I need to use the debugger but let me be clear I have not used C++ for an extremely long time and I've used visual studio for a grand total of 2 weeks so I do not know all the cool stuff it can do with the debugger.
I am a student at university at the beginning of my second year who is trying to work out how to do something mostly by failing.
I AM NOT a professional coder and I don't have all the knowledge that you people have when it comes to these issues and that is why I am asking this question. I am trying my best to show my issue so yes my code contains a lot of errors as I only have a very basic understanding of a lot of C++ principles so can you please keep that in mind when commenting
I'm only posting this here because I can don't know who else to ask right now.
I have a function called world that is suppose to call my render class to draw all the objects inside of its vector to the screen.
#include "C_World.h"
C_World::C_World()
{
// creates an instance of the renderer class to render any drawable objects
C_Renderer *render = new C_Renderer;
}
C_World::~C_World()
{
delete[] render;
}
// adds an object to the world vector
void C_World::addToWorld(C_renderable* a)
{
world_list.push_back(a);
}
void C_World::World_Update()
{
render->ClearScreen();
World_Render();
}
void C_World::World_Render() {
for (int i = 0; i < 1; i++)
{
//render->DrawSprite(world_list[i]->getTexture(), world_list[i]->get_X, world_list[i]->get_Y());
render->DrawSprite(1, 1, 1);
}
}
While testing I commented out the Sprites get functions in order to check if they were causing the issue.
the renderer sprites are added to the vector list in the constructor through the create sprite function
C_Renderer::C_Renderer()
{
// test sprite: Id = 1
CreateSprite("WhiteBlock.png", 250, 250, 1);
}
I thought this might of been the issue so I had it in other functions but this didn't solve anything
Here are the Draw and create Sprite functions
// Creates a sprite that is stored in the SpriteList
// Sprites in the spriteList can be used in the drawSprite function
void C_Renderer::CreateSprite(std::string texture_name,
unsigned int Texture_Width, unsigned int Texture_height, int spriteId)
{
C_Sprite *a = new C_Sprite(texture_name,Texture_Width,
Texture_height,spriteId);
SpriteList.push_back(a);
size_t b = SpriteList.size();
HAPI.DebugText(std::to_string(b));
}
// Draws a sprite to the X and Y co-ordinates
void C_Renderer::DrawSprite(int id,int x,int y)
{
Blit(screen, _screenWidth, SpriteList[id]->get_Texture(),
SpriteList[id]->getTexture_W(), SpriteList[id]->getTexture_H(), x, y);
}
I even added some test code into the create sprite function to check to see if the sprite was being added too the vector list. It returns 1 so I assume it is.
Exception thrown: read access violation.
std::_Vector_alloc<std::_Vec_base_types<C_Sprite *,
std::allocator<C_Sprite *> > >::_Mylast(...) returned 0x8.
that is the full error that I get from the compiler
I'm really really stuck if there is anymore information you need just say and ill post it straight away
Edit 2:
#pragma once
#include <HAPI_lib.h>
#include <vector>
#include <iostream>
#include "C_renderable.h"
#include "C_Renderer.h"
class C_World
{
public:
C_World();
~C_World();
C_Renderer *render = nullptr;
void World_Update();
void addToWorld(C_renderable* a);
private:
std::vector<C_renderable*> world_list;
void C_World::World_Render();
};
#pragma once
#include <HAPI_lib.h>
#include "C_renderable.h"
#include "C_Sprite.h"
#include <vector>
class C_Renderer
{
public:
C_Renderer();
~C_Renderer();
// gets a pointer to the top left of screen
BYTE *screen = HAPI.GetScreenPointer();
void Blit(BYTE *destination, unsigned int destWidth,
BYTE *source, unsigned int sourceWidth, unsigned int sourceHeight,
int posX, int posY);
void C_Renderer::BlitBackground(BYTE *destination,
unsigned int destWidth, unsigned int destHeight, BYTE *source,
unsigned int sourceWidth, unsigned int sourceHeight);
void SetPixel(unsigned int x,
unsigned int y, HAPI_TColour col,BYTE *screen, unsigned int width);
unsigned int _screenWidth = 1750;
void CreateSprite(std::string texture_name,
unsigned int Texture_Width,unsigned int Texture_height, int spriteId);
void DrawSprite(int id, int x, int y);
void ClearScreen();
private:
std::vector<C_Sprite*> SpriteList;
};
I don't say this lightly, but the code you've shown is absolutely terrible. You need to stop and go back several levels in your understanding of C++.
In all likeliness, your crash is the result of a simple "shadowing" issue in one or more of your functions:
C_World::C_World()
{
// creates an instance of the renderer class to render any drawable objects
C_Renderer *render = new C_Renderer;
}
C_World::~C_World()
{
delete[] render;
}
There are multiple things wrong here, and you don't show the definition of C_World but if this code compiles we can deduce that it has a member render, and you have fallen into a common trap.
C_Renderer *render = new C_Renderer;
Because this line starts with a type this is a definition of a new, local variable, render. Your compiler should be warning you that this shadows the class-scope variable of the same name.
What these lines of code
C_World::C_World()
{
// creates an instance of the renderer class to render any drawable objects
C_Renderer *render = new C_Renderer;
}
do is:
. assign an undefined value to `this->render`,
. create a *local* variable `render`,
. construct a dynamic `C_Renderer` presumably on the heap,
. assign that to the *local* variable `render`,
. exit the function discarding the value of `render`.
So at this point the memory is no-longer being tracked, it has been leaked, and this->render is pointing to an undefined value.
You repeat this problem in several of your functions, assigning new results to local variables and doing nothing with them. It may not be this specific instance of the issue that's causing the problem.
Your next problem is a mismatch of new/delete vs new[]/delete[]:
C_World::~C_World()
{
delete[] render;
}
this would result in undefined behavior: this->render is undefined, and delete[] on a non-new[] allocation is undefined.
Most programmers use a naming convention that distinguishes a member variable from a local variable. Two common practices are an m_ prefix or an _ suffix for members, e.g.
class C_World
{
public:
C_Foo* m_foo; // option a
C_Renderer* render_; // option b
// ...
}
Perhaps you should consider using modern C++'s concept of smart pointers:
#include <memory>
class C_World {
// ...
std::unique_ptr<C_Renderer> render_;
// ...
};
C_World::C_World()
: render_(new C_Renderer) // initializer list
{}
But it's unclear why you are using a dynamic allocation here in the first place. It seems like an instance member would be better:
class C_World {
C_Renderer render_;
};
C_World::C_World() : render_() {}

C++ Member variable losing value after constructor

I'm having a problem in one of my classes. I have these 2 classes, GameApp and Simulation:
GameApp.h
#pragma once
#include "Simulation.h"
class Simulation;
class GameApp {
static GameApp *instance;
public:
~GameApp(void);
static GameApp *initializeContext(const char *gameTitle, const int windowWidth, const int windowHeight);
//void setSimulation(Simulation &simulation) { *(this->simulation) = simulation; }
Simulation *getSimulation() { return simulation; }
static const int TARGET_FPS = 50; // Frames per second
private:
GameApp(void);
Simulation *simulation;
double frameIntervalList[TARGET_FPS]; // A list containing the time to render the last 60 frames
// Other stuff that doesn't matter
Simulation.h
#pragma once
#include <vector>
#include "GameApp.h"
class Simulation {
public:
Simulation(void);
Simulation(const Simulation &copy);
~Simulation(void);
Simulation &operator=(const Simulation &other);
protected:
std::vector<Entity*> *entities;
And, in GameApp.cpp, in the function initializeContext, I have:
#include "GameApp.h"
GameApp *GameApp::instance = NULL;
GameApp::GameApp() {
gamePaused = false;
frameIntervalSum = 0;
this->simulation = new Simulation();
for (int i = 0; i < 60; i++) {
frameIntervalList[i] = 0;
}
}
GameApp *GameApp::initializeContext(const char *gameTitle, const int windowWidth, const int windowHeight) {
instance = new GameApp();
// (...) Rest of initialize funcion
}
The problem is, for some misterious reason, when I call initializeContext, the first line of it calls GameApp's constructor, which creates a new Simulation, which allocates correctly and I get a memory address for the simulation pointer. But when the program exits the constructor of GameApp, in the line right after instance = new GameApp();, if I check the simulator variable on the newly created instance using the debugger, I get the pointer value of 0x00000000, and the Simulation that I just created is gone. This would indeed happen if I was using the stack memory on the constructor, but I'm clearly using new, creating the new Simulation variable in the correct way, I guess. What may be happening here?
Also, there's a commented setSimulation function on the GameApp.h file. When I leave this uncommented, I get the compiler error 2582, "operator= function is unavailable in Simulation". Can this be related to my problem?
EDIT: The problem was indeed the for loop with the hardcoded size. I changed the size of frameIntervalList from 60 to 50 in the header but forgot to change it on the loop. Also updated code to show the declaration of frameIntervalList.
The only code that executes between the initialization of the simulation member variable and the code that comes after the GameApp ctor is the for loop that initialzes frameIntervalList so its initialization with a hardcoded size might overwrite the value of simulation variable if you are unlucky. (Or lucky because it helps you to catch a very ugly bug early!!! :-)

class members and functions c++

I'm learning c++. I have written a small program which should compute the energy
of a N particle system. Up to now I have three small files:
data.h:
class Particle {
public:
double mass;
double charge;
double posx,posy,posz;
};
Particle part[2];
main.cpp:
#include <iostream>
#include "data.h"
using namespace std;
double energy(Particle part );
int main ()
{
double sd;
part[0].mass = 10.0;
part[4].mass = 90.0;
cout << part[0].mass << "\n";
cout << part[4].mass << "\n";
sd = energy(part);
cout << "sd" << sd << "\n" ;
return 0;
}
energy.cpp:
#include <iostream>
using namespace std;
double energy(Particle part)
{
cout << part[0].mass << "\n";
double dummy;
dummy = 2.0;
return (dummy);
}
I have two questions:
1)I want to make visible the Class particle in the function "energy". In other words,
I want to use the variables of the class function (with the values given in "main")
in the energy function.
I have tried as you see energy(Particle part) but it seems Particle is not defined
in that scope.
2)As you see in "data.h" I declared "part" as an array with two members. However,
in "main" I can use more than two members, for instance part[3],part[4]... Why I
could use more members than those I declared?
I am compiling with g++ -o test energy.cpp main.cpp
thanks.
1)I want to make visible the Class particle in the function "energy". In other words, I want to use the variables of the class function (with the values given in "main") in the energy function. I have tried as you see energy(Particle part) but it seems Particle is not defined in that scope.
If I understand you right.. You want to have
Particle part[2];
to be use able in main.cpp and in energy.cpp ?
If yes.. change this to:
extern Particle part[2];
and in energy.cpp add this:
#include "data.h"
Particle part[2];
and you will be able to use
double energy()
{
//main.cpp will have same part
cout << part[0].mass << "\n";
double dummy;
dummy = 2.0;
return (dummy);
}
2)As you see in "data.h" I declared "part" as an array with two members. However, in "main" I can use more than two members, for instance part[3],part[4]... Why I could use more members than those I declared?
Because it's C/C++ ? no range checks. You can do what ever you want.
But if you do, the result will be unexpected.
1)I want to make visible the Class particle in the function "energy".
You should #include "data.h" in the file energy.cpp.
2)As you see in "data.h" I declared "part" as an array with two members.
You probably shouldn't have done that, for two reasons:
You will learn later to avoid declaring global objects. It is legal (and often correct) to do so, but until you learn, you probably want to declare it as a local variable in main.
You should not declare global objects in header files, since they will then be declared in every translation unit that includes the header file.
However, in "main" I can use more than two members, for instance part[3],part[4]... Why I could use more members than those I declared?
By indexing beyond the end of the array, you have invoked "undefined behavior". The system is free to do almost anything (for example, crash, send Bill Gates an email, start a global thermo-nuclear war, &c). Among the infinite variety of things included in "undefined behavior" is the most confusing one of all -- appear to work. That is what happened in your case. You should not count on it continuing to appear to work.
All sorts of things you can do with a class ...
struct Vector3
{
double m_x, m_y, m_z;
};
class Particle
{
public:
double ComputeEnergy() { // return answer }
double GetMass() const { return m_mass; }
double GetCharge() const { return m_charge; }
const Vector3& GetPos() const { return m_pos; }
void SetMass(double mass) { m_mass = mass; }
void SetCharge(double charge) { m_charge = charge; }
void SetPos(const Vector3& pos) { m_pos = pos; }
void SetPos(double x, double y, double z)
{
m_pos.m_x = x;
m_pos.m_y = y;
m_pos.m_z = z;
}
private:
double m_mass;
double m_charge;
Vector3 m_pos;
};
You need to #include "data.h" in energy.cpp. Includes are only processed on a per-file basis, so energy.cpp can't see the header without that.
EDIT: In your function, the parameter part, out-scopes the global definition of part, so the part in your function is not an array. You want:
cout << part.mass << "\n";
1>Include "data.h" in energy.cpp
2> C++ array is very primitive it doesn't has any bound checking so you were able to access part[4].But there is no guarantee that it will work every time.Most of the time program may crash during run-time complaining the memory is corrupt.
To answer the first question, you could simply include data.h in energy.cpp.
#include "data.h"
Unfortunately, you've created "part" in the global space and so each .cpp file will independently create it. When it goes to link the object files, it will see that multiple references to "part" exist. What you can do here is use the "extern" keyword and in data.h, you would simply declare it as an external variable. Or, because you only reference "part" in main.cpp, you could just move the global definition in there and the problem is solved.
Now, when it comes to what you have done in energy.cpp, you've create a separate variable also called "part". When scoping rules are applied, it means that the compiler is going to take the local definition over the global definition. Since you are passing a class object and not a class array, you'll get a compiler error when referencing it like "part[0].mass".
Instead, why are you concerned about the value of the other particle and not the particle you passed in? If you want the mass of a particular Particle object, then you should write it like "part.mass"
Of course, I would argue that what you really want to create is a member function for energy within Particle. Right now, you are currently using classes in a C style struct way. This means that you are missing the ability to use all the object oriented goodness that C++ has to offer. You could do it like this
class Particle
{
protected:
double mass;
double charge;
double posx,posy,posz;
public:
void SetMass(double newMass) { mass = newMass; }
void SetCharge(double newCharge) { charge = newCharge; }
void SetX(double newX) { posX = newX; }
void SetY(double newY) { posY = newY; }
void SetZ(double newZ) { posZ = newZ; }
double GetEnergy() { return 2.0; }
};
To answer your second question, C++ assumes you know more about the memory then it does. There is no bounds checking in GCC(AFAIK) because the memory could be allocated anywhere at any time and deallocated as well. However, unlike other languages, you have to manage the memory yourself. There's a lot of optimizations and C++ trickery that this enables(like declaring a zero sized array for unknown sizes and assigning a block of memory to it).
Cheers!