@@ -63,8 +63,10 @@ typedef enum {
63
63
struct rb_fiber_scheduler_blocking_operation {
64
64
void * (* function )(void * );
65
65
void * data ;
66
+
66
67
rb_unblock_function_t * unblock_function ;
67
68
void * data2 ;
69
+
68
70
int flags ;
69
71
struct rb_fiber_scheduler_blocking_operation_state * state ;
70
72
@@ -208,7 +210,10 @@ rb_fiber_scheduler_blocking_operation_execute(rb_fiber_scheduler_blocking_operat
208
210
return -1 ; // Invalid blocking operation
209
211
}
210
212
211
- // Atomically check if we can transition from QUEUED to EXECUTING
213
+ // Resolve sentinel values for unblock_function and data2:
214
+ rb_thread_resolve_unblock_function (& blocking_operation -> unblock_function , & blocking_operation -> data2 , GET_THREAD ());
215
+
216
+ // Atomically check if we can transition from QUEUED to EXECUTING
212
217
rb_atomic_t expected = RB_FIBER_SCHEDULER_BLOCKING_OPERATION_STATUS_QUEUED ;
213
218
if (RUBY_ATOMIC_CAS (blocking_operation -> status , expected , RB_FIBER_SCHEDULER_BLOCKING_OPERATION_STATUS_EXECUTING ) != expected ) {
214
219
// Already cancelled or in wrong state
@@ -1124,25 +1129,33 @@ rb_fiber_scheduler_blocking_operation_cancel(rb_fiber_scheduler_blocking_operati
1124
1129
1125
1130
rb_atomic_t current_state = RUBY_ATOMIC_LOAD (blocking_operation -> status );
1126
1131
1127
- switch (current_state ) {
1132
+ switch (current_state ) {
1128
1133
case RB_FIBER_SCHEDULER_BLOCKING_OPERATION_STATUS_QUEUED :
1129
- // Work hasn't started - just mark as cancelled
1134
+ // Work hasn't started - just mark as cancelled:
1130
1135
if (RUBY_ATOMIC_CAS (blocking_operation -> status , current_state , RB_FIBER_SCHEDULER_BLOCKING_OPERATION_STATUS_CANCELLED ) == current_state ) {
1131
- return 0 ; // Successfully cancelled before execution
1136
+ // Successfully cancelled before execution:
1137
+ return 0 ;
1132
1138
}
1133
1139
// Fall through if state changed between load and CAS
1134
1140
1135
1141
case RB_FIBER_SCHEDULER_BLOCKING_OPERATION_STATUS_EXECUTING :
1136
1142
// Work is running - mark cancelled AND call unblock function
1137
- RUBY_ATOMIC_SET (blocking_operation -> status , RB_FIBER_SCHEDULER_BLOCKING_OPERATION_STATUS_CANCELLED );
1138
- if (blocking_operation -> unblock_function ) {
1143
+ if (RUBY_ATOMIC_CAS (blocking_operation -> status , current_state , RB_FIBER_SCHEDULER_BLOCKING_OPERATION_STATUS_CANCELLED ) != current_state ) {
1144
+ // State changed between load and CAS - operation may have completed:
1145
+ return 0 ;
1146
+ }
1147
+ // Otherwise, we successfully marked it as cancelled, so we can call the unblock function:
1148
+ rb_unblock_function_t * unblock_function = blocking_operation -> unblock_function ;
1149
+ if (unblock_function ) {
1150
+ RUBY_ASSERT (unblock_function != (rb_unblock_function_t * )-1 && "unblock_function is still sentinel value -1, should have been resolved earlier" );
1139
1151
blocking_operation -> unblock_function (blocking_operation -> data2 );
1140
1152
}
1141
- return 1 ; // Cancelled during execution (unblock function called)
1153
+ // Cancelled during execution (unblock function called):
1154
+ return 1 ;
1142
1155
1143
1156
case RB_FIBER_SCHEDULER_BLOCKING_OPERATION_STATUS_COMPLETED :
1144
1157
case RB_FIBER_SCHEDULER_BLOCKING_OPERATION_STATUS_CANCELLED :
1145
- // Already finished or cancelled
1158
+ // Already finished or cancelled:
1146
1159
return 0 ;
1147
1160
}
1148
1161
0 commit comments