implement tcmalloc::Cleanup

This is similar, but slightly less featureful than
absl::{Make,}Cleanup.
This commit is contained in:
Aliaksey Kandratsenka 2024-02-17 14:20:04 -05:00
parent dec85dcc03
commit 5f92c0616a
3 changed files with 81 additions and 18 deletions

75
src/base/cleanup.h Normal file
View File

@ -0,0 +1,75 @@
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
* Copyright (c) 2024, gperftools Contributors
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef BASE_CLEANUP_H_
#define BASE_CLEANUP_H_
#include "config.h"
#include <type_traits>
namespace tcmalloc {
// Cleanup represents a piece of work (like closing file descriptor)
// when it's scope ends. Anything that can be invoked, and returns
// null can be used. Most typical callback is lambda. This is somewhat
// similar to Go's defer statement.
//
// This is direct equivalent of abseil's absl::Cleanup, except ours
// cannot be moved from (use std::optional if you need this) and
// cannot be canceled. And is much simpler as a result.
//
// Note, we don't offer equivalent of absl::MakeCleanup. Instead, we
// encourage use of C++17 class template argument deduction. I.e. use
// like this:
//
// tcmalloc::Cleanup cleanup([&] () { fclose(something); });
template <typename Callback>
class Cleanup {
public:
static_assert(std::is_same<std::invoke_result_t<Callback>, void>::value,
"Cleanup callback must return void");
explicit Cleanup(Callback callback) : callback_(std::move(callback)) {}
// We don't support copying or moving those
Cleanup(const Cleanup& other) = delete;
Cleanup& operator=(const Cleanup& other) = delete;
~Cleanup() {
callback_();
}
private:
Callback callback_;
};
} // namespace tcmalloc
#endif // BASE_CLEANUP_H_

View File

@ -59,6 +59,7 @@
#include <atomic>
#include "base/basictypes.h"
#include "base/cleanup.h"
#include "base/logging.h"
#ifndef CLONE_UNTRACED
@ -108,22 +109,6 @@ private:
int fd_;
};
template <typename Body>
struct SimpleCleanup {
const Body body;
explicit SimpleCleanup(const Body& body) : body(body) {}
~SimpleCleanup() {
body();
}
};
template <typename Body>
SimpleCleanup<Body> MakeSimpleCleanup(const Body& body) {
return SimpleCleanup<Body>{body};
};
} // namespace
/* Synchronous signals that should not be blocked while in the lister thread.
@ -561,7 +546,7 @@ int TCMalloc_ListAllProcessThreads(void *parameter,
SetPTracerSetup ptracer_setup;
auto cleanup = MakeSimpleCleanup([&] () {
tcmalloc::Cleanup cleanup([&] () {
int old_errno = errno;
if (need_sigprocmask) {

View File

@ -85,6 +85,7 @@
#include <string>
#include <vector>
#include "base/cleanup.h"
#include "base/logging.h"
#include "gperftools/malloc_hook.h"
#include "gperftools/malloc_extension.h"
@ -1169,6 +1170,9 @@ static ATTRIBUTE_NOINLINE void TestNewOOMHandling() {
std::new_handler old = std::set_new_handler(test_new_handler);
get_test_sys_alloc()->simulate_oom = true;
tcmalloc::Cleanup restore_oom([] () {
get_test_sys_alloc()->simulate_oom = false;
});
ASSERT_EQ(saw_new_handler_runs, 0);
@ -1182,7 +1186,6 @@ static ATTRIBUTE_NOINLINE void TestNewOOMHandling() {
ASSERT_GE(saw_new_handler_runs, 1);
get_test_sys_alloc()->simulate_oom = false;
std::set_new_handler(old);
}
#endif // !DEBUGALLOCATION