• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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