// Copyright 2019 The MediaPipe Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef MEDIAPIPE_DEPS_NO_DESTRUCTOR_H_ #define MEDIAPIPE_DEPS_NO_DESTRUCTOR_H_ #include <type_traits> #include <utility> namespace mediapipe { // NoDestructor<T> is a wrapper around an object of type T that // * stores the object of type T inline inside NoDestructor<T> // * eagerly forwards constructor arguments to it (i.e. acts like T in terms // of construction) // * provides access to the object of type T like a pointer via ->, *, and get() // (note that const NoDestructor<T> works like a pointer to const T) // * never calls T's destructor for the object // (hence NoDestructor<T> objects created on the stack or as member variables // will lead to memory and/or resource leaks) // // One key use case of NoDestructor (which in itself is not lazy) is optimizing // the following pattern of safe on-demand construction of an object with // non-trivial constructor in static storage without destruction ever happening: // const std::string& MyString() { // static std::string* x = new std::string("foo"); // note the "static" // return *x; // } // By using NoDestructor we do not need to involve heap allocation and // corresponding pointer following (and hence extra CPU cache usage/needs) // on each access: // const std::string& MyString() { // static NoDestructor<std::string> x("foo"); // return *x; // } // Since C++11 this static-in-a-function pattern results in exactly-once, // thread-safe, on-demand construction of an object, and very fast access // thereafter (the cost is a few extra cycles). // NoDestructor makes accesses even faster by storing the object inline in // static storage. // // Note that: // * Since destructor is never called, the object lives on during program exit // and can be safely accessed by any threads that have not been joined. // * This static-in-a-function NoDestructor usage pattern should be preferred // to uses of gtl::LazyStaticPtr in new code. // // Also note that // static NoDestructor<NonPOD> ptr(whatever); // can safely replace // static NonPOD* ptr = new NonPOD(whatever); // or // static NonPOD obj(whatever); // at file-level scope when the safe static-in-a-function pattern is infeasible // to use for some good reason. // All three of the NonPOD patterns above suffer from the same issue that // initialization of that object happens non-thread-safely at // a globally-undefined point during initialization of static-storage objects, // but NoDestructor<> usage provides both the safety of having the object alive // during program exit sequence and the performance of not doing extra memory // dereference on access. // template <typename T> class NoDestructor { … }; } // namespace mediapipe #endif // MEDIAPIPE_DEPS_NO_DESTRUCTOR_H_