blob: ab087aeb2fbd29ff0f7f06796ccf9c5bd68d8637 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
#pragma once
#include <type_traits>
#include <utility>
namespace doris::cloud {
// A simple RAII class to defer the execution of a function until the end of the
// scope.
template <typename Fn>
requires std::is_invocable_v<Fn>
class DeferFn {
public:
DeferFn(Fn &&fn) : fn_(std::move(fn)) {}
DeferFn(const DeferFn &) = delete;
DeferFn &operator=(const DeferFn &) = delete;
~DeferFn() { fn_(); }
private:
Fn fn_;
};
} // namespace doris::cloud
// A macro to create a DeferFn object that will execute the given function
// when it goes out of scope. This is useful for cleanup tasks or finalization
// actions that should always run, regardless of how the scope is exited (e.g.
// normal return, exception thrown, etc.).
//
// Usage:
// DORIS_CLOUD_DEFER {
// // Code to execute at the end of the scope
// };
//
#define DORIS_CLOUD_DEFER_IMPL(line, counter) \
::doris::cloud::DeferFn defer_fn_##line##_##counter = [&]()
#define DORIS_CLOUD_DEFER_EXPAND(line, counter) \
DORIS_CLOUD_DEFER_IMPL(line, counter)
#define DORIS_CLOUD_DEFER DORIS_CLOUD_DEFER_EXPAND(__LINE__, __COUNTER__)
// A macro to create a DeferFn object that will execute the given function
// with additional parameters when it goes out of scope. This is useful for
// cleanup tasks or finalization actions that should always run, regardless of
// how the scope is exited (e.g. normal return, exception thrown, etc.).
//
// Usage:
// DORIS_CLOUD_DEFER_COPY(param1, param2) {
// // Code to execute at the end of the scope, using param1 and param2
// };
//
// Note: The parameters are captured by copy, so they can be used safely, for
// example,
// void foo(int &a, int &b) {
// DORIS_CLOUD_DEFER_COPY(a, b) mutable {
// a += 1;
// b *= 2;
// };
// }
//
// int x = 1, y = 2;
// foo(x, y);
// assert(x == 1 && y == 2);
//
// The captured parameters are passed by value, so they modifications inside the
// deferred function do not affect the original variables outside the scope, or
// the modifications after the definition of the defer function will not affect
// the captured values.
#define DORIS_CLOUD_DEFER_COPY_IMPL(line, counter, ...) \
::doris::cloud::DeferFn defer_fn_##line##_##counter = [&, __VA_ARGS__ ]()
#define DORIS_CLOUD_DEFER_COPY_EXPAND(line, counter, ...) \
DORIS_CLOUD_DEFER_COPY_IMPL(line, counter, __VA_ARGS__)
#define DORIS_CLOUD_DEFER_COPY(...) \
DORIS_CLOUD_DEFER_COPY_EXPAND(__LINE__, __COUNTER__, __VA_ARGS__)