A smart pointer that lazily recreates its resource

I have a ServiceProvider class that contains a pair of pointers to different services, for example:

 class ServiceProvider() { Service3* GetService3(); public: void Process(Object* o); void Shrink(); private: TAutoSpawningPtr<Service1> service1; TAutoSpawningPtr<Service2> service2; Service3* service3; } 

Please note that TAutoSpawningPtr is the theoretical class of the smart pointer I'm looking for, and service3 is declared as a regular pointer to explicitly show the behavior I needed. Body Process() :

 void ServiceProvider::Process(Object* o) { service1->Process(o); service2->Process(o); GetService3()->Process(o); } 

The body of GetService3() :

 void ServiceProvider::GetService3() { if(!service3) { service3 = new Service3(); } return service3; } 

As you can see, an instance of Service3 is created lazily and does not exist until it is needed.

Shrink() method is called periodically to remove all internal services. Like this:

 void ServiceProvider::Shrink() { service1.Release(); // delete its internal Service1 pointer if it exists. service2.Release(); // delete its internal Service2 pointer if it exists. if (service3) { // delete its internal Service3 pointer if it exists. delete service3; service3 = nullptr; } } 

What I need: I want TAutoSpawningPtr<> be a smart pointer class that automatically instantiates the class, invoking the default construct when I cast the pointer using an overloaded operator-> . The internal resource available to the pointer had to be deleted once when the Release() method was called (and, of course, it had to be recreated when I needed it).

Why do I need it?

  • Automatic control of the presence / absence of the object.
  • To exclude nullptrs when the draining pointers directly (e.g. this->service3->Process(o) ) instead of indirect GetService3() .
  • To free unused services without explicit checks.

Question: Does the standard (or any third-party) library have an automatic pointer class that will satisfy my needs? And if not, can you bring me some code examples that show the behavior I need. Thanks.

+5
source share
1 answer

The simplest solution here would be to simply call a function that initializes the two if they are not initialized or point to nothing.

But if you really want to, you can create a simple proxy pointer class that does this for you. for instance

 #include <iostream> #include <memory> using std::cout; using std::endl; class Something { public: Something() { cout << __PRETTY_FUNCTION__ << endl; } void do_something() { cout << __PRETTY_FUNCTION__ << endl; } }; template <typename Type, template <typename...> class Ptr = std::unique_ptr> class AutoAllocatingPtr { public: Type* operator->() { if (!this->ptr) { this->ptr = Ptr<Type>{new Type{}}; } return this->ptr.get(); } void release() { this->ptr.reset(); } private: Ptr<Type> ptr; }; int main() { // default unique ownership with std::unique_ptr auto ptr = AutoAllocatingPtr<Something>{}; ptr->do_something(); ptr.release(); ptr->do_something(); // if you want shared ownership auto s_ptr = AutoAllocatingPtr<Something, std::shared_ptr>{}; s_ptr->do_something(); s_ptr.release(); s_ptr->do_something(); } 

Note Pay attention to the code at the end and how you can use it to switch the type of semantics of the property displayed by the pointer.

+5
source

Source: https://habr.com/ru/post/1269283/


All Articles