Note: This is a complete re-wording of a question I posted a while ago. If you find they are duplicate, please close the other one.
My problem is quite general but it seems that it could be explained more easily based on a concrete simple example.
So imagine I want to simulate the electricity consumption in an office throught time. Let's assume that there is only a light and heating.
class Simulation {
public:
Simulation(Time const& t, double lightMaxPower, double heatingMaxPower)
: time(t)
, light(&time,lightMaxPower)
, heating(&time,heatingMaxPower) {}
private:
Time time; // Note : stack-allocated
Light light;
Heating heating;
};
class Light {
public:
Light(Time const* time, double lightMaxPower)
: timePtr(time)
, lightMaxPower(lightMaxPower) {}
bool isOn() const {
if (timePtr->isNight()) {
return true;
} else {
return false;
}
}
double power() const {
if (isOn()) {
return lightMaxPower;
} else {
return 0.;
}
private:
Time const* timePtr; // Note : non-owning pointer
double lightMaxPower;
};
// Same kind of stuff for Heating
The important points are:
1.Time cannot be moved to be a data member Light or Heating since its change does not come from any of these classes.
2.Time does not have to be explicitly passed as a parameter to Light. Indeed, there could be a reference to Light in any part of the program that does not want to provide Time as a parameter.
class SimulationBuilder {
public:
Simulation build() {
Time time("2015/01/01-12:34:56");
double lightMaxPower = 42.;
double heatingMaxPower = 43.;
return Simulation(time,lightMaxPower,heatingMaxPower);
}
};
int main() {
SimulationBuilder builder;
auto simulation = builder.build();
WeaklyRelatedPartOfTheProgram lightConsumptionReport;
lightConsumptionReport.editReport((simulation.getLight())); // No need to supply Time information
return 0;
}
Now, Simulation is perfectly find as long as it is not copy/move constructed. Because if it is, Light will also get copy/move constructed and by default, the pointer to Time will be pointing to the Time in the old Simulation instance which is copied/moved from.
However, Simulation actually is copy/move constructed in between the return statement in SimulationBuilder::build() and the object creation in main()
Now there are a number of ways to solve the problem:
1: Rely on copy elision. In this case (and in my real code) copy elision seems to be allowed by the standard. But not required, and as a matter of fact, it is not elided by clang -O3. To be more precise, clang elides Simulation copy, but does call the move ctor for Light. Also notice that relying on an implementation-dependent time is not robust.
2: Define a move-ctor in Simulation:
Simulation::Simulation(Simulation&& old)
: time(old.time)
, light(old.light)
, heating(old.heating)
{
light.resetTimePtr(&time);
heating.resetTimePtr(&time);
}
Light::resetTimePtr(Time const* t) {
timePtr = t;
}
This does work but the big problem here is that it weakens encapsulation: now Simulation has to know that Light needs more info during a move. In this simplified example, this is not too bad, but imagine timePtr is not directly in Light but in one of its sub-sub-sub-member. Then I would have to write
Simulation::Simulation(Simulation&& old)
: time(old.time)
, subStruct(old.subStruct)
{
subStruct.getSubMember().getSubMember().getSubMember().resetTimePtr(&time);
}
which completly breaks encapsulation and the law of Demeter. Even when delegating functions I find it horrible.
3: Use some kind of observer pattern where Time is being observed by Light and sends a message when it is copy/move constructed so that Light change its pointer when receiving the message.
I must confess I am lazy to write a complete example of it but I think it will be so heavy I am not sure the added complexity worth it.
4: Use a owning pointer in Simulation:
class Simulation {
private:
std::unique_ptr<Time> const time; // Note : heap-allocated
};
Now when Simulation is moved, the Time memory is not, so the pointer in Light is not invalidated. Actually this is what almost every other object-oriented language does since all objects are created on the heap.
For now, I favor this solution, but still think it is not perfect: heap-allocation could by slow, but more importantly it simply does not seems idiomatic. I've heard B. Stroustrup say that you should not use a pointer when not needed and needed meant more or less polymorphic.
5: Construct Simulation in-place, without it being return by SimulationBuilder (Then copy/move ctor/assignment in Simulation can then all be deleted). For instance
class Simulation {
public:
Simulation(SimulationBuilder const& builder) {
builder.build(*this);
}
private:
Time time; // Note : stack-allocated
Light light;
Heating heating;
...
};
class SimulationBuilder {
public:
void build(Simulation& simulation) {
simulation.time("2015/01/01-12:34:56");
simulation.lightMaxPower = 42.;
simulation.heatingMaxPower = 43.;
}
};
Now my questions are the following:
1: What solution would you use? Do you think of another one?
2: Do you think there is something wrong in the original design? What would you do to fix it?
3: Did you ever came across this kind of pattern? I find it rather common throughout my code. Generally though, this is not a problem since Time is indeed polymorphic and hence heap-allocated.
4: Coming back to the root of the problem, which is "There is no need to move, I only want an unmovable object to be created in-place, but the compiler won't allow me to do so" why is there no simple solution in C++ and is there a solution in another language ?
If all classes need access to the same const (and therefore immutable) feature, you have (at least) 2 options to make the code clean and maintainable:
store copies of the SharedFeature rather than references - this is reasonable if SharedFeature is both small and stateless.
store a std::shared_ptr<const SharedFeature> rather than a reference to const - this works in all cases, with almost no additional expense. std::shared_ptr is of course fully move-aware.
EDIT: Due to the class naming and ordering I completely missed the fact that your two classes are unrelated.
It's really hard to help you with such an abstract concept as "feature" but I'm going to completely change my thought here. I would suggest moving the feature's ownership into MySubStruct. Now copying and moving will work fine because only MySubStruct knows about it and is able to make the correct copy. Now MyClass needs to be able to operate on feature. So, where needed just add delegation to MySubStruct: subStruct.do_something_with_feature(params);.
If your feature needs data members from both sub struct AND MyClass then I think you split responsibilities incorrectly and need to reconsider all the way back to the split of MyClass and MySubStruct.
Original answer based on the assumption that MySubStruct was a child of MyClass:
I believe the correct answer is to remove featurePtr from the child and provide a proper protected interface to feature in the parent (note: I really do mean an abstract interface here, not just a get_feature() function). Then the parent doesn't have to know about children and the child can operator on the feature as needed.
To be completely clear: MySubStruct will not know that the parent class even HAS a member called feature. For example, perhaps something like this:
1: What solution would you use? Do you think of another one?
Why not apply a few design patterns? I see uses for a factory and a singleton in your solution. There are probably a few others that we could claim work but I am way more experienced with applying a Factory during a simulation than anything else.
Simulation turns into a Singleton.
The build() function in SimulationBuilder gets moved into Simulation. The constructor for Simulation gets privatized, and your main call becomes Simulation * builder = Simulation::build();. Simulation also gets a new variable static Simulation * _Instance;, and we make a few changes to Simulation::build()
class Simulation
{
public:
static Simulation * build()
{
// Note: If you don't need a singleton, just create and return a pointer here.
if(_Instance == nullptr)
{
Time time("2015/01/01-12:34:56");
double lightMaxPower = 42.;
double heatingMaxPower = 43.;
_Instance = new Simulation(time, lightMaxPower, heatingMaxPower);
}
return _Instance;
}
private:
static Simulation * _Instance;
}
Simulation * Simulation::_Instance = nullptr;
Light and Heating objects get provided as a Factory.
This thought is worthless if you are only going to have 2 objects inside of simulation. But, if you are going to be managing 1...N objects and multiple types, then I would strongly encourage you utilize a factory, and a dynamic list (vector, deque, etc.). You would need to make Light and Heating inherit from a common template, set things up to register those classes with the factory, set the factory so that it is templated and an instance of the factory can only create objects of a specific template, and initialize the factory for the Simulation object. Basically the factory would look something like this
template<class T>
class Factory
{
// I made this a singleton so you don't have to worry about
// which instance of the factory creates which product.
static std::shared_ptr<Factory<T>> _Instance;
// This map just needs a key, and a pointer to a constructor function.
std::map<std::string, std::function< T * (void)>> m_Objects;
public:
~Factory() {}
static std::shared_ptr<Factory<T>> CreateFactory()
{
// Hey create a singleton factory here. Good Luck.
return _Instance;
}
// This will register a predefined function definition.
template<typename P>
void Register(std::string name)
{
m_Objects[name] = [](void) -> P * return new P(); };
}
// This could be tweaked to register an unknown function definition,
void Register(std::string name, std::function<T * (void)> constructor)
{
m_Objects[name] = constructor;
}
std::shared_ptr<T> GetProduct(std::string name)
{
auto it = m_Objects.find(name);
if(it != m_Objects.end())
{
return std::shared_ptr<T>(it->second());
}
return nullptr;
}
}
// We need to instantiate the singleton instance for this type.
template<class T>
std::shared_ptr<Factory<T>> Factory<T>::_Instance = nullptr;
That may seem a bit weird, but it really makes creating templated objects fun. You can register them by doing this:
// To load a product we would call it like this:
pFactory.get()->Register<Light>("Light");
pFactory.get()->Register<Heating>("Heating");
And then when you need to actually get an object all you need is:
std::shared_ptr<Light> light = pFactory.get()->GetProduct("Light");
2: Do you think there is something wrong in the original design? What would you do to fix it?
Yeah I certainly do, but unfortunately I don't have much to expound upon from my answer to item 1.
If I were to fix anything I start "fixing" by seeing what a Profiling session tells me. If I was worried about things like time to allocate memory, then profiling is the best way to get an accurate idea about how long to expect allocations to take. All the theories in the world cannot make up for profiling when you are not reusing known profiled implementations.
Also, if I were truly worried about the speed of things like memory allocation then I would take into consideration things from my profiling run such as the number of times that an object is created vs the objects time of life, hopefully my profiling session told me this. An object like your Simulation class should be created at most 1 time for a given simulation run while an object like Light might be created 0..N times during the run. So, I would focus on how creating Light objects affected my performance.
3: Did you ever came across this kind of pattern? I find it rather common throughout my code. Generally though, this is not a problem since Time is indeed polymorphic and hence heap-allocated.
I do not typically see simulation objects maintain a way to see the current state change variables such as Time. I typically see an object maintain its state, and only update when a time change occurs through a function such as SetState(Time & t){...}. If you think about it, that kind of makes sense. A simulation is a way to see the change of objects given a particular parameter(s), and the parameter should not be required for the object to report its state. Thus, an object should only update by single function and maintain its state between function calls.
// This little snippet is to give you an example of how update the state.
// I guess you could also do a publish subscribe for the SetState function.
class Light
{
public:
Light(double maxPower)
: currPower(0.0)
, maxPower(maxPower)
{}
void SetState(const Time & t)
{
currentPower = t.isNight() ? maxPower : 0.0;
}
double GetCurrentPower() const
{
return currentPower;
}
private:
double currentPower;
double maxPower;
}
Keeping an object from performing its own check on Time helps alleviate multithreaded stresses such as "How do I handle the case where the time changes and invalidates my on/off state after I read the time, but before I returned my state?"
4: Coming back to the root of the problem, which is "There is no need to move, I only want an unmovable object to be created in-place, but the compiler won't allow me to do so" why is there no simple solution in C++ and is there a solution in another language ?
If you only ever want 1 object to be created you can use the Singleton Design Pattern. When correctly implemented a Singleton is guaranteed to only ever make 1 instance of an object, even in a multithreaded scenario.
In the comment to your second solution, you're saying that it weakens the encapsulation, because the Simulation has to know that Light needs more information during move. I think it is the other way around. The Light needs to know that is being used in a context where the provided reference to the Time object may become invalid during Light's lifetime. Which is not good, because it forces a design of Light based on how it is being used, not based on what it should do.
Passing a reference between two objects creates (or should create) a contract between them. When passing a reference to a function, that reference should be valid until the function being called returns. When passing a reference to an object constructor, that reference should be valid throughout the lifetime of the constructed object. The object passing a reference is responsible for its validity. If you don't follow this, you may create very hard to trace relationships between the user of the reference and an entity maintaining lifetime of the referenced object. In your example, the Simulation is unable to uphold the contract between it and the Light object it creates when it is moved. Since the lifetime of the Light object is tightly coupled to the lifetime of the Simulation object, there are 3 ways to resolve this:
1) your solution number 2)
2) pass a reference to the Time object to constructor of the Simulation. If you assume the contract between the Simulation and the outer entity passing the reference is reliable, so will be the contract between Simulation and Light. You may, however, consider the Time object to be internal detail of the Simulation object and thus you would break encapsulation.
3) make the Simulation unmovable. Since C++(11/14) does not have any "in-place constructor methods" (don't know how good a term that is), you cannot create an in-place object by returning it from some function. Copy/Move-elision is currently an optimalization, not a feature. For this, you can either use your solution 5) or use lambdas, like this:
class SimulationBuilder {
public:
template< typename SimOp >
void withNewSimulation(const SimOp& simOp) {
Time time("2015/01/01-12:34:56");
double lightMaxPower = 42.;
double heatingMaxPower = 43.;
Simulation simulation(time,lightMaxPower,heatingMaxPower);
simOp( simulation );
}
};
int main() {
SimulationBuilder builder;
builder.withNewSimulation([] (Simulation& simulation) {
WeaklyRelatedPartOfTheProgram lightConsumptionReport;
lightConsumptionReport.editReport((simulation.getLight())); // No need to supply Time information
}
return 0;
}
If none fits your needs, then you either have to reevaluate your needs (might be a good option, too) or use heap allocation and pointers somewhere.
Related
I'm quite far into the development of a game using SDL, OpenGL and C++ and am looking for ways to optimize the way the game switches between GLSL shaders for lots of different objects of different types. This is much more of a C++ question than an OpenGL question. However, I still want to provide as much context as I can, as I feel some justification is needed as to why the proposed Shader class I need, needs to be created / deleted the way that it is.
The first four sections are my justifications, journey & attempts leading up to this point, however my question can likely be answered by just the final section alone and I've intentionally written it as a bit of a tldr.
The necessity for a Shader class:
I've seen many implementations online of OpenGL shaders being created, compiled and deleted all in the same function when game objects are created during gameplay. This has proven to be inefficient and far too slow in particular sections of my game. Thus, I've required a system that creates and compiles shaders during a load-time and then intermittently uses/swaps between them during game-time before being deleted later.
This has lead to the creation of a class(Shader) that manages OpenGL shaders. Each instance of the class should manage one unique OpenGL shader each and contains some complex behavior around the shader type, where it's loaded in from, where it's used, the uniform variables it takes, etc.
With this said, the most important role of this class is to store the GLuint variable id that is returned from glCreateShader(), and manage all OpenGL calls that relate to the OpenGL shader with this id. I understand that this is effectively futile given the global nature of OpenGL(as anywhere in the program could technically call glDeleteShader() with the matching id and break the class), however for the purposes of intentionally encapsulating all OpenGL calls to very specific areas throughout the entire codebase this system will drastically reduce code-complexity.
Where the problems start...
The most "automatic" way to manage this GLuint id, would be to invoke glCreateShader() on the object's construction and glDeleteShader() on the object's destruction. This guarantees(within OpenGL limits) that the OpenGL shader will exist for the entire lifetime of the C++ Shader object and eliminates the need to call some void createShader() and deleteShader() functions.
This is all well and good, however problems soon arise when considering what happens if this object is copied. What if a copy of this object is destructed? That means that glDeleteShader() will be called and effectively break all copies of the shader object.
What about simple mistakes like accidentally invoking std::vector::push_back() in a vector of Shaders? Various std::vector methods can invoke the constructor / copy constructor / destructor of their type, which can result in the same problem as above.
Okay then... how about we do create some void createShader() and deleteShader() methods even if it's messy? Unfortunately this just defers the above problem, as once again any calls that modify the OpenGL shader will desynchronize / outright break all copies of a shader class with the same id. I've limited the OpenGL calls to glCreateShader() and glDeleteShader() in this example to keep things simple, however I should note that there are many other OpenGL calls in the class that would make creating various instance/static variables that keep track of instance copies far too complicated to justify doing it this way.
The last point I want to make before jumping into the class design below is that for a project as large as a raw C++, OpenGL and SDL Game, I'd prefer if any potential OpenGL mistakes I make generate compiler errors versus graphical issues that are harder to track down. This can be reflected in the class design below.
The first version of the Shader class:
It is for the above reasons that I have elected to:
Make the constructor private.
Provide a public static create function that returns a pointer to a new Shader object in place of a constructor.
Make the copy constructor private.
Make the operator= private (Although this might not be necessary).
Make the destructor private.
Put calls to glCreateShader() in the constructor and glDeleteShader() in the destructor, to have OpenGL shaders exist for the lifetime of this object.
As the create function invokes the new keyword(and returns the pointer to it), the place with the outside call to Shader::create() must then invoke delete manually (more on this in a second).
To my understanding, the first two bullet points utilize a factory pattern and will generate a compiler error should a non-pointer type of the class be attempted to be created. The third, fourth and fifth bullet points then prevent the object from being copied. The seventh bullet point then ensures that the OpenGL Shader will exist for the same lifetime of the C++ Shader object.
Smart Pointers and the main problem:
The only thing I'm not a huge fan of in the above, is the new/delete calls. They also make the glDeleteShader() calls in the destructor of the object feel inappropriate given the encapsulation that the class is trying to achieve. Given this, I opted to:
change the create function to return a std::unique_ptr of the Shader type instead of a Shader pointer.
The create function then looked like this:
std::unique_ptr<Shader> Shader::create() {
return std::make_unique<Shader>();
}
But then a new problem arose... std::make_unique unfortunately requires that the constructor is public, which interferes with the necessities described in the previous section. Fortunately, I found a solution by changing it to:
std::unique_ptr<Shader> Shader::create() {
return std::unique_ptr<Shader>(new Shader());
}
But... now std::unique_ptr requires that the destructor is public! This is... better but unfortunately, this means that the destructor can be manually called outside of the class, which in turn means the glDeleteShader() function can be called from outside the class.
Shader* p = Shader::create();
p->~Shader(); // Even though it would be hard to do this intentionally, I don't want to be able to do this.
delete p;
The final class:
For the sake of simplicity, I have removed the majority of instance variables, function/constructor arguments & other attributes but here's what the final proposed class (mostly)looks like:
class GLSLShader {
public:
~GLSLShader() { // OpenGL delete calls for id }; // want to make this private.
static std::unique_ptr<GLSLShader> create() { return std::unique_ptr<GLSLShader>(new GLSLShader()); };
private:
GLSLShader() { // OpenGL create calls for id };
GLSLShader(const GLSLShader& glslShader);
GLSLShader& operator=(const GLSLShader&);
GLuint id;
};
I'm happy with everything in this class, aside from the fact that the destructor is public. I've put this design to the test and the performance increase is very noticeable. Even though I can't imagine I'd ever accidentally manually call the destructor on a Shader object, I don't like that it is publicly exposed. I also feel that I might accidentally miss something, like the std::vector::push_back consideration in the second section.
I've found two potential solutions to this problem. I'd like some advice on these or other solutions.
Make std::unique_ptr or std::make_unique a friend of the Shader class. I've been reading threads such as this one, however this is to make the constructor accessible, rather than the destructor. I also don't quite understand the downsides / extra considerations needed with making std::unique_ptr or std::make_unique a friend (The top answer to that thread + comments)?
Not use smart pointers at all. Is there perhaps a way to have my static create() function return a raw pointer(using the new keyword), that is automatically deleted inside the class / when the Shader goes out of scope and the destructor is called?
Thank you very much for your time.
This is a context challenge.
You are solving the wrong problem.
GLuint id, would be to invoke glCreateShader() on the object's construction and glDeleteShader()
Fix the problem here.
The Rule of Zero is that you make your resource wrappers manage lifetimes, and you don't do it in business logic types. We can write a wrapper around a GLuint that knows how to clean itself up and is move-only, preventing double destruction, by hijacking std::unique_ptr to store an integer instead of a pointer.
Here we go:
// "pointers" in unique ptrs must be comparable to nullptr.
// So, let us make an integer qualify:
template<class Int>
struct nullable{
Int val=0;
nullable()=default;
nullable(Int v):val(v){}
friend bool operator==(std::nullptr_t, nullable const& self){return !static_cast<bool>(self);}
friend bool operator!=(std::nullptr_t, nullable const& self){return static_cast<bool>(self);}
friend bool operator==(nullable const& self, std::nullptr_t){return !static_cast<bool>(self);}
friend bool operator!=(nullable const& self, std::nullptr_t){return static_cast<bool>(self);}
operator Int()const{return val;}
};
// This both statelessly stores the deleter, and
// tells the unique ptr to use a nullable<Int> instead of an Int*:
template<class Int, void(*deleter)(Int)>
struct IntDeleter{
using pointer=nullable<Int>;
void operator()(pointer p)const{
deleter(p);
}
};
// Unique ptr's core functionality is cleanup on destruction
// You can change what it uses for a pointer.
template<class Int, void(*deleter)(Int)>
using IntResource=std::unique_ptr<Int, IntDeleter<Int,deleter>>;
// Here we statelessly remember how to destroy this particular
// kind of GLuint, and make it an RAII type with move support:
using GLShaderResource=IntResource<GLuint,glDeleteShader>;
now that type knows it is a shader and cleans itself up it non-null.
GLShaderResource id(glCreateShader());
SomeGLFunction(id.get());
apologies for any typos.
Stuff that in your class, and copy ctors are blocked, move ctors do the right thing, dtors clean up automatically, etc.
struct GLSLShader {
// public!
~GLSLShader() = default;
GLSLShader() { // OpenGL create calls for id };
private: // does this really need to be private?
GLShaderResource id;
};
so much simpler.
std::vector<GLSLShader> v;
and that just works. Our GLShaderResource is semi-regular (move only regular type, no sort support), and vector is happy with those. Rule of 0 means that GLSLShader, which owns it, is also semi-regular and supports RAII -- resource allocation is initialization -- which in turn means it cleans up after itself properly when stored in std containers.
A type being "Regular" means it "behaves like an int" -- like the prototypical value type. C++'s standard library, and much of C++, likes it when you are using regular or semi-regular types.
Note that this is basically zero overhead; sizeof(GLShaderResource) is the same as GLuint and nothing goes on the heap. We have a pile of compile-time type machinery wrapping a simple 32 bit integers; that compile-time type machinery generates code, but doesn't make the data more complex than 32 bits.
Live example.
The overhead includes:
Some calling conventions make passing a struct wrapping only an int be passed differently than an int.
On destruction, we check every one of these to see if it is 0 to decide if we want to call glDeleteShader; compilers can sometimes prove that something is guaranteed zero and skip that check. But it won't tell you if it did manage to pull that off. (OTOH, humans are notoriously bad at proving that they kept track of all resources, so a few runtime checks aren't the worst thing).
If you are doing a completely unoptimized build, there are going to be a few extra instructions when you call a OpenGL function. But after any non-zero level of inlineing by the compiler they will disappear.
The type isn't "trivial" (a term in the C++ standard) in a few ways (copyable, destroyable, constructible), which makes doing things like memset illegal under the C++ standard; you can't treat it like raw memory in a few low level ways.
A problem!
Many OpenGL implementations have pointers for glDeleteShader/glCreateShader etc, and the above relies on them being actual functions not pointers or macros or whatever.
There are two easy workarounds. The first is to add a & to the deleter arguments above (two spots). This has the problem that it only works when they are actually pointers now, and not when they are actual functions.
Making code that works in both cases is a bit tricky, but I think almost every GL implementation uses function pointers, so you should be good unless you want to make a "library quality" implementation. In that case, you can write some helper types that create constexpr function pointers that call the function pointer (or not) by name.
Finally, apparently some destructors require extra parameters. Here is a sketch.
using GLuint=std::uint32_t;
GLuint glCreateShaderImpl() { return 7; }
auto glCreateShader = glCreateShaderImpl;
void glDeleteShaderImpl(GLuint x) { std::cout << x << " deleted\n"; }
auto glDeleteShader = glDeleteShaderImpl;
std::pair<GLuint, GLuint> glCreateTextureWrapper() { return {7,1024}; }
void glDeleteTextureImpl(GLuint x, GLuint size) { std::cout << x << " deleted size [" << size << "]\n"; }
auto glDeleteTexture = glDeleteTextureImpl;
template<class Int>
struct nullable{
Int val=0;
nullable()=default;
nullable(Int v):val(v){}
nullable(std::nullptr_t){}
friend bool operator==(std::nullptr_t, nullable const& self){return !static_cast<bool>(self);}
friend bool operator!=(std::nullptr_t, nullable const& self){return static_cast<bool>(self);}
friend bool operator==(nullable const& self, std::nullptr_t){return !static_cast<bool>(self);}
friend bool operator!=(nullable const& self, std::nullptr_t){return static_cast<bool>(self);}
operator Int()const{return val;}
};
template<class Int, auto& deleter>
struct IntDeleter;
template<class Int, class...Args, void(*&deleter)(Int, Args...)>
struct IntDeleter<Int, deleter>:
std::tuple<std::decay_t<Args>...>
{
using base = std::tuple<std::decay_t<Args>...>;
using base::base;
using pointer=nullable<Int>;
void operator()(pointer p)const{
std::apply([&p](std::decay_t<Args> const&...args)->void{
deleter(p, args...);
}, static_cast<base const&>(*this));
}
};
template<class Int, void(*&deleter)(Int)>
using IntResource=std::unique_ptr<Int, IntDeleter<Int,deleter>>;
using GLShaderResource=IntResource<GLuint,glDeleteShader>;
using GLTextureResource=std::unique_ptr<GLuint,IntDeleter<GLuint, glDeleteTexture>>;
int main() {
auto res = GLShaderResource(glCreateShader());
std::cout << res.get() << "\n";
auto tex = std::make_from_tuple<GLTextureResource>(glCreateTextureWrapper());
std::cout << tex.get() << "\n";
}
Implement a deleter yourself, and let the deleter be a friend of your class.
Then edit your declaration like this:
static std::unique_ptr<GLSLShader, your_deleter> create();
I wanted to know of how to make my use of the command pattern thread-safe while maintaining performance. I have a simulation where I perform upwards of tens of billions of iterations; performance is critical.
In this simulation, I have a bunch of Moves that perform commands on objects in my simulation. The base class looks like this:
class Move
{
public:
virtual ~Move(){}
// Perform a move.
virtual void Perform(Object& obj) = 0;
// Undo a move.
virtual void Undo() = 0;
};
The reason I have the object passed in on Perform rather than the constructor, as is typical with the Command pattern, is that I cannot afford to instantiate a new Move object every iteration. Rather, a concrete implementation of Move would simply take Object, maintain a pointer to it and it's previous state for when it's needed. Here's an example of a concrete implementation:
class ConcreteMove : public Move
{
std::string _ns;
std::string _prev;
Object* _obj;
ConcreteMove(std::string newstring): _ns(newstring) {}
virtual void Perform(Object& obj) override
{
_obj= &obj;
_prev = obj.GetIdentifier();
obj.SetIdentifier(_ns);
}
virtual void Undo()
{
_obj->SetIdentifier(_prev);
}
};
Unfortunately, what this has cost me is thread-safety. I want to parallelize my loop, where multiple iterators perform moves on a bunch of objects simultaneously. But obviously one instance of ConcreteMove cannot be reused because of how I implemented it.
I considered having Perform return a State object which can be passed into Undo, that way making the implementation thread-safe, since it is independent of the ConcereteMove state. However, the creation and destruction of such an object on each iteration is too costly.
Furthermore, the simulation has a vector of Moves because multiple moves can be performed every iteration stored in a MoveManager class which contains a vector of Move object pointers instantiated by the client. I set it up this way because the constructors of each particular Concrete moves take parameters (see above example).
I considered writing a copy operator for Move and MoveManager such that it can be duplicated amongst the threads, but I don't believe that is a proper answer because then the ownership of the Move objects falls on MoveManager rather than the client (who is only responsible for the first instance). Also, the same would be said for MoveManager and responsibility of maintaining that.
Update: Here's my MoveManager if it matters
class MoveManager
{
private:
std::vector<Move*> _moves;
public:
void PushMove(Move& move)
{
_moves.push_back(&move);
}
void PopMove()
{
_moves.pop_back();
}
// Select a move by index.
Move* SelectMove(int i)
{
return _moves[i];
}
// Get the number of moves.
int GetMoveCount()
{
return (int)_moves.size();
}
};
Clarification: All I need is one collection of Move objects per thread. They are re-used every iteration, where Perform is called on different objects each time.
Does anyone know how to solve this problem efficiently in a thread-safe manner?
Thanks!
What about the notion of a thread ID. Also, why not preconstruct the identifier strings and pass pointers to them?
class ConcreteMove : public Move
{
std::string *_ns;
std::vector<std::string *> _prev;
std::vector<Object *> _obj;
ConcreteMove(unsigned numthreads, std::string *newstring)
: _ns(newstring),
_prev(numthreads),
_obj(numthreads)
{
}
virtual void Perform(unsigned threadid, Object &obj) override
{
_obj[threadid] = &obj;
_prev[threadid] = obj.GetIdentifier();
obj.SetIdentifier(_ns);
}
virtual void Undo(unsigned threadid)
{
_obj[threadid]->SetIdentifier(_prev[threadid]);
}
};
Impossible with stated requirements. Specifically,
Use the command pattern. "the command pattern is a behavioral design pattern in which an object is used to represent and encapsulate all the information needed to call a method at a later time." Thus you're storing data.
You "can't afford" to allocate memory.
You have "billions" of iterations, which means some large static allocation won't suffice.
You want to store data without any place to store it. Thus there is no answer. However, if you're willing to change your requirements, there are undoubtedly many ways to solve your problem (whatever it may be -- I couldn't tell from the description.)
I also can't estimate how many Move objects you need at once. If that number is reasonably low then a specialized allocation scheme might solve part of your problem. Likewise, if most of the Move objects are duplicates, a different specialized allocation scheme might help.
In general what you're asking can't be solved, but relax the requirements and it shouldn't be hard.
Your Move Manager should not contain a vector of pointers, it should be a vector of Move objects
std::vector<Move> _moves;
It seems you will have one Move Manager per thread, so no issue of multi-threading problems, set the vector capacity at max, and then apply perform and other actions on the move in the vector
No new allocation, and you will be reusing the move objects
So, I've done (a small amount) of reading and am aware that unique_ptr in combination with raw pointers is the pattern to use when modeling unique ownership.
However, I really like the simple and clear concept of using a weak_ptr to check if a value is valid, and then discard the shared_ptr after using it, and this keeps everyone happy (at a slight reference counting performance cost).
My particular problem right now is in creating an expressive and flexible system for tracking multitouch points, and it seemed elegant to use the destruction of the object that represents a touch to be the signal that the touch has ended. If I went with the raw pointer route, I would need to define some semantics that each component interfacing with this system would need to conform to, something slightly ugly like having a second argument involved that indicates whether the pointer is valid or some such.
This issue with the raw pointer route is perhaps a strawman issue as I don't expect this to become a large project, but the question is mostly of practical interest in terms of how to write the best modern C++ code.
pseudocode:
class InputConsumer {
void handle(std::list<std::weak_ptr<Touch>>*);
// consumer doesnt hold references to anything outside of its concern.
// It only has to know how to deal with input data made available to it.
// the consumer is a child who is given toys to play with and I am trying to
// see how far I can go to sandbox it
}
class InputSender {
std::list<std::weak_ptr<Touch>> exposedinputdata;
std::list<std::shared_ptr<Touch>> therealownedtouches;
// sender populates exposedinputdata when input events come in.
// I want to let the consumer copy out weak_ptrs as much as it wants,
// but for it to never hold on to it indefinitely. There does not appear
// to be an easy way to enforce this (admittedly it is kind of vague. it
// has to be around for long enough to be used to read out data, but
// not e.g. 3 frames. Maybe what I need is to make an intelligent
// smart pointer that has a timer inside of it.)
std::list<std::weak_ptr<InputConsumer>> consumers;
void feedConsumersWithInput() {
for (auto i = consumers.begin(); i != consumers.end(); ++i) {
if (i->expired()) {
consumers.erase(i);
} else {
i->lock()->handle(&exposedinputdata);
}
}
}
When I saw the ability of weak_ptr to express very similar semantics to what I am modeling, I just really wanted to use it, because its interface is clean and simple, and most importantly it self-documents how this code is going to work. This is a huge benefit down the road.
Now I'm pretty sure that everything will be really peachy until such time as an InputConsumer calls lock() on weak_ptr<Touch> and retains the shared_ptr<Touch>. It will prevent the underlying Touch from being freed even after the primary owner of it has erased its owning shared_ptr! This seems to me the only wrinkle, and a little one at that. I think it's far harder to screw up ownership handling with shared_ptr than it is to do so with raw pointers.
What are some ways of patching this up? I am thinking of maybe making a template subclass (?! I have never written such a thing, recently got into templates. Loving them) of weak_ptr that will somehow forbid retaining a shared_ptr, or something.
Maybe I can subclass shared_ptr and override its dtor to throw if it doesn't call the deleter?
Considering that having a weak_ptr always requires reference counting, rolling out whatever solution is (more or less) like rewriting the shared_ptr one.
The quick and dirty way is probably derive shared_ptr and provide it with only the move ctor (monitore_ptr(monitored_ptr&&) ) and transfer operator (monitored_ptr& operator=(monitored_ptr&&) ), thus disabling the shared_ptr copy (and hence "sharing") capabilities.
The problem of derivation is that, being shared_ptr not polymorphic, you end up with a non polymorphic type that exibit some polymorphism towards shared_ptr (you can assign to it, thus violating your assumptions).
This can be compensated by using protected inheritance and re-expose only the required functionalities (essentially the * and -> operators).
To avoid miss-behavior against weak_ptr (like your monitored_ptr given to weak_ptr given to shared_ptr)... I'll also suggest to override weak_ptr as well, with protected inheritance.
At that point you end up with a pair of classes that are self sufficient and not compatible with any other shared pointer.
In any case, the key is writing proper contructors, and not (as you proposed) throw in the destructor: it is a situation with a lot of potential gotcha, hardly manageable.
(see for example here)
I'm going to propose a pretty simple design. It is a thin wrapper around a weak_ptr where the only way to access the underlying T is to pass a lambda to a method.
This restricts the lifetime of the shared_ptr from lock() to be the time you call the method: while in theory you can lock the shared_ptr indefinitely, you can only do it by never returning from the try.
template<typename T>
struct monitored_pointer {
template<typename Lambda>
bool try( Lambda&& closure ) const {
auto p = m_ptr.lock();
if (!p)
return false;
std::forward<Lambda>(closure)(*p):
return true;
}
bool valid() const {
return try( [](T&){} );
}
void reset( std::weak_ptr<T> ptr = std::weak_ptr<T>() )
{
m_ptr = ptr;
}
explicit operator bool() const { return valid(); }
monitored_pointer() {}
monitored_pointer( monitored_pointer && ) = default;
monitored_pointer& operator=( monitored_pointer && ) = default;
explicit monitored_pointer( std::weak_ptr<T> ptr ):m_ptr(ptr) {}
private:
std::weak_ptr<T> m_ptr;
};
valid and operator bool just helps when you want to clean out expired monitored_pointers.
Use looks something like:
if (!ptr.try( [&]( Touch& touch ) {
// code that uses the `touch` here
})) {
// code that handles the fact that ptr is no longer valid here
}
I am currently going through the book Head First Object Oriented Analysis and Design and also getting used to some of the features of C++11 (especially unique_ptr and move semantics) at the same time. In the book, they give the design of a strategy board game as an example. It has a board, tiles and units on tiles. The code is in Java and I was trying to rewrite it in C++. In Java, the tile class is as follows:
public class Tile
{
private List units;
public Tile()
{
units = new LinkedList();
}
protected void addUnit(Unit unit)
{
units.add(unit);
}
protected List getUnits()
{
return units;
}
}
I did the same thing in c++ first using shared_ptr. It worked but very slow compared to my second version which used raw pointers. I then tried unique_ptr:
class Tile
{
public:
Tile();
virtual ~Tile();
void addUnit()
{
mUnits.push_back(std::unique_ptr<Unit>(new Unit());
}
std::vector<std::unique_ptr<Unit>> getUnits()
{
return mUnits;
}
private:
std::vector<std::unique_ptr<Unit>> mUnits;
};
the compiler does not like the getUnits. From what I understand it comes from the fact that the copy constructor is disabled in the unique_ptr. How would you return the list of vectors?
Thanks!
A value returned in C++ incurs a copy - if that's what you want, you can't use unique_ptr or have to make a manual copy and std::move it. However, I take you only want to provide access to the Units (for whatever reason...), so simply return a reference:
std::vector<std::unique_ptr<Unit>> const& getUnits() const
{
return mUnits;
}
(The const is only needed if you don't want to give write access into the vector.)
Now, a few questions arise still: Why is ~Tile virtual? I see no need.
Why do you use an owning ptr to point to the units? In the original Java code, you get handed a reference to an external Unit and only store a reference - if the Tile in the Java code is destroyed, the units are not (from what I can see), as long as they are referenced somewhere else. To achieve the exact same in C++, you were correct in using shared_ptr.
Of course, you could just clarify who is the real owner of the units and operate accordingly - if it is not Tile, use a raw pointer. See also "Which kind of pointer do I use when?"
What's a good existing class/design pattern for multi-stage construction/initialization of an object in C++?
I have a class with some data members which should be initialized in different points in the program's flow, so their initialization has to be delayed. For example one argument can be read from a file and another from the network.
Currently I am using boost::optional for the delayed construction of the data members, but it's bothering me that optional is semantically different than delay-constructed.
What I need reminds features of boost::bind and lambda partial function application, and using these libraries I can probably design multi-stage construction - but I prefer using existing, tested classes. (Or maybe there's another multi-stage construction pattern which I am not familiar with).
The key issue is whether or not you should distinguish completely populated objects from incompletely populated objects at the type level. If you decide not to make a distinction, then just use boost::optional or similar as you are doing: this makes it easy to get coding quickly. OTOH you can't get the compiler to enforce the requirement that a particular function requires a completely populated object; you need to perform run-time checking of fields each time.
Parameter-group Types
If you do distinguish completely populated objects from incompletely populated objects at the type level, you can enforce the requirement that a function be passed a complete object. To do this I would suggest creating a corresponding type XParams for each relevant type X. XParams has boost::optional members and setter functions for each parameter that can be set after initial construction. Then you can force X to have only one (non-copy) constructor, that takes an XParams as its sole argument and checks that each necessary parameter has been set inside that XParams object. (Not sure if this pattern has a name -- anybody like to edit this to fill us in?)
"Partial Object" Types
This works wonderfully if you don't really have to do anything with the object before it is completely populated (perhaps other than trivial stuff like get the field values back). If you do have to sometimes treat an incompletely populated X like a "full" X, you can instead make X derive from a type XPartial, which contains all the logic, plus protected virtual methods for performing precondition tests that test whether all necessary fields are populated. Then if X ensures that it can only ever be constructed in a completely-populated state, it can override those protected methods with trivial checks that always return true:
class XPartial {
optional<string> name_;
public:
void setName(string x) { name_.reset(x); } // Can add getters and/or ctors
string makeGreeting(string title) {
if (checkMakeGreeting_()) { // Is it safe?
return string("Hello, ") + title + " " + *name_;
} else {
throw domain_error("ZOINKS"); // Or similar
}
}
bool isComplete() const { return checkMakeGreeting_(); } // All tests here
protected:
virtual bool checkMakeGreeting_() const { return name_; } // Populated?
};
class X : public XPartial {
X(); // Forbid default-construction; or, you could supply a "full" ctor
public:
explicit X(XPartial const& x) : XPartial(x) { // Avoid implicit conversion
if (!x.isComplete()) throw domain_error("ZOINKS");
}
X& operator=(XPartial const& x) {
if (!x.isComplete()) throw domain_error("ZOINKS");
return static_cast<X&>(XPartial::operator=(x));
}
protected:
virtual bool checkMakeGreeting_() { return true; } // No checking needed!
};
Although it might seem the inheritance here is "back to front", doing it this way means that an X can safely be supplied anywhere an XPartial& is asked for, so this approach obeys the Liskov Substitution Principle. This means that a function can use a parameter type of X& to indicate it needs a complete X object, or XPartial& to indicate it can handle partially populated objects -- in which case either an XPartial object or a full X can be passed.
Originally I had isComplete() as protected, but found this didn't work since X's copy ctor and assignment operator must call this function on their XPartial& argument, and they don't have sufficient access. On reflection, it makes more sense to publically expose this functionality.
I must be missing something here - I do this kind of thing all the time. It's very common to have objects that are big and/or not needed by a class in all circumstances. So create them dynamically!
struct Big {
char a[1000000];
};
class A {
public:
A() : big(0) {}
~A() { delete big; }
void f() {
makebig();
big->a[42] = 66;
}
private:
Big * big;
void makebig() {
if ( ! big ) {
big = new Big;
}
}
};
I don't see the need for anything fancier than that, except that makebig() should probably be const (and maybe inline), and the Big pointer should probably be mutable. And of course A must be able to construct Big, which may in other cases mean caching the contained class's constructor parameters. You will also need to decide on a copying/assignment policy - I'd probably forbid both for this kind of class.
I don't know of any patterns to deal with this specific issue. It's a tricky design question, and one somewhat unique to languages like C++. Another issue is that the answer to this question is closely tied to your individual (or corporate) coding style.
I would use pointers for these members, and when they need to be constructed, allocate them at the same time. You can use auto_ptr for these, and check against NULL to see if they are initialized. (I think of pointers are a built-in "optional" type in C/C++/Java, there are other languages where NULL is not a valid pointer).
One issue as a matter of style is that you may be relying on your constructors to do too much work. When I'm coding OO, I have the constructors do just enough work to get the object in a consistent state. For example, if I have an Image class and I want to read from a file, I could do this:
image = new Image("unicorn.jpeg"); /* I'm not fond of this style */
or, I could do this:
image = new Image(); /* I like this better */
image->read("unicorn.jpeg");
It can get difficult to reason about how a C++ program works if the constructors have a lot of code in them, especially if you ask the question, "what happens if a constructor fails?" This is the main benefit of moving code out of the constructors.
I would have more to say, but I don't know what you're trying to do with delayed construction.
Edit: I remembered that there is a (somewhat perverse) way to call a constructor on an object at any arbitrary time. Here is an example:
class Counter {
public:
Counter(int &cref) : c(cref) { }
void incr(int x) { c += x; }
private:
int &c;
};
void dontTryThisAtHome() {
int i = 0, j = 0;
Counter c(i); // Call constructor first time on c
c.incr(5); // now i = 5
new(&c) Counter(j); // Call the constructor AGAIN on c
c.incr(3); // now j = 3
}
Note that doing something as reckless as this might earn you the scorn of your fellow programmers, unless you've got solid reasons for using this technique. This also doesn't delay the constructor, just lets you call it again later.
Using boost.optional looks like a good solution for some use cases. I haven't played much with it so I can't comment much. One thing I keep in mind when dealing with such functionality is whether I can use overloaded constructors instead of default and copy constructors.
When I need such functionality I would just use a pointer to the type of the necessary field like this:
public:
MyClass() : field_(0) { } // constructor, additional initializers and code omitted
~MyClass() {
if (field_)
delete field_; // free the constructed object only if initialized
}
...
private:
...
field_type* field_;
next, instead of using the pointer I would access the field through the following method:
private:
...
field_type& field() {
if (!field_)
field_ = new field_type(...);
return field_;
}
I have omitted const-access semantics
The easiest way I know is similar to the technique suggested by Dietrich Epp, except it allows you to truly delay the construction of an object until a moment of your choosing.
Basically: reserve the object using malloc instead of new (thereby bypassing the constructor), then call the overloaded new operator when you truly want to construct the object via placement new.
Example:
Object *x = (Object *) malloc(sizeof(Object));
//Use the object member items here. Be careful: no constructors have been called!
//This means you can assign values to ints, structs, etc... but nested objects can wreak havoc!
//Now we want to call the constructor of the object
new(x) Object(params);
//However, you must remember to also manually call the destructor!
x.~Object();
free(x);
//Note: if you're the malloc and new calls in your development stack
//store in the same heap, you can just call delete(x) instead of the
//destructor followed by free, but the above is the correct way of
//doing it
Personally, the only time I've ever used this syntax was when I had to use a custom C-based allocator for C++ objects. As Dietrich suggests, you should question whether you really, truly must delay the constructor call. The base constructor should perform the bare minimum to get your object into a serviceable state, whilst other overloaded constructors may perform more work as needed.
I don't know if there's a formal pattern for this. In places where I've seen it, we called it "lazy", "demand" or "on demand".