Added correct copy constructor. Surprisingly, the incorrect default copy constructor...
[videolink.git] / auto_handle.hpp
1 // Copyright 2005 Ben Hutchings <ben@decadent.org.uk>.
2 // See the file "COPYING" for licence details.
3
4 #ifndef INC_AUTO_HANDLE_HPP
5 #define INC_AUTO_HANDLE_HPP
6
7 // Like auto_ptr, but for arbitrary "handle" types.
8 // The parameters are:
9 // - handle_type: the type of the raw handle to be wrapped
10 // - closer_type: a function object type whose operator() takes a raw handle
11 //                and closes it (or does nothing if it is a null handle)
12 // - factory_type: a function object type whose operator() returns a null
13 //                 handle
14
15 template<typename handle_type, typename closer_type, typename factory_type>
16 class auto_handle_ref;
17
18 template<typename handle_type, typename closer_type, typename factory_type>
19 class auto_handle
20     // Use inheritance so we can benefit from the empty base optimisation
21     : private closer_type, private factory_type
22 {
23     typedef auto_handle_ref<handle_type, closer_type, factory_type> ref_type;
24 public:
25     auto_handle()
26             : handle_(factory_type::operator()())
27         {}
28     explicit auto_handle(handle_type handle)
29             : handle_(handle)
30         {}
31     auto_handle(auto_handle & other)
32             : handle_(other.release())
33         {}
34     auto_handle(ref_type other)
35             : handle_(other.release())
36         {}
37     auto_handle & operator=(auto_handle & other)
38         {
39             reset(other.release());
40         }
41     ~auto_handle()
42         {
43             reset();
44         }
45     handle_type get() const
46         {
47             return handle_;
48         }
49     handle_type release()
50         {
51             handle_type handle(handle_);
52             handle_ = factory_type::operator()();
53             return handle;
54         }
55     void reset()
56         {
57             closer_type::operator()(handle_);
58             handle_ = factory_type::operator()();
59         }
60     void reset(handle_type handle)
61         {
62             closer_type::operator()(handle_);
63             handle_ = handle;
64         }
65     operator ref_type()
66         {
67             return ref_type(*this);
68         }
69 private:
70     handle_type handle_;
71 };
72
73 template<typename handle_type, typename closer_type, typename factory_type>
74 class auto_handle_ref
75 {
76     typedef auto_handle<handle_type, closer_type, factory_type> target_type;
77 public:
78     explicit auto_handle_ref(target_type & target)
79             : target_(target)
80         {}
81     handle_type release()
82         {
83             return target_.release();
84         }
85 private:
86     target_type & target_;
87 };
88
89 #endif // !defined(INC_AUTO_HANDLE_HPP)