BackgroundAction.h 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. /*
  2. * Copyright (c) 2019-2020, Sergey Bugaev <bugaevc@serenityos.org>
  3. * Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #pragma once
  8. #include <AK/Function.h>
  9. #include <AK/NonnullRefPtr.h>
  10. #include <AK/Optional.h>
  11. #include <AK/Queue.h>
  12. #include <LibCore/Event.h>
  13. #include <LibCore/EventLoop.h>
  14. #include <LibCore/Object.h>
  15. #include <LibThreading/Thread.h>
  16. namespace Threading {
  17. template<typename Result>
  18. class BackgroundAction;
  19. class BackgroundActionBase {
  20. template<typename Result>
  21. friend class BackgroundAction;
  22. private:
  23. BackgroundActionBase() { }
  24. static void enqueue_work(Function<void()>);
  25. static Thread& background_thread();
  26. };
  27. template<typename Result>
  28. class BackgroundAction final : public Core::Object
  29. , private BackgroundActionBase {
  30. C_OBJECT(BackgroundAction);
  31. public:
  32. static NonnullRefPtr<BackgroundAction<Result>> create(
  33. Function<Result(BackgroundAction&)> action,
  34. Function<void(Result)> on_complete = nullptr)
  35. {
  36. return adopt_ref(*new BackgroundAction(move(action), move(on_complete)));
  37. }
  38. void cancel()
  39. {
  40. m_cancelled = true;
  41. }
  42. bool is_cancelled() const
  43. {
  44. return m_cancelled;
  45. }
  46. virtual ~BackgroundAction() { }
  47. private:
  48. BackgroundAction(Function<Result(BackgroundAction&)> action, Function<void(Result)> on_complete)
  49. : Core::Object(&background_thread())
  50. , m_action(move(action))
  51. , m_on_complete(move(on_complete))
  52. {
  53. enqueue_work([this] {
  54. m_result = m_action(*this);
  55. if (m_on_complete) {
  56. Core::EventLoop::current().post_event(*this, make<Core::DeferredInvocationEvent>([this, result = m_result.release_value()](auto&) {
  57. m_on_complete(result);
  58. this->remove_from_parent();
  59. }));
  60. Core::EventLoop::wake();
  61. } else {
  62. this->remove_from_parent();
  63. }
  64. });
  65. }
  66. bool m_cancelled { false };
  67. Function<Result(BackgroundAction&)> m_action;
  68. Function<void(Result)> m_on_complete;
  69. Optional<Result> m_result;
  70. };
  71. }