Project

General

Profile

Feature #18411

Updated by ioquatix (Samuel Williams) almost 3 years ago

When implementing pure-ruby IO scheduler, we may need to invoke some Ruby IO operations without entering the scheduler. 

 ```ruby 
 def io_write(fiber, io, buffer, length) 
   offset = 0 
  
   while length > 0 
     # From offset until the end: 
     chunk = buffer.to_str(offset, length) 
     case result = io.write_nonblock(chunk, exception: false) 
     when :wait_readable 
       self.io_wait(fiber, io, IO::READABLE) 
     when :wait_writable 
       self.io_wait(fiber, io, IO::WRITABLE) 
     else 
       offset += result 
       length -= result 
     end 
   end 
  
   return offset 
 end 
 ``` 

 There are some cases where even in this code `read_nonblock` can invoke fiber scheduler creating infinite recursion. 

 Therefore, I propose to introduce `Fiber.blocking{...}` which has almost identical implementation to `Fiber.new(blocking: true) {}.resume`. 

 In the above code, we change the line: 

 ``` 
     case result = io.write_nonblock(chunk, exception: false) 
 ``` 

 to 

 ``` 
     case result = Fiber.blocking{io.write_nonblock(chunk, exception: false)} 
 ``` 

 This ensures that `write_nonblock` can never enter the scheduler again.

Back