[#106939] [Ruby master Bug#18455] `IO#close` has poor performance and difficult to understand semantics. — "ioquatix (Samuel Williams)" <noreply@...>

Issue #18455 has been reported by ioquatix (Samuel Williams).

10 messages 2022/01/01

[#106977] [Ruby master Feature#18461] closures are capturing unused variables — "bughit (bug hit)" <noreply@...>

Issue #18461 has been reported by bughit (bug hit).

12 messages 2022/01/05

[#106994] [Ruby master Feature#18462] Proposal to merge WASI based WebAssembly support — "katei (Yuta Saito)" <noreply@...>

Issue #18462 has been reported by katei (Yuta Saito).

8 messages 2022/01/07

[#106996] [Ruby master Feature#18463] Random number generation with xoshiro — "bbrklm (Benson Muite)" <noreply@...>

Issue #18463 has been reported by bbrklm (Benson Muite).

8 messages 2022/01/07

[#107005] [Ruby master Bug#18464] RUBY_INTERNAL_EVENT_NEWOBJ tracepoint causes an interpreter crash when combined with Ractors — "kjtsanaktsidis (KJ Tsanaktsidis)" <noreply@...>

Issue #18464 has been reported by kjtsanaktsidis (KJ Tsanaktsidis).

14 messages 2022/01/08

[#107008] [Ruby master Bug#18465] Make `IO#write` atomic. — "ioquatix (Samuel Williams)" <noreply@...>

Issue #18465 has been reported by ioquatix (Samuel Williams).

16 messages 2022/01/09

[#107073] [Ruby master Feature#18481] Porting YJIT to Rust (request for feedback) — "maximecb (Maxime Chevalier-Boisvert)" <noreply@...>

Issue #18481 has been reported by maximecb (Maxime Chevalier-Boisvert).

26 messages 2022/01/12

[#107106] [Ruby master Bug#18487] Kernel#binding behaves differently depending on implementation language of items on the stack — "alanwu (Alan Wu)" <noreply@...>

Issue #18487 has been reported by alanwu (Alan Wu).

11 messages 2022/01/13

[#107190] [Ruby master Feature#18498] Introduce a public WeakKeysMap that compares by equality — "byroot (Jean Boussier)" <noreply@...>

Issue #18498 has been reported by byroot (Jean Boussier).

17 messages 2022/01/19

[#107203] [Ruby master Bug#18501] [BUG] try to mark T_NONE object in RubyVM::InstructionSequence. load_from_binary — "byroot (Jean Boussier)" <noreply@...>

Issue #18501 has been reported by byroot (Jean Boussier).

8 messages 2022/01/20

[#107204] [Ruby master Bug#18502] Make ruby-2.7.5 on Solaris 10 ld.so.1: gcc: fatal: libintl.so.8: open failed: No such file or directory — "dklein (Dmitri Klein)" <noreply@...>

Issue #18502 has been reported by dklein (Dmitri Klein).

8 messages 2022/01/20

[#107275] [Ruby master Bug#18512] MacOS 12.1 Monterey Bug — "oucl5976@... (Paul Liu)" <noreply@...>

Issue #18512 has been reported by oucl5976@gmail.com (Paul Liu).

9 messages 2022/01/25

[#107291] [Ruby master Bug#18518] NoMemoryError + [FATAL] failed to allocate memory for twice 1 << large — "Eregon (Benoit Daloze)" <noreply@...>

Issue #18518 has been reported by Eregon (Benoit Daloze).

12 messages 2022/01/26

[#107310] [Ruby master Bug#18555] Running "bundle exec middleman server" on M1 Mac gives [BUG] Bus Error at 0x0000000104b04000 — "anthonyaykut (Anthony Aykut)" <noreply@...>

Issue #18555 has been reported by anthonyaykut (Anthony Aykut).

13 messages 2022/01/28

[#107346] [Ruby master Misc#18557] DevMeeting-2022-02-17 — "mame (Yusuke Endoh)" <noreply@...>

Issue #18557 has been reported by mame (Yusuke Endoh).

18 messages 2022/01/29

[#107392] [Ruby master Bug#18560] "Compaction isn't available on this platform" error running PG test suite on ppc64le — "vo.x (Vit Ondruch)" <noreply@...>

Issue #18560 has been reported by vo.x (Vit Ondruch).

7 messages 2022/01/31

[ruby-core:107089] [Ruby master Bug#18482] Fiber can not disable scheduler

From: "ioquatix (Samuel Williams)" <noreply@...>
Date: 2022-01-12 20:56:32 UTC
List: ruby-core #107089
Issue #18482 has been updated by ioquatix (Samuel Williams).

Status changed from Open to Rejected

Did you read the documentation?

https://rubyapi.org/3.1/o/fiber#method-c-new

----------------------------------------
Bug #18482: Fiber can not disable scheduler
https://bugs.ruby-lang.org/issues/18482#change-95934

* Author: jakit (Jakit Liang)
* Status: Rejected
* Priority: Normal
* Assignee: ioquatix (Samuel Williams)
* ruby -v: ruby 3.1.0p0 (2021-12-25 revision fb4df44d16) [arm64-darwin20]
* Backport: 2.6: UNKNOWN, 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN
----------------------------------------
class Fiber can not disable scheduler with it's parameter.

When parameter is false:

```
require 'fiber'
require 'io/nonblock'

class SimpleScheduler
  def initialize
    @readable = {}
    @writable = {}
    @waiting = {}
    @ready = []
    @blocking = 0
    @urgent = IO.pipe
  end

  def run
    while @readable.any? or @writable.any? or @waiting.any? or @blocking.positive? or @ready.any?
      readable, writable = IO.select(@readable.keys + [@urgent.first], @writable.keys, [], 0)

      readable&.each do |io|
        if fiber = @readable.delete(io)
          fiber.resume
        end
      end

      writable&.each do |io|
        if fiber = @writable.delete(io)
          fiber.resume
        end
      end

      @waiting.keys.each do |fiber|
        if current_time > @waiting[fiber]
          @waiting.delete(fiber)
          fiber.resume
        end
      end

      ready, @ready = @ready, []
      ready.each do |fiber|
        fiber.resume
      end
    end
  end

  def io_wait(io, events, timeout)
    unless (events & IO::READABLE).zero?
      @readable[io] = Fiber.current
    end
    unless (events & IO::WRITABLE).zero?
      @writable[io] = Fiber.current
    end

    Fiber.yield
    return events
  end

  def kernel_sleep(duration = nil)
    block(:sleep, duration)
    return true
  end

  def block(blocker, timeout = nil)
    if timeout
      @waiting[Fiber.current] = current_time + timeout
      begin
        Fiber.yield
      ensure
        @waiting.delete(Fiber.current)
      end
    else
      @blocking += 1
      begin
        Fiber.yield
      ensure
        @blocking -= 1
      end
    end
  end

  def unblock(blocker, fiber)
    @ready << fiber
    io = @urgent.last
    io.write_nonblock('.')
  end

  def close
    run
    @urgent.each(&:close)
    @urgent = nil
  end

  private
  def current_time
    Process.clock_gettime(Process::CLOCK_MONOTONIC)
  end
end

scheduler = SimpleScheduler.new
Fiber.set_scheduler(scheduler)

puts "Go to sleep!"

f = Fiber.new(false) do
  puts "Going to sleep"
  sleep(1)
  puts "I slept well"
end

f.resume

puts "Wakey-wakey, sleepyhead"
```

Result:

```
Go to sleep!
Going to sleep
Wakey-wakey, sleepyhead
I slept well
```

And when parameter is true:

```
require 'fiber'
require 'io/nonblock'

class SimpleScheduler
  def initialize
    @readable = {}
    @writable = {}
    @waiting = {}
    @ready = []
    @blocking = 0
    @urgent = IO.pipe
  end

  def run
    while @readable.any? or @writable.any? or @waiting.any? or @blocking.positive? or @ready.any?
      readable, writable = IO.select(@readable.keys + [@urgent.first], @writable.keys, [], 0)

      readable&.each do |io|
        if fiber = @readable.delete(io)
          fiber.resume
        end
      end

      writable&.each do |io|
        if fiber = @writable.delete(io)
          fiber.resume
        end
      end

      @waiting.keys.each do |fiber|
        if current_time > @waiting[fiber]
          @waiting.delete(fiber)
          fiber.resume
        end
      end

      ready, @ready = @ready, []
      ready.each do |fiber|
        fiber.resume
      end
    end
  end

  def io_wait(io, events, timeout)
    unless (events & IO::READABLE).zero?
      @readable[io] = Fiber.current
    end
    unless (events & IO::WRITABLE).zero?
      @writable[io] = Fiber.current
    end

    Fiber.yield
    return events
  end

  def kernel_sleep(duration = nil)
    block(:sleep, duration)
    return true
  end

  def block(blocker, timeout = nil)
    if timeout
      @waiting[Fiber.current] = current_time + timeout
      begin
        Fiber.yield
      ensure
        @waiting.delete(Fiber.current)
      end
    else
      @blocking += 1
      begin
        Fiber.yield
      ensure
        @blocking -= 1
      end
    end
  end

  def unblock(blocker, fiber)
    @ready << fiber
    io = @urgent.last
    io.write_nonblock('.')
  end

  def close
    run
    @urgent.each(&:close)
    @urgent = nil
  end

  private
  def current_time
    Process.clock_gettime(Process::CLOCK_MONOTONIC)
  end
end

scheduler = SimpleScheduler.new
Fiber.set_scheduler(scheduler)

puts "Go to sleep!"

f = Fiber.new(true) do
  puts "Going to sleep"
  sleep(1)
  puts "I slept well"
end

f.resume

puts "Wakey-wakey, sleepyhead"
```

Result (was still the same):

```
Go to sleep!
Going to sleep
Wakey-wakey, sleepyhead
I slept well
```

While make the set_scheduler line commented:

```
scheduler = SimpleScheduler.new
# Fiber.set_scheduler(scheduler) // Here is commented

puts "Go to sleep!"

f = Fiber.new(false) do
  puts "Going to sleep"
  sleep(1)
  puts "I slept well"
end
```

Result is right:

```
Go to sleep!
Going to sleep
I slept well
Wakey-wakey, sleepyhead
```

Maybe in some situation.

I wrote my gem without Scheduler. But user defined its Scheduler for his or her logic code.

It will break the sequence of Fiber which was needed for my gem.

Also, using Fiber in the Enumerator situation will be broke down too:

```
db.with_each_row_of_result(sql_stmt) do |row|
  yield row
end
```

[[https://blog.appsignal.com/2018/11/27/ruby-magic-fibers-and-enumerators-in-ruby.html]]

It will break the sequence of db rows when doing enum such like python's generator.

========================

Also, another question is that I saw something was talk in:

https://bugs.ruby-lang.org/issues/16786

I think there would be a better way to improve this.

You can see, in c++, std::thread is easy to create and join a new thread.

If someone make a std::thread::scheduler into STL of C++.

And let user to implement its std::thread::handler to implement the virtual methods (interface or callback) to use it.

And std::thread::scheduler holds an independent thread pool which is not separated.

What do you think about this std::thread::scheduler?

What about make a golang's GMP into std::thread or std::coroutine.

Why not STL do that?

Why not STL let std::thread become a self-scheduled module?

Otherwise, the sense of implement Scheduler as async await may be a good idea, but there has module named Ractor can solve it.

Maybe:

```
IO.async do |readable, writeble|
  if readable
    # code
  end
end
```

======================

In other programming language, like Python.

Python never let it's Generator mixed with async IO but add `async` syntax:

```
async def coro():      # a coroutine function
    await smth()

async def asyncgen():  # an asynchronous generator function
    await smth()
    yield 42
```

Python goes in a right way. Methods can run async and something like IO.write() can put in it.

```
async def async_write(data):      # a coroutine function
    IO.write(data)

async def send(message):  # an asynchronous generator function
    await async_write("hello " + message)
    yield 1
```

https://www.python.org/dev/peps/pep-0525/#id10

Also, JavaScript use `async` syntax to identify the `async` procedure.

Above that, I think the Fiber.scheduler may not be a good idea. Because Ractor is here.

Ractor can run methods async and we can put IO.write in it and make it "async".




-- 
https://bugs.ruby-lang.org/

Unsubscribe: <mailto:ruby-core-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>

In This Thread

Prev Next