defer.h 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
  2. // This source code is licensed under both the GPLv2 (found in the
  3. // COPYING file in the root directory) and Apache 2.0 License
  4. // (found in the LICENSE.Apache file in the root directory).
  5. #pragma once
  6. #include <functional>
  7. #include "rocksdb/rocksdb_namespace.h"
  8. namespace ROCKSDB_NAMESPACE {
  9. // Defers the execution of the provided function until the Defer
  10. // object goes out of scope.
  11. //
  12. // Usage example:
  13. //
  14. // Status DeferTest() {
  15. // Status s;
  16. // Defer defer([&s]() {
  17. // if (!s.ok()) {
  18. // // do cleanups ...
  19. // }
  20. // });
  21. // // do something ...
  22. // if (!s.ok()) return;
  23. // // do some other things ...
  24. // return s;
  25. // }
  26. //
  27. // The above code ensures that cleanups will always happen on returning.
  28. //
  29. // Without the help of Defer, you can
  30. // 1. every time when !s.ok(), do the cleanup;
  31. // 2. instead of returning when !s.ok(), continue the work only when s.ok(),
  32. // but sometimes, this might lead to nested blocks of "if (s.ok()) {...}".
  33. //
  34. // With the help of Defer, you can centralize the cleanup logic inside the
  35. // lambda passed to Defer, and you can return immediately on failure when
  36. // necessary.
  37. class Defer final {
  38. public:
  39. explicit Defer(std::function<void()>&& fn) : fn_(std::move(fn)) {}
  40. ~Defer() { fn_(); }
  41. // Disallow copy.
  42. Defer(const Defer&) = delete;
  43. Defer& operator=(const Defer&) = delete;
  44. private:
  45. std::function<void()> fn_;
  46. };
  47. // An RAII utility object that saves the current value of an object so that
  48. // it can be overwritten, and restores it to the saved value when the
  49. // SaveAndRestore object goes out of scope.
  50. template <typename T>
  51. class SaveAndRestore {
  52. public:
  53. // obj is non-null pointer to value to be saved and later restored.
  54. explicit SaveAndRestore(T* obj) : obj_(obj), saved_(*obj) {}
  55. // new_value is stored in *obj
  56. SaveAndRestore(T* obj, const T& new_value)
  57. : obj_(obj), saved_(std::move(*obj)) {
  58. *obj = new_value;
  59. }
  60. SaveAndRestore(T* obj, T&& new_value) : obj_(obj), saved_(std::move(*obj)) {
  61. *obj = std::move(new_value);
  62. }
  63. ~SaveAndRestore() { *obj_ = std::move(saved_); }
  64. // No copies
  65. SaveAndRestore(const SaveAndRestore&) = delete;
  66. SaveAndRestore& operator=(const SaveAndRestore&) = delete;
  67. private:
  68. T* const obj_;
  69. T saved_;
  70. };
  71. } // namespace ROCKSDB_NAMESPACE