Blame view

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