lifetime.h 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. // This file is part of Desktop App Toolkit,
  2. // a set of libraries for developing nice desktop applications.
  3. //
  4. // For license and copyright information please follow this link:
  5. // https://github.com/desktop-app/legal/blob/master/LEGAL
  6. //
  7. #pragma once
  8. #include "base/unique_function.h"
  9. #include <vector>
  10. namespace rpl {
  11. namespace details {
  12. template <typename Type>
  13. inline Type take(Type &value) {
  14. return std::exchange(value, Type{});
  15. }
  16. } // namespace details
  17. class lifetime {
  18. public:
  19. lifetime() = default;
  20. lifetime(lifetime &&other);
  21. lifetime &operator=(lifetime &&other);
  22. ~lifetime() { destroy(); }
  23. template <typename Destroy, typename = decltype(std::declval<Destroy>()())>
  24. lifetime(Destroy &&destroy);
  25. explicit operator bool() const { return !_callbacks.empty(); }
  26. template <typename Destroy, typename = decltype(std::declval<Destroy>()())>
  27. void add(Destroy &&destroy);
  28. void add(lifetime &&other);
  29. void destroy();
  30. void release();
  31. template <typename Type, typename... Args>
  32. Type *make_state(Args&& ...args) {
  33. const auto result = new Type(std::forward<Args>(args)...);
  34. add([=] {
  35. static_assert(sizeof(Type) > 0, "Can't delete unknown type.");
  36. delete result;
  37. });
  38. return result;
  39. }
  40. private:
  41. std::vector<base::unique_function<void()>> _callbacks;
  42. };
  43. inline lifetime::lifetime(lifetime &&other)
  44. : _callbacks(details::take(other._callbacks)) {
  45. }
  46. inline lifetime &lifetime::operator=(lifetime &&other) {
  47. std::swap(_callbacks, other._callbacks);
  48. other.destroy();
  49. return *this;
  50. }
  51. template <typename Destroy, typename>
  52. inline lifetime::lifetime(Destroy &&destroy) {
  53. _callbacks.emplace_back(std::forward<Destroy>(destroy));
  54. }
  55. template <typename Destroy, typename>
  56. inline void lifetime::add(Destroy &&destroy) {
  57. _callbacks.emplace_back(std::forward<Destroy>(destroy));
  58. }
  59. inline void lifetime::add(lifetime &&other) {
  60. auto callbacks = details::take(other._callbacks);
  61. _callbacks.insert(
  62. _callbacks.end(),
  63. std::make_move_iterator(callbacks.begin()),
  64. std::make_move_iterator(callbacks.end()));
  65. }
  66. inline void lifetime::destroy() {
  67. auto callbacks = details::take(_callbacks);
  68. for (auto i = callbacks.rbegin(), e = callbacks.rend(); i != e; ++i) {
  69. (*i)();
  70. }
  71. }
  72. inline void lifetime::release() {
  73. _callbacks.clear();
  74. }
  75. } // namespace rpl