General Purpose library for Freestanding C++ and POSIX systems
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

75 lines
1.4 KiB

  1. #pragma once
  2. #include "gp/vfs/process_data.hpp"
  3. #include <atomic>
  4. namespace gp {
  5. struct topic_list{
  6. struct node{
  7. std::atomic_bool is_locked;
  8. gp::process_data* value;
  9. std::atomic<struct node*> next;
  10. bool try_acquire() noexcept {
  11. bool expected = false;
  12. return !(is_locked.compare_exchange_strong(expected, true));
  13. }
  14. void release() noexcept {
  15. is_locked.store(false);
  16. }
  17. };
  18. using node_ptr = struct node*;
  19. using node_ptr_rep = std::atomic<struct node*>;
  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. // RELEASE WHEN NO LONGER IN USE
  43. bool try_push(node_ptr node) {
  44. auto ed = end.load();
  45. if(ed) {
  46. if(ed->try_acquire()) {
  47. node->next.store(ed);
  48. if(end.compare_exchange_strong(ed, node)) {
  49. ed->release();
  50. return true;
  51. } else {
  52. ed->release();
  53. return false;
  54. }
  55. } else return false;
  56. } else {
  57. if(end.compare_exchange_strong(ed, node)) {
  58. start.store(node);
  59. return true;
  60. } else {
  61. return false;
  62. }
  63. }
  64. }
  65. };
  66. }