1/*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15#ifndef SCOPE_GUARD_H
16#define SCOPE_GUARD_H
17
18#include <utility>
19
20namespace OHOS {
21namespace IntellVoiceUtils {
22template <typename Func>
23class ScopeGuard {
24public:
25    explicit ScopeGuard(Func &&f) : func_(std::forward<Func>(f)), active_(true)
26    {
27    }
28
29    ScopeGuard(ScopeGuard &&rhs) : func_(std::move(rhs.func_)), active_(rhs.active_)
30    {
31        rhs.Disable();
32    }
33
34    ~ScopeGuard()
35    {
36        if (active_) {
37            func_();
38        }
39    }
40
41    void Disable()
42    {
43        active_ = false;
44    }
45
46    bool Active() const
47    {
48        return active_;
49    }
50
51    void EarlyExit()
52    {
53        if (active_) {
54            func_();
55        }
56        active_ = false;
57    }
58private:
59    Func func_;
60    bool active_;
61    ScopeGuard() = delete;
62    ScopeGuard(const ScopeGuard &) = delete;
63    ScopeGuard &operator=(const ScopeGuard &) = delete;
64    ScopeGuard &operator=(ScopeGuard &&) = delete;
65};
66
67// tag dispatch
68struct ScopeGuardOnExit {};
69
70template <typename Func>
71inline ScopeGuard<Func> operator+(ScopeGuardOnExit, Func &&fn)
72{
73    return ScopeGuard<Func>(std::forward<Func>(fn));
74}
75}
76}
77
78/*
79  * ScopeGuard ensure the specified function which is created by ON_SCOPE_EXIT is executed no matter how the current
80  * scope exit.
81  * when use ON_SCOPE_EXIT macro, the format is:
82  * ON_SCOPE_EXIT {
83  * your code
84  * };
85*/
86#define ON_SCOPE_EXIT \
87    auto __onScopeGuardExit__ = OHOS::IntellVoiceUtils::ScopeGuardOnExit() + [&]()
88
89#define CANCEL_SCOPE_EXIT \
90    (__onScopeGuardExit__.Disable())
91
92#define EARLY_SCOPE_EXIT \
93    (__onScopeGuardExit__.EarlyExit())
94
95#define ON_SCOPE_EXIT_WITH_NAME(variable_name) \
96    auto variable_name = OHOS::IntellVoiceUtils::ScopeGuardOnExit() + [&]()
97
98#endif
99