BackgroundAction.h 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. #pragma once
  2. #include <AK/Function.h>
  3. #include <AK/NonnullRefPtr.h>
  4. #include <AK/Optional.h>
  5. #include <AK/Queue.h>
  6. #include <AK/RefCounted.h>
  7. #include <LibCore/CEventLoop.h>
  8. #include <LibCore/CObject.h>
  9. #include <LibThread/Lock.h>
  10. #include <LibThread/Thread.h>
  11. namespace LibThread {
  12. template<typename Result>
  13. class BackgroundAction;
  14. class BackgroundActionBase {
  15. template<typename Result>
  16. friend class BackgroundAction;
  17. private:
  18. BackgroundActionBase() {}
  19. static Lockable<Queue<Function<void()>>>& all_actions();
  20. static Thread& background_thread();
  21. };
  22. template<typename Result>
  23. class BackgroundAction final : public CObject
  24. , public RefCounted<BackgroundAction<Result>>
  25. , private BackgroundActionBase {
  26. C_OBJECT(BackgroundAction);
  27. public:
  28. static NonnullRefPtr<BackgroundAction<Result>> create(
  29. Function<Result()> action,
  30. Function<void(Result)> on_complete = nullptr
  31. )
  32. {
  33. return adopt(*new BackgroundAction(move(action), move(on_complete)));
  34. }
  35. virtual ~BackgroundAction() {}
  36. private:
  37. BackgroundAction(Function<Result()> action, Function<void(Result)> on_complete)
  38. : CObject(background_thread())
  39. , m_action(move(action))
  40. , m_on_complete(move(on_complete))
  41. {
  42. LOCKER(all_actions().lock());
  43. this->ref();
  44. all_actions().resource().enqueue([this] {
  45. m_result = m_action();
  46. if (m_on_complete) {
  47. CEventLoop::main().post_event(*this, make<CDeferredInvocationEvent>([this](CObject&) {
  48. m_on_complete(m_result.release_value());
  49. this->deref();
  50. }));
  51. CEventLoop::main().wake();
  52. } else
  53. this->deref();
  54. });
  55. }
  56. Function<Result()> m_action;
  57. Function<void(Result)> m_on_complete;
  58. Optional<Result> m_result;
  59. };
  60. }