BackgroundAction.h 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. /*
  2. * Copyright (c) 2019-2020, Sergey Bugaev <bugaevc@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/Function.h>
  8. #include <AK/NonnullRefPtr.h>
  9. #include <AK/Optional.h>
  10. #include <AK/Queue.h>
  11. #include <LibCore/Event.h>
  12. #include <LibCore/EventLoop.h>
  13. #include <LibCore/Object.h>
  14. #include <LibThreading/Lock.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 Lockable<Queue<Function<void()>>>& all_actions();
  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()> action,
  34. Function<void(Result)> on_complete = nullptr)
  35. {
  36. return adopt_ref(*new BackgroundAction(move(action), move(on_complete)));
  37. }
  38. virtual ~BackgroundAction() { }
  39. private:
  40. BackgroundAction(Function<Result()> action, Function<void(Result)> on_complete)
  41. : Core::Object(&background_thread())
  42. , m_action(move(action))
  43. , m_on_complete(move(on_complete))
  44. {
  45. Locker locker(all_actions().lock());
  46. all_actions().resource().enqueue([this] {
  47. m_result = m_action();
  48. if (m_on_complete) {
  49. Core::EventLoop::current().post_event(*this, make<Core::DeferredInvocationEvent>([this](auto&) {
  50. m_on_complete(m_result.release_value());
  51. this->remove_from_parent();
  52. }));
  53. Core::EventLoop::wake();
  54. } else {
  55. this->remove_from_parent();
  56. }
  57. });
  58. }
  59. Function<Result()> m_action;
  60. Function<void(Result)> m_on_complete;
  61. Optional<Result> m_result;
  62. };
  63. }