-
Notifications
You must be signed in to change notification settings - Fork 5.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Summary: The following targets were moved to folly/futures: ``` //folly/experimental:cleanup //folly/experimental/test:cleanup_test ``` `arc f` was applied This is a codemod. It was automatically generated and will be landed once it is approved and tests are passing in sandcastle. You have been added as a reviewer by Sentinel or Butterfly. p:ad_meclen.folly Reviewed By: ot Differential Revision: D58024166 fbshipit-source-id: 65701585d243ec55be1799f8b1e2c490a6bfab65
- Loading branch information
1 parent
c10a7c1
commit ade5b95
Showing
7 changed files
with
205 additions
and
178 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,177 @@ | ||
/* | ||
* Copyright (c) Meta Platforms, Inc. and affiliates. | ||
* | ||
* 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 <memory> | ||
#include <mutex> | ||
|
||
#include <glog/logging.h> | ||
|
||
#include <folly/futures/Future.h> | ||
|
||
namespace folly { | ||
|
||
// Structured Async Cleanup | ||
// | ||
|
||
// Structured Async Cleanup - traits | ||
// | ||
|
||
namespace detail { | ||
struct cleanup_fn { | ||
template < | ||
class T, | ||
class R = decltype(std::declval<T>().cleanup()), | ||
std::enable_if_t<std::is_same_v<R, folly::SemiFuture<folly::Unit>>, int> = | ||
0> | ||
R operator()(T&& t) const { | ||
return ((T&&)t).cleanup(); | ||
} | ||
}; | ||
} // namespace detail | ||
|
||
template <class T> | ||
constexpr bool is_cleanup_v = folly::is_invocable_v<detail::cleanup_fn, T>; | ||
|
||
template <typename T> | ||
using is_cleanup = std::bool_constant<is_cleanup_v<T>>; | ||
|
||
// Structured Async Cleanup | ||
// | ||
// This helps compose a task with async cleanup | ||
// The task result is stored until cleanup completes and is then produced | ||
// The cleanup task is not allowed to fail. | ||
// | ||
// This can be used with collectAll to combine multiple async resources | ||
// | ||
// ensureCleanupAfterTask(collectAll(a.run(), b.run()), collectAll(a.cleanup(), | ||
// b.cleanup())).wait(); | ||
// | ||
template <typename T> | ||
folly::SemiFuture<T> ensureCleanupAfterTask( | ||
folly::SemiFuture<T> task, folly::SemiFuture<folly::Unit> cleanup) { | ||
return folly::makeSemiFuture() | ||
.deferValue([task_ = std::move(task)](folly::Unit) mutable { | ||
return std::move(task_); | ||
}) | ||
.defer([cleanup_ = std::move(cleanup)](folly::Try<T> taskResult) mutable { | ||
return std::move(cleanup_).defer( | ||
[taskResult_ = std::move(taskResult)](folly::Try<folly::Unit> t) { | ||
if (t.hasException()) { | ||
terminate_with<std::logic_error>("cleanup must not throw"); | ||
} | ||
return std::move(taskResult_).value(); | ||
}); | ||
}); | ||
} | ||
|
||
// Structured Async Cleanup | ||
// | ||
// This implementation is a base class that collects a set of cleanup tasks | ||
// and runs them in reverse order. | ||
// | ||
// A class derived from Cleanup | ||
// - only allows cleanup to be run once | ||
// - is required to complete cleanup before running the destructor | ||
// - *should not* run cleanup tasks. Running the cleanup task should be | ||
// delegated to the owner of the derived class | ||
// - *should not* be owned by a shared_ptr. Cleanup is intended to remove | ||
// shared ownership. | ||
// | ||
class Cleanup { | ||
public: | ||
Cleanup() : safe_to_destruct_(false), cleanup_(folly::makeSemiFuture()) {} | ||
~Cleanup() { | ||
if (!safe_to_destruct_) { | ||
LOG(FATAL) << "Cleanup must complete before it is destructed."; | ||
} | ||
} | ||
|
||
// Returns: a SemiFuture that, just like destructors, sequences the cleanup | ||
// tasks added in reverse of the order they were added. | ||
// | ||
// calls to cleanup() do not mutate state. The returned SemiFuture, once | ||
// it has been given an executor, does mutate state and must not overlap with | ||
// any calls to addCleanup(). | ||
// | ||
folly::SemiFuture<folly::Unit> cleanup() { | ||
return folly::makeSemiFuture() | ||
.deferValue([this](folly::Unit) { | ||
if (!cleanup_.valid()) { | ||
LOG(FATAL) << "cleanup already run - cleanup task invalid."; | ||
} | ||
return std::move(cleanup_); | ||
}) | ||
.defer([this](folly::Try<folly::Unit> t) { | ||
if (t.hasException()) { | ||
LOG(FATAL) << "Cleanup actions must be noexcept."; | ||
} | ||
this->safe_to_destruct_ = true; | ||
}); | ||
} | ||
|
||
protected: | ||
// includes the provided SemiFuture under the scope of this. | ||
// | ||
// when the cleanup() for this started it will get this SemiFuture first. | ||
// | ||
// order matters, just like destructors, cleanup tasks will be run in reverse | ||
// of the order they were added. | ||
// | ||
// all gets will use the Executor provided to the SemiFuture returned by | ||
// cleanup() | ||
// | ||
// calls to addCleanup() must not overlap with each other and must not overlap | ||
// with a running SemiFuture returned from addCleanup(). | ||
// | ||
void addCleanup(folly::SemiFuture<folly::Unit> c) { | ||
if (!cleanup_.valid()) { | ||
LOG(FATAL) | ||
<< "Cleanup::addCleanup must not be called after Cleanup::cleanup."; | ||
} | ||
cleanup_ = std::move(c).deferValue( | ||
[nested = std::move(cleanup_)](folly::Unit) mutable { | ||
return std::move(nested); | ||
}); | ||
} | ||
|
||
// includes the provided model of Cleanup under the scope of this | ||
// | ||
// when the cleanup() for this started it will cleanup this first. | ||
// | ||
// order matters, just like destructors, cleanup tasks will be run in reverse | ||
// of the order they were added. | ||
// | ||
// all gets will use the Executor provided to the SemiFuture returned by | ||
// cleanup() | ||
// | ||
// calls to addCleanup() must not overlap with each other and must not overlap | ||
// with a running SemiFuture returned from addCleanup(). | ||
// | ||
template < | ||
class OtherCleanup, | ||
std::enable_if_t<is_cleanup_v<OtherCleanup>, int> = 0> | ||
void addCleanup(OtherCleanup&& c) { | ||
addCleanup(((OtherCleanup&&)c).cleanup()); | ||
} | ||
|
||
private: | ||
bool safe_to_destruct_; | ||
folly::SemiFuture<folly::Unit> cleanup_; | ||
}; | ||
|
||
} // namespace folly |
Oops, something went wrong.