Register    Login    Forum    Search    FAQ

Board index » Everything




Post new topic Reply to topic  [ 6 posts ] 
Author Message
 Post Posted: June 16th, 2017, 1:05 pm 
 

Joined: February 12th, 2017, 1:50 pm
Posts: 12
Hi everyone!
I made a little "platformer-framework" around sfml. Really I just used sf::Texture, sf::Sprite and sf::Clock so if I know how to load and display sprites in the chilli framework (in some time when the tut is out ;)) I want to "port" it over to the Chilli Framework :)
For those who are interested, here is the github: https://github.com/florianPat/SFMLPlatformer
It would be very cool if some of you maybe look over it, write what could be improved and so on. You know ;)
I know that I should use more const-correctness but up until this point, I was to lazy to really do it, so...
I am not sure if I use the shared_ptr, unique_ptr really right or if I do a big mistake, so response on that would be also pretty cool.
Moreover, in Component, I have a circular dependencie. I do not know how to avoid that, but if someone comes up with an idea, I would be very likely to hear it!
Thanks for answers in advance (or how you call it ;))


Top 
 Profile  
Reply with quote  
 Post Posted: June 16th, 2017, 3:27 pm 
Site Admin
User avatar

Joined: December 31st, 2011, 4:53 pm
Posts: 3303
Location: Japan
Looks like interesting stuff. It's already a pretty complex system, I can't really give a detailed analysis. But it seems like your use of shared_ptr isn't bad. You've got some weird code where you pass in an iterator as a parameter, that could probably be cleaned up. Also, I think you should add a garbage collection function to clear out all objects that don't have any external references. I'll see if I can build this later. Looking forward to seeing what you make of it bro :)

_________________
Chili


Top 
 Profile  
Reply with quote  
 Post Posted: June 16th, 2017, 11:37 pm 
 

Joined: April 19th, 2017, 12:49 pm
Posts: 33
Location: Germany
Hi,
looks like you already solved the circular dependency problem. If u cant avoid it by design you ve to use forward declarations afaik like u did with the Actor class in Component.h.

short explanation:
https://stackoverflow.com/questions/4926105/what-is-forward-declaration-in-c

how to use it properly:
https://stackoverflow.com/questions/553682/when-can-i-use-a-forward-declaration

If u already know that stuff ignore it.

I reviewed some parts of your code.

like:
Code:
template<typename T>
inline T* Actor::getComponent(int componentId)
{
...
return dynamic_cast<T*>(result->second.get()); //TODO: Do I really want to return a raw pointer?
}


I am not that familiar with smart pointers yet, but i would say its fine to get a rawpointer here.

In my sourcecode i handle resourcemanagement with smartpointers.
For example when i load a new texture from file and store it in a std::unordered_map like:

std::unordered_map<std::string, std::pair<std::unique_ptr<T>, unsigned int>> m_resources;
T can be for example a sf::texture, sf::font, sound etc.
(i know shared pointer would be a better way to solve that like you re already doing, but i was to lazy to adjust it yet)

When for example a sprite needs a texture you can use a raw pointer imho. Even if the ownership of the texture ll move the raw pointer adress should stay the same - i made a quick test before with std::unique_pointer

Code:
   Foo f1(1);
   Foo f2(2);

   Foo* pRaw1;
   Foo* pRaw2;

   std::unique_ptr<Foo> p1(std::make_unique<Foo>(f1));   
   pRaw1 = p1.get();

   std::unique_ptr<Foo> p2 = std::move(p1);
   pRaw2 = p2.get();


   std::cout << "p1Raw1: " << pRaw1 << std::endl;
   std::cout << "p2Raw2: " << pRaw2 << std::endl;


Please correct me if anything is wrong.


Top 
 Profile  
Reply with quote  
 Post Posted: June 17th, 2017, 3:58 am 
 

Joined: February 28th, 2013, 3:23 am
Posts: 2663
Location: Oklahoma, United States
Use smart pointers for lifetime and ownership of resources. Use raw pointers to pass to functions when lifetime will outlive the function and ownership of the resource won't be transferred to the function or anything inside the function.

That's my rule of thumb.

The reason for smart pointers is to allocate when created, and deallocate when destroyed ( leaves scope ). It makes resources on the heap act more like resources allocated on the stack. When a resource allocated on the stack leaves scope, then the resource is freed. So when a smart pointer like std::unique_ptr leaves scope, the dynamically allocated memory is freed. This also reduces the amount of work the programmer has to do. Before std::unique_ptr, you would have to use operator new/new[] to allocate and either at the end of a function or in a class destructor, you'd have to call operator delete/delete[] ( new/delete for single elements new[]/delete[] for arrays of elements ).

std::shared_ptr is useful for shared ownership, and has it's benefits and drawbacks. Personally, I'd only use it in multithreaded situations because of the atomic reference counting. The way I would approach resource sharing in single threaded situations would be to store the unique_ptr some where, and pass around the raw pointer stored using unique_ptr::get(). I always know in my own code, raw pointers are not owned, while unique_ptrs are owned. Either way I don't have to delete my pointers because of the stance I take on how I use them.

_________________
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com


Top 
 Profile  
Reply with quote  
 Post Posted: June 17th, 2017, 4:03 am 
 

Joined: February 28th, 2013, 3:23 am
Posts: 2663
Location: Oklahoma, United States
Forgot to mention about shared_ptr. Dealing with passing them around can get confusing because of the reference counting. If you pass them by value, the reference count goes up, so pass to a function, add 1, copied inside the function add 1, leave the function subtract 1 for the paramter, then maybe 1 for the copy depending on the lifetime of the copy. Pass by reference, no increment for the paramter, but there add one for the copy. Leave the function, no decrement for the parameter, but maybe for the copy again depending on the lifetime of the copy. Pass by const ref...reference counter can't be incremented for the parameter or the copy, so is it still a "shared" pointer?

_________________
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com


Top 
 Profile  
Reply with quote  
 Post Posted: June 17th, 2017, 4:12 pm 
Site Admin
User avatar

Joined: December 31st, 2011, 4:53 pm
Posts: 3303
Location: Japan
shared_ptr is excellent in both single-threaded and multi-threaded situations. If you have some shared resource and you have one object own it with a unique pointer and others reference it with normal pointers, when the owner dies all the others will have dangling references and that is a terrible situation.

If you have a situation of sharing between peers, use shared_ptr. If you have a situation where one object is guaranteed to have a lifetime that encompasses all the lifetimes of the objects which refer to the resource, you can have that object own the resource outright with a unique pointer and give out references. This situation is not what I would call sharing, and it does not require a shared pointer.

_________________
Chili


Top 
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
 
Post new topic Reply to topic  [ 6 posts ] 

Board index » Everything


 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for: