Skip to content

Commit

Permalink
[C++] Add RAII util (defer) to auto cleanup / close resources after e…
Browse files Browse the repository at this point in the history
…xiting the scope (#369)
  • Loading branch information
eddyxu committed Dec 13, 2022
1 parent a771a88 commit 5a766dc
Show file tree
Hide file tree
Showing 6 changed files with 129 additions and 0 deletions.
1 change: 1 addition & 0 deletions cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ set(lance_objects
$<TARGET_OBJECTS:format>
$<TARGET_OBJECTS:io>
$<TARGET_OBJECTS:lance_io_exec>
$<TARGET_OBJECTS:lance_util>
)

add_subdirectory(src)
Expand Down
1 change: 1 addition & 0 deletions cpp/src/lance/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ add_subdirectory(arrow)
add_subdirectory(encodings)
add_subdirectory(format)
add_subdirectory(io)
add_subdirectory(util)

if (CMAKE_BUILD_TYPE STREQUAL Debug)
add_subdirectory(testing)
Expand Down
17 changes: 17 additions & 0 deletions cpp/src/lance/util/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Copyright 2022 Lance Authors
#
# Licensed 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.

add_library(lance_util OBJECT defer.h defer.cc)

add_lance_test(defer_test)
29 changes: 29 additions & 0 deletions cpp/src/lance/util/defer.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright 2022 Lance Authors
//
// Licensed 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.

#include "lance/util/defer.h"

#include <utility>

namespace lance::util {

Defer::Defer(std::function<void()>&& cb) : callback_(std::move(cb)) {}

Defer::Defer(Defer&& other) : callback_(std::move(other.callback_)){};

Defer::~Defer() {
callback_();
}

} // namespace lance::util
51 changes: 51 additions & 0 deletions cpp/src/lance/util/defer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright 2022 Lance Authors
//
// Licensed 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 <functional>

namespace lance::util {

/// Defer the execution of a lambda function until out of scope.
///
/// It offers RAII to general function calls. It is modeled after Golang's Defer statement.
///
/// \example
///
/// void WriteData(const std::string& path) {
/// auto fd = fopen(path.c_str());
/// Defer auto_closer([&]() { fclose(fd); }
/// for (int i = 0; i < 10; i++) {
/// fprint(fd, "line: %d\n", i);
/// }
/// // fd is closed when out of scope.
/// }
///
class Defer {
public:
Defer() = delete;

explicit Defer(std::function<void(void)>&& cb);

/// Move constructor.
Defer(Defer&& other);

~Defer();

private:
std::function<void()> callback_;
};

} // namespace lance::util
30 changes: 30 additions & 0 deletions cpp/src/lance/util/defer_test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright 2022 Lance Authors
//
// Licensed 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.

#include "lance/util/defer.h"

#include <catch2/catch_test_macros.hpp>

TEST_CASE("Test Call Defer") {
int i = 100;

{
lance::util::Defer incr([&i]() { i += 200; });

CHECK(i == 100);
i += 20;
}

CHECK(i == 320);
}

0 comments on commit 5a766dc

Please sign in to comment.