cleanup.hpp
2.81 KB
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