| 3047 | } |
| 3048 | |
| 3049 | target_state |
| 3050 | execute_direct_impl (action a, |
| 3051 | const target& ct, |
| 3052 | size_t start_count, |
| 3053 | atomic_count* task_count) |
| 3054 | { |
| 3055 | context& ctx (ct.ctx); |
| 3056 | |
| 3057 | target& t (const_cast<target&> (ct)); // MT-aware. |
| 3058 | target::opstate& s (t[a]); |
| 3059 | |
| 3060 | // Similar logic to execute_impl() above. |
| 3061 | // |
| 3062 | size_t tc (ctx.count_applied ()); |
| 3063 | |
| 3064 | size_t exec (ctx.count_executed ()); |
| 3065 | size_t busy (ctx.count_busy ()); |
| 3066 | |
| 3067 | optional<target_state> r; |
| 3068 | if (s.task_count.compare_exchange_strong ( |
| 3069 | tc, |
| 3070 | busy, |
| 3071 | memory_order_acq_rel, // Synchronize on success. |
| 3072 | memory_order_acquire)) // Synchronize on failure. |
| 3073 | { |
| 3074 | if (s.state == target_state::unknown) |
| 3075 | { |
| 3076 | if (task_count == nullptr) |
| 3077 | r = execute_impl (a, t); |
| 3078 | else |
| 3079 | { |
| 3080 | if (ctx.sched->async (start_count, |
| 3081 | *task_count, |
| 3082 | [a] (const diag_frame* ds, target& t) |
| 3083 | { |
| 3084 | diag_frame::stack_guard dsg (ds); |
| 3085 | execute_impl (a, t); |
| 3086 | }, |
| 3087 | diag_frame::stack (), |
| 3088 | ref (t))) |
| 3089 | return target_state::unknown; // Queued. |
| 3090 | |
| 3091 | // Executed synchronously, fall through. |
| 3092 | } |
| 3093 | } |
| 3094 | else |
| 3095 | { |
| 3096 | assert (s.state == target_state::unchanged || |
| 3097 | s.state == target_state::failed); |
| 3098 | |
| 3099 | r = s.state == target_state::unchanged && t.is_a<dir> () |
| 3100 | ? execute_recipe (a, t, nullptr /* recipe */) |
| 3101 | : s.state; |
| 3102 | |
| 3103 | s.task_count.store (exec, memory_order_release); |
| 3104 | ctx.sched->resume (s.task_count); |
| 3105 | } |
| 3106 | } |
nothing calls this directly
no test coverage detected