1 /*============================================================================= 2 Copyright (c) 2010.2017 Daniel James 3 4 Use, modification and distribution is subject to the Boost Software 5 License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at 6 http://www.boost.org/LICENSE_1_0.txt) 7 =============================================================================*/ 8 9 #if !defined(BOOST_SPIRIT_QUICKBOOK_CLEANUP_HPP) 10 #define BOOST_SPIRIT_QUICKBOOK_CLEANUP_HPP 11 12 namespace quickbook 13 { 14 // This header defines a class which will store pointers and delete what 15 // they're pointing to on destruction. Add an object, and you can use 16 // pointers and references to it during the cleanup object's lifespan. 17 // 18 // Example use: 19 // 20 // struct wonder_struct { 21 // quickbook::cleanup cleanup; 22 // }; 23 // 24 // wonder_struct w; 25 // thing& t = w.cleanup.add(new thing()); 26 // 27 // Can now use 't' until the wonder_struct is destroyed. 28 // 29 // Anything added to cleanup is destroyed in reverse order, so it 30 // should be okay for an object to depend on something that was previously 31 // added. 32 33 namespace detail 34 { 35 struct cleanup_node; 36 } 37 struct cleanup 38 { cleanupquickbook::cleanup39 cleanup() : first_(0) {} 40 ~cleanup(); 41 template <typename T> T& add(T*); 42 43 private: 44 detail::cleanup_node* first_; 45 46 cleanup& operator=(cleanup const&); 47 cleanup(cleanup const&); 48 }; 49 50 namespace detail 51 { delete_impl(void * ptr)52 template <typename T> void delete_impl(void* ptr) 53 { 54 delete static_cast<T*>(ptr); 55 } 56 57 struct cleanup_node 58 { 59 void* ptr_; 60 void (*del_)(void*); 61 cleanup_node* next_; 62 cleanup_nodequickbook::detail::cleanup_node63 cleanup_node() : ptr_(0), del_(0), next_(0) {} cleanup_nodequickbook::detail::cleanup_node64 cleanup_node(void* ptr, void (*del)(void* x)) 65 : ptr_(ptr), del_(del), next_(0) 66 { 67 } ~cleanup_nodequickbook::detail::cleanup_node68 ~cleanup_node() 69 { 70 if (ptr_) del_(ptr_); 71 } 72 move_assignquickbook::detail::cleanup_node73 void move_assign(cleanup_node& n) 74 { 75 ptr_ = n.ptr_; 76 del_ = n.del_; 77 n.ptr_ = 0; 78 n.del_ = 0; 79 } 80 81 private: 82 cleanup_node(cleanup_node const&); 83 cleanup_node& operator=(cleanup_node const&); 84 }; 85 } 86 add(T * ptr)87 template <typename T> T& cleanup::add(T* ptr) 88 { 89 detail::cleanup_node n(ptr, &detail::delete_impl<T>); 90 detail::cleanup_node* n2 = new detail::cleanup_node(); 91 n2->next_ = first_; 92 first_ = n2; 93 n2->move_assign(n); 94 return *ptr; 95 } 96 ~cleanup()97 inline cleanup::~cleanup() 98 { 99 while (first_) { 100 detail::cleanup_node* to_delete = first_; 101 first_ = first_->next_; 102 delete to_delete; 103 } 104 } 105 } 106 107 #endif 108