BackgroundAction.cpp 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  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. #include <AK/Queue.h>
  8. #include <LibThreading/BackgroundAction.h>
  9. #include <LibThreading/Lock.h>
  10. #include <LibThreading/Thread.h>
  11. #include <unistd.h>
  12. static Threading::Lockable<Queue<Function<void()>>>* s_all_actions;
  13. static Threading::Thread* s_background_thread;
  14. static int s_notify_pipe_fds[2];
  15. static intptr_t background_thread_func()
  16. {
  17. while (true) {
  18. char buffer[1];
  19. auto nread = read(s_notify_pipe_fds[0], buffer, sizeof(buffer));
  20. if (nread < 0) {
  21. perror("read");
  22. _exit(1);
  23. }
  24. Vector<Function<void()>> work_items;
  25. {
  26. Threading::Locker locker(s_all_actions->lock());
  27. while (!s_all_actions->resource().is_empty()) {
  28. work_items.append(s_all_actions->resource().dequeue());
  29. }
  30. }
  31. for (auto& work_item : work_items)
  32. work_item();
  33. }
  34. VERIFY_NOT_REACHED();
  35. }
  36. static void init()
  37. {
  38. if (pipe(s_notify_pipe_fds) < 0) {
  39. perror("pipe");
  40. _exit(1);
  41. }
  42. s_all_actions = new Threading::Lockable<Queue<Function<void()>>>();
  43. s_background_thread = &Threading::Thread::construct(background_thread_func).leak_ref();
  44. s_background_thread->set_name("Background thread");
  45. s_background_thread->start();
  46. }
  47. Threading::Thread& Threading::BackgroundActionBase::background_thread()
  48. {
  49. if (s_background_thread == nullptr)
  50. init();
  51. return *s_background_thread;
  52. }
  53. void Threading::BackgroundActionBase::enqueue_work(Function<void()> work)
  54. {
  55. if (s_all_actions == nullptr)
  56. init();
  57. Locker locker(s_all_actions->lock());
  58. s_all_actions->resource().enqueue(move(work));
  59. char ch = 'x';
  60. if (write(s_notify_pipe_fds[1], &ch, sizeof(ch)) < 0) {
  61. perror("write");
  62. _exit(1);
  63. }
  64. }