]> git.sesse.net Git - casparcg/blob - common/scope_exit.h
#281
[casparcg] / common / scope_exit.h
1 #pragma once
2
3 #include "exception/exceptions.h"
4
5 #include <functional>
6
7 namespace caspar {
8
9 namespace detail 
10 {
11     template<typename T>
12     class scope_exit
13     {
14                 scope_exit(const scope_exit&);
15                 scope_exit& operator=(const scope_exit&);
16     public:         
17
18                 template<typename T2>
19         explicit scope_exit(T2&& func) 
20                         : func_(std::forward<T2>(func))
21                         , valid_(true)
22                 {
23                 }
24                 
25                 scope_exit(scope_exit&& other)
26                         : func_(std::move(other.v))
27                         , valid_(std::move(other.valid_))
28                 {
29                         other.valid_ = false;
30                 }
31
32                 scope_exit& operator=(scope_exit&& other)
33                 {
34                         func_  = std::move(other.func_);
35                         valid_ = std::move(other.valid_);
36
37                         other.valid_ = false;
38
39                         return *this;
40                 }
41
42         ~scope_exit()
43                 {
44                         try
45                         {
46                                 if(valid_)
47                                         func_();
48                         }
49                         catch(...)
50                         {
51                                 if(!std::uncaught_exception()) 
52                                         throw;
53                                 else
54                                         CASPAR_LOG_CURRENT_EXCEPTION();
55                         }
56                 }
57     private:
58         T func_;
59                 bool valid_;
60     };          
61         
62         class scope_exit_helper {};
63
64         template <typename T>
65         scope_exit<typename std::decay<T>::type> operator+(scope_exit_helper, T&& exitScope)
66         {
67                 return scope_exit<typename std::decay<T>::type>(std::forward<T>(exitScope));
68         }
69 }
70
71 #define _CASPAR_EXIT_SCOPE_LINENAME_CAT(name, line) name##line
72 #define _CASPAR_EXIT_SCOPE_LINENAME(name, line) _CASPAR_EXIT_SCOPE_LINENAME_CAT(name, line)
73 #define CASPAR_SCOPE_EXIT auto _CASPAR_EXIT_SCOPE_LINENAME(EXIT, __LINE__) = ::caspar::detail::scope_exit_helper() + [&]() mutable
74
75 }