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