Yes, I was also wondering why it's necessary to come up with yet another smart pointer, which you need to learn and which is probably not battle tested.
They also seem to have wrapped the STL, which I think is a big no-no. No real reason to relearn something new if there is an established standard. A modern C++ library shouldn't do that.
I am a member of the Boden dev team. The smart pointer system is actually still a topic of discussion in the Boden team as well. It has a couple of nice properties, like the fine grained control bdn::P gives us over the time when an object is actually destructed. For example, these pointers provide an easy way to ensure that destruction of our View objects happens only on the main thread, no matter which thread released the last reference.
But on the other hand, not using the standard constructs definitely has a cost associated with it. We are happy for your feedback on this issue.
Note that we also think about the idea of transforming P and making it a specialization of std::shared_ptr for objects derived from bdn::Base. That would give us the best of both worlds. Feel free to let us know what you think.
Deferring destructors is a suspicious pattern in general - in C++, I generally expect them to not be async and unpredictable like that. What guarantees do you make wrt destruction order? I hope it's not as complicated as finalizers in Java and C#...
The more logical model, to me, would be to have child views owned by parent views, and to only allow ownership-changing calls (i.e. adding or removing a child) from the main thread. That way all you really need is unique_ptr (from parent to children) and raw pointers (from children to parent, and from any observers). Although it would probably still be better to use shared_ptr just so that observers can use weak_ptr, since untangling lifetimes in callbacks can be tricky, and often it's easier to just check if the object is still there.
To give a specific code example, with unique_ptr, the same snippet would be:
_window = std::make_unique<bdn::Window>();
_window->setTitle("AwesomeApp");
auto button = std::make_unique<bdn::Button>();
button->setLabel("Hello World");
// The following *moves* button, such that _window takes ownership over it.
// It can only be called from the main thread.
_window->setContentView(button);
_window->requestAutoSize();
_window->requestCenter();
_window->setVisible(true);
And furthermore, _window wouldn't have to be a pointer at all - it can just be a member of MainViewController.
They also seem to have wrapped the STL, which I think is a big no-no. No real reason to relearn something new if there is an established standard. A modern C++ library shouldn't do that.