General Purpose library for Freestanding C++ and POSIX systems
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

96 行
2.2 KiB

  1. #pragma once
  2. #include "gp/system/system.hpp"
  3. namespace gp{
  4. class simple_scheduling : public gp::scheduling_scheme {
  5. struct locked_circular_buffer {
  6. std::atomic_bool lock;
  7. gp::array<gp::topic_list::node_ptr, gp_config::limits::max_processes> processes;
  8. size_t read_idx = 0;
  9. size_t write_idx = 0;
  10. void push(gp::topic_list::node_ptr node) {
  11. bool t = true;
  12. bool f = false;
  13. while(not lock.compare_exchange_strong(f,t)){}
  14. {
  15. gp_config::assertion((write_idx + 1)%processes.size() != read_idx, "bad push to circular buffer");
  16. processes[write_idx] = node;
  17. write_idx=(write_idx+1)%processes.size();
  18. }
  19. while(not lock.compare_exchange_strong(t,f)){}
  20. }
  21. gp::topic_list::node_ptr pop() {
  22. bool t = true;
  23. bool f = false;
  24. gp::topic_list::node_ptr ret;
  25. while(not lock.compare_exchange_strong(f,t)){}
  26. {
  27. if(read_idx == write_idx) {
  28. ret = nullptr;
  29. } else {
  30. ret = processes[read_idx];
  31. read_idx=(read_idx+1)%processes.size();
  32. }
  33. }
  34. while(not lock.compare_exchange_strong(t,f)){}
  35. return ret;
  36. }
  37. };
  38. locked_circular_buffer running;
  39. locked_circular_buffer waiting;
  40. locked_circular_buffer to_clean;
  41. locked_circular_buffer naughty;
  42. system* sys = nullptr;
  43. public:
  44. simple_scheduling()
  45. {}
  46. virtual void link(system& value) {
  47. gp_config::assertion(!(sys), "Double linkage detected");
  48. sys = &value;
  49. sys->process_managers.emplace_back(*sys,0);
  50. }
  51. virtual gp::topic_list::node_ptr one(size_t) {
  52. auto v = running.pop();
  53. do{
  54. if(v) return v;
  55. v = running.pop();
  56. }while(true);
  57. }
  58. virtual void push(gp::topic_list::node_ptr node) {
  59. running.push(node);
  60. }
  61. virtual gp::topic_list::node_ptr next(size_t, gp::topic_list::node_ptr current) {
  62. switch(current->value->state) {
  63. case process_status::inactive:
  64. case process_status::running:
  65. running.push(current);
  66. break;
  67. case process_status::finished:
  68. to_clean.push(current);
  69. break;
  70. case process_status::zombie:
  71. naughty.push(current);
  72. break;
  73. case process_status::waiting:
  74. waiting.push(current);
  75. break;
  76. }
  77. return one(0);
  78. }
  79. virtual gp::scheduler& current_scheduler() {
  80. return sys->process_managers[0];
  81. }
  82. };
  83. }