Advertisement
Guest User

Untitled

a guest
Sep 21st, 2019
124
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.25 KB | None | 0 0
  1. use std::thread;
  2.  
  3. trait System {}
  4.  
  5. struct SystemEntry {
  6. /// The system to execute
  7. system: Box<dyn System>
  8.  
  9. /// The max value for the gate
  10. gate_max: usize
  11.  
  12. /// The gate blocking a system's execution till it completes
  13. gate: usize,
  14. }
  15.  
  16. impl SystemEntry {
  17. /// Decrement the gate toward zero
  18. #[inline]
  19. pub fn decrement(&mut self) {
  20. self.gate.saturating_sub(1);
  21. }
  22.  
  23. /// Reset the gate for another pass
  24. #[inline]
  25. pub fn reset(&mut self) {
  26. self.gate = self.gate_max;
  27. }
  28.  
  29. /// Whether the system entry is ready for execution
  30. #[inline]
  31. pub fn can_execute(&self) -> bool {
  32. self.gate == 0
  33. }
  34. }
  35.  
  36. /// A node in the system graph
  37. ///
  38. /// ### Safety
  39. /// This struct is highly unsafe and only intended for use inside `SystemGraph`
  40. struct Node {
  41. /// Pointer to the system this node owns
  42. system: *mut SystemEntry,
  43.  
  44. /// A pointer to the list of child pointers for this node. Set to null if the node has no children
  45. child_ptr: *mut Node,
  46.  
  47. /// The number of child pointers in this node. Set to 0 if the node has no children
  48. child_len: usize
  49. }
  50.  
  51. impl Node {
  52. /// Execute the system this entry points to
  53. ///
  54. /// ### Safety
  55. /// Assumes that the underlying pointer is valid
  56. #[inline]
  57. pub unsafe fn execute(&self){
  58. (*self.system).system.execute();
  59. }
  60.  
  61. /// Get the child pointers of this node
  62. ///
  63. /// ### Safety
  64. /// Assumes that `child_ptr` is valid and that there are
  65. /// at least `child_len - 1` pointers in memory after it
  66. pub unsafe fn children(&self) -> &[*mut Node] {
  67. slice::from_raw_parts(
  68. self.child_ptr as *const Node,
  69. self.child_len
  70. )
  71. }
  72.  
  73. }
  74.  
  75. /// A DAG describing how systems in the ecs relate and their execution order.
  76. ///
  77. /// ### Remarks
  78. /// This is a special system that lives outside the usual ecs execution order
  79. struct SystemGraph {
  80. /// The list of systems in this graph
  81. systems: Vec<SystemEntry>,
  82.  
  83. /// The nodes describing the graph
  84. nodes: Vec<Node>
  85.  
  86. /// The child pointers for the nodes of this graph
  87. child_ptrs: Vec<*mut Node>,
  88. }
  89.  
  90. impl SystemGraph {
  91. /// Get the root node of the graph. The first node is always an empty logical node
  92. /// that points to all the children in the graph
  93. ///
  94. /// ### Safety
  95. /// The node pointer in this node is NOT valid and should not be dereferenced
  96. pub fn root(&self) -> &Node {
  97. &self.nodes[0]
  98. }
  99. }
  100.  
  101. struct ActiveJob {
  102. /// The node this job belongs to
  103. node: *mut Node,
  104.  
  105. /// The completion handle for this job
  106. completion_handle: JobHandle
  107. }
  108.  
  109. impl ActiveJob {
  110. /// Create a new active job entry for a given node and handle
  111. ///
  112. /// ### Safety
  113. /// Assumes that the node is a valid pointer and will remain valid till the job
  114. /// is completed
  115. pub fn new(node: *mut Node, handle: JobHandle) -> Self {
  116. Self {
  117. node: node,
  118. completion_handle: handle
  119. }
  120. }
  121.  
  122. /// Check if the job has completed, if so
  123. #[inline]
  124. pub fn completed(&self) -> bool {
  125. self.completion_handle.is_complete()
  126. }
  127. }
  128.  
  129. /// The executor that handles executing all ECS systems as jobs
  130. struct EcsExecutor {
  131. /// The dag describing the system execution order
  132. dag: SystemGraph,
  133.  
  134. /// The list of entries pending execution
  135. pending: Vec<*mut SystemEntry>,
  136.  
  137. /// The jobs currently in flight
  138. in_flight: Vec<ActiveJob>,
  139. }
  140.  
  141. impl EcsExecutor {
  142. fn execute(&mut self) {
  143. unsafe {
  144. // Queue up the root tasks and begin execution
  145. let root = self.dag.root();
  146. for child in root.children() {
  147. // TODO: Execute the child
  148. let handle = execute_child();
  149.  
  150. self.in_flight.push(ActiveJob::(child, handle));
  151. }
  152.  
  153. // Continue to dispatch tasks till the entire dag has been traversed
  154. while !self.in_flight.is_empty() {
  155. // Check if any in flight jobs have completed
  156. for job in self.in_flight.iter() {
  157. if !job.completed() {
  158. continue;
  159. }
  160.  
  161. let children = (*job.node).children();
  162. for child in children.iter() {
  163. (*child).gate.saturating_sub(1);
  164.  
  165. // The last prerequisite for the child has completed
  166. // begin executing the child
  167. if (*child).gate == 0 {
  168. // TODO: Execute the child
  169. let handle = execute_child();
  170.  
  171. self.in_flight.push(ActiveJob::(child, handle));
  172. }
  173. }
  174.  
  175. self.in_flight.remove(job);
  176. }
  177.  
  178. // Yield while the job threads process the active work
  179. thread::yield_now();
  180. }
  181.  
  182. // At this point `in_flight` should be empty and all systems have finished executing
  183.  
  184. // TODO: Join on the remaining tasks
  185. }
  186. }
  187. }
  188.  
  189. fn main() {
  190.  
  191. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement