General Purpose library for Freestanding C++ and POSIX systems
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

81 рядки
1.5 KiB

  1. #pragma once
  2. #include "gp/vfs/process_data.hpp"
  3. #include <atomic>
  4. class runqueue{
  5. struct node{
  6. std::atomic_bool is_locked;
  7. gp::process_data* value;
  8. std::atomic<struct node*> next;
  9. bool try_acquire() noexcept {
  10. bool expected = false;
  11. return !(is_locked.compare_exchange_strong(expected, true));
  12. }
  13. void release() noexcept {
  14. is_locked.store(false);
  15. }
  16. };
  17. using node_ptr = struct node*;
  18. using node_ptr_rep = std::atomic<struct node*>;
  19. struct topic_list{
  20. node_ptr_rep start;
  21. node_ptr_rep end;
  22. // NODES ARE ACQUIRED ON POP
  23. node_ptr try_pop() {
  24. auto ptr = start.load();
  25. if(!ptr) return nullptr;
  26. if(ptr->try_acquire()) {
  27. auto replace = ptr->next.load();
  28. auto expected = ptr;
  29. if(end.load() == ptr) {
  30. end.store(nullptr);
  31. }
  32. if(start.compare_exchange_strong(expected, replace)) {
  33. return ptr;
  34. } else {
  35. return nullptr;
  36. }
  37. } else {
  38. return nullptr;
  39. }
  40. }
  41. // ONLY PUSH ACQUIRED NODES
  42. bool try_push(node_ptr node) {
  43. auto ed = end.load();
  44. if(ed) {
  45. if(ed->try_acquire()) {
  46. node->next.store(ed);
  47. if(end.compare_exchange_strong(ed, node)) {
  48. ed->release();
  49. node->release();
  50. return true;
  51. } else {
  52. ed->release();
  53. node->release();
  54. return false;
  55. }
  56. } else return false;
  57. } else {
  58. if(end.compare_exchange_strong(ed, node)) {
  59. start.store(node);
  60. node->release();
  61. return true;
  62. } else {
  63. return false;
  64. }
  65. }
  66. }
  67. };
  68. topic_list running;
  69. topic_list waiting;
  70. };