// // Copyright 2016 Pixar // // Licensed under the Apache License, Version 2.0 (the "Apache License") // with the following modification; you may not use this file except in // compliance with the Apache License and the following modification to it: // Section 6. Trademarks. is deleted and replaced with: // // 6. Trademarks. This License does not grant permission to use the trade // names, trademarks, service marks, or product names of the Licensor // and its affiliates, except as required to comply with Section 4(c) of // the License and to reproduce the content of the NOTICE file. // // You may obtain a copy of the Apache License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the Apache License with the above modification is // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // #ifndef PXR_BASE_TF_SCOPED_H #define PXR_BASE_TF_SCOPED_H #include "pxr/pxr.h" #include PXR_NAMESPACE_OPEN_SCOPE /// \class TfScoped /// \ingroup group_tf_Multithreading /// /// Execute code on exiting scope. /// /// A \c TfScoped executes code when destroyed. It's useful when cleanup code /// should be executed when exiting the scope because it gets executed no /// matter how the scope is exited (e.g. normal execution, return, exceptions, /// etc). /// /// \code /// int func(bool x) { /// TfScoped scope(cleanup); /// return func2(x); // call cleanup after calling func2 /// } /// \endcode /// template > class TfScoped { TfScoped(TfScoped const &) = delete; TfScoped &operator=(TfScoped const &) = delete; public: /// The type of the function executed on destruction. typedef T Procedure; /// Execute \p leave when this object goes out of scope. explicit TfScoped(const Procedure& leave) : _onExit(leave) { } ~TfScoped() { _onExit(); } private: // Can't put these on the heap. No implementation needed. static void *operator new(::std::size_t size); private: Procedure _onExit; }; // Specialization of TfScoped for member functions. template class TfScoped { TfScoped(TfScoped const &) = delete; TfScoped &operator=(TfScoped const &) = delete; public: /// The type of the function executed on destruction. typedef void (T::*Procedure)(); /// Execute \p leave on \p obj when this object goes out of scope. explicit TfScoped(T* obj, const Procedure& leave) : _obj(obj), _onExit(leave) { } ~TfScoped() { (_obj->*_onExit)(); } private: // Can't put these on the heap. No implementation needed. static void *operator new(::std::size_t size); private: T* _obj; Procedure _onExit; }; // Specialization of TfScoped for functions taking one pointer argument. template class TfScoped { TfScoped(TfScoped const &) = delete; TfScoped &operator=(TfScoped const &) = delete; public: /// The type of the function executed on destruction. typedef void (*Procedure)(T*); /// Execute \p leave, passing \p obj, when this object goes out of scope. explicit TfScoped(const Procedure& leave, T* obj) : _obj(obj), _onExit(leave) { } ~TfScoped() { _onExit(_obj); } private: // Can't put these on the heap. No implementation needed. static void *operator new(::std::size_t size); private: T* _obj; Procedure _onExit; }; /// \class TfScopedVar /// /// Reset variable on exiting scope. /// /// A \c TfScopedVar sets a variable to a value when created then restores its /// original value when destroyed. For example: /// /// \code /// int func(bool x) { /// TfScopedVar scope(x, true); // set x to true /// return func2(x); // restore x after calling func2 /// } /// \endcode template class TfScopedVar { TfScopedVar(TfScopedVar const &) = delete; TfScopedVar &operator=(TfScopedVar const &) = delete; public: /// Set/reset variable /// /// Sets \p x to \p val immediately and restores its old value when this /// goes out of scope. explicit TfScopedVar(T& x, const T& val) : _x(&x), _old(x) { x = val; } ~TfScopedVar() { *_x = _old; } private: // Can't put these on the heap. No implementation needed. static void *operator new(::std::size_t size); private: T* _x; T _old; }; /// \class TfScopedAutoVar /// /// Reset variable on exiting scope. /// /// A \c TfScopedAutoVar sets a variable to a value when created then restores /// its original value when destroyed. /// /// For example: /// \code /// int func(bool x) { /// TfScopedAutoVar scope(x, true); // set x to true /// return func2(x); // restore x after calling func2 /// } /// \endcode /// /// This differs from \c TfScopedVar in that it's not a template class, the /// value type is deduced automatically and it allocates memory on the heap. /// If performance is critical or memory must not be allocated then use \c /// TfScopedVar instead. /// /// \see TfScopedVar class TfScopedAutoVar { TfScopedAutoVar(TfScopedAutoVar const &) = delete; TfScopedAutoVar &operator=(TfScopedAutoVar const &) = delete; public: /// Set/reset variable /// /// Sets \p x to \p val immediately and restores its old value when this /// goes out of scope. template explicit TfScopedAutoVar(T& x, const T& val) : _scope(std::bind(&TfScopedAutoVar::_Set, &x, x)) { x = val; } private: // Restore value function template static void _Set(T* x, const T& val) { *x = val; } // Can't put these on the heap. No implementation needed. static void *operator new(::std::size_t size); private: TfScoped<> _scope; }; PXR_NAMESPACE_CLOSE_SCOPE #endif // PXR_BASE_TF_SCOPED_H