Feature #4328

export rb_thread_call_with_gvl()

Added by Eric Wong about 3 years ago. Updated over 1 year ago.

[ruby-core:34888]
Status:Closed
Priority:Normal
Assignee:Koichi Sasada
Category:core
Target version:1.9.3

Description

=begin
I think it is general enough to remain supported along
with the rest of the MRI C API, especially since
rbthreadblocking_region() exists and is supported.

It's useful for interacting with certain C libraries that expect a
user-supplied callback function so the extension can allocate a Ruby
object inside the callback.

It can also be easily made a no-op for Ruby implementations without a
GVL.
=end

0001-export-rb_thread_call_with_gvl.patch Magnifier - [PATCH] export rb_thread_call_with_gvl() (1.5 KB) Eric Wong, 01/27/2011 03:51 PM


Related issues

Related to ruby-trunk - Feature #5543: rb_thread_blocking_region() API is poorly designed Closed 11/02/2011

Associated revisions

Revision 32486
Added by Koichi Sasada almost 3 years ago

  • internal.h (rbthreadcallwithgvl, rbthreadcallwithoutgvl): make them visible as experimental C APIs. fixes Feature #4328.

History

#1 Updated by Usaku NAKAMURA about 3 years ago

  • Status changed from Open to Assigned
  • Assignee set to Koichi Sasada

=begin

=end

#2 Updated by Eric Wong almost 3 years ago

I should note that even Rubinius has this function in it's C API.

#3 Updated by Koichi Sasada almost 3 years ago

Hi,

As you can read in comment, this API is difficult to use. There are
some assumptions for caller. I'm not sure that these assumptions are
reasonable or not. This is why we don't put into public API.

BTW, the naming "withgvl" is reasonable for native English speakers?

(2011/01/27 15:51), Eric Wong wrote:

Feature #4328: export rbthreadcallwithgvl()
http://redmine.ruby-lang.org/issues/show/4328

Author: Eric Wong
Status: Open, Priority: Normal
Category: core, Target version: 1.9.3

I think it is general enough to remain supported along
with the rest of the MRI C API, especially since
rbthreadblocking_region() exists and is supported.

It's useful for interacting with certain C libraries that expect a
user-supplied callback function so the extension can allocate a Ruby
object inside the callback.

It can also be easily made a no-op for Ruby implementations without a
GVL.


http://redmine.ruby-lang.org

--
// SASADA Koichi at atdot dot net

#4 Updated by Eric Wong almost 3 years ago

SASADA Koichi ko1@atdot.net wrote:

Hi,

As you can read in comment, this API is difficult to use. There are
some assumptions for caller. I'm not sure that these assumptions are
reasonable or not. This is why we don't put into public API.

I think the assumptions and requirements for calling this function are
reasonable (and best of all, well-documented). The API isn't difficult
to me and the documentation is clear as to what is safe and what is not.

Threading APIs can always be tricky, but I think the C API for GVL is
a good one.

BTW, the naming "withgvl" is reasonable for native English speakers?

Yes.

Thank you for the response.

--
Eric Wong

#5 Updated by Koichi Sasada almost 3 years ago

Hi,

(2011/06/14 14:56), Eric Wong wrote:

I think the assumptions and requirements for calling this function are
reasonable (and best of all, well-documented). The API isn't difficult
to me and the documentation is clear as to what is safe and what is not.

Threading APIs can always be tricky, but I think the C API for GVL is
a good one.

I think a requirement "caller should be a Ruby thread" is difficult.

For example, external library calls registered callback in other native
threads (not ruby threads). If C extension programmer does not know
such specification of external library, (s)he would make and register a
callback function using this API. Finally, the Ruby code run on non
Ruby code. I'm afraid of such situation.

To avoid this situation, one solution is checking "the thread is really
Ruby thread or not" when rbthreadcallwithgvl() is called. This
check was already introduced into this API.

Other solution is making the non-ruby thread to ruby thread. I feel
necessity of such API, however, I need more consideration to implement it.

To limit to usage of rbthreadcallwithgvl() as "only blocking
function", former (current) solution is enough.

BTW, the naming "withgvl" is reasonable for native English speakers?

Yes.

Thank you. We keep this name.

Please discuss with me about naming of another "withgvl".
In gc.c, there are other "withgvl" functions.

  • negativesizeallocationerrorwith_gvl
  • gcwithgvl

    The functions are callback of rbthreadcallwithgvl().

    The meaning of "withgvl" in rbthreadcallwithgvl() is "acquire GVL
    and call passed function". However, above two functions use then name
    "*
    with_gvl" in different meaning (run in GVL acquired situation, only).

    Do you have good naming idea for them?

    // SASADA Koichi at atdot dot net

#6 Updated by Eric Wong almost 3 years ago

SASADA Koichi ko1@atdot.net wrote:

Hi,

(2011/06/14 14:56), Eric Wong wrote:

I think the assumptions and requirements for calling this function are
reasonable (and best of all, well-documented). The API isn't difficult
to me and the documentation is clear as to what is safe and what is not.

Threading APIs can always be tricky, but I think the C API for GVL is
a good one.

I think a requirement "caller should be a Ruby thread" is difficult.

For example, external library calls registered callback in other native
threads (not ruby threads). If C extension programmer does not know
such specification of external library, (s)he would make and register a
callback function using this API. Finally, the Ruby code run on non
Ruby code. I'm afraid of such situation.

To avoid this situation, one solution is checking "the thread is really
Ruby thread or not" when rbthreadcallwithgvl() is called. This
check was already introduced into this API.

Yup, I like this check. Most C libraries I've used with do not start
threads internally, so I don't think it's a big problem. I always
review code to all libraries I use so I don't hit surprises like this,
though many programmers do not.

Other solution is making the non-ruby thread to ruby thread. I feel
necessity of such API, however, I need more consideration to implement it.

This would be interesting, I look forward to it.

To limit to usage of rbthreadcallwithgvl() as "only blocking
function", former (current) solution is enough.

Yes, I strongly believe rbthreadcallwithgvl() is useful for many
general cases already.

BTW, the naming "withgvl" is reasonable for native English speakers?

Yes.

Thank you. We keep this name.

Please discuss with me about naming of another "withgvl".
In gc.c, there are other "withgvl" functions.

  • negativesizeallocationerrorwith_gvl
  • gcwithgvl

The functions are callback of rbthreadcallwithgvl().

The meaning of "withgvl" in rbthreadcallwithgvl() is "acquire GVL
and call passed function". However, above two functions use then name
"*
with_gvl" in different meaning (run in GVL acquired situation, only).

I agree, "*withgvl" having two meanings is confusing.

Do you have good naming idea for them?

Not sure, maybe "*ingvl"?

Or "ingvl*" as prefix since io.c already uses "maygvl" and "nogvl_" as
prefixes.

Maybe we should avoid "gvl" in the name completely for these two
functions. Most Ruby functions need GVL anyways and they don't have
"gvl" in the name.

--
Eric Wong

#7 Updated by Eric Hodel almost 3 years ago

On Jun 14, 2011, at 2:44 AM, Eric Wong wrote:

SASADA Koichi ko1@atdot.net wrote:

The meaning of "withgvl" in rbthreadcallwithgvl() is "acquire GVL
and call passed function". However, above two functions use then name
"*
with_gvl" in different meaning (run in GVL acquired situation, only).

I agree, "*withgvl" having two meanings is confusing.

Do you have good naming idea for them?

Not sure, maybe "*ingvl"?

"*ifgvl"?

Or "ingvl*" as prefix since io.c already uses "maygvl" and "nogvl_" as
prefixes.

Maybe we should avoid "gvl" in the name completely for these two
functions. Most Ruby functions need GVL anyways and they don't have
"gvl" in the name.

#8 Updated by Koichi Sasada almost 3 years ago

  • Status changed from Assigned to Closed
  • % Done changed from 0 to 100

This issue was solved with changeset r32486.
Eric, thank you for reporting this issue.
Your contribution to Ruby is greatly appreciated.
May Ruby be with you.


  • internal.h (rbthreadcallwithgvl, rbthreadcallwithoutgvl): make them visible as experimental C APIs. fixes Feature #4328.

#9 Updated by Eric Hodel almost 2 years ago

  • Description updated (diff)

I was going to use rbthreadcallwithgvl for #6612, but the declaration was moved to internal.h which is not exported and causes a warning when compiling zlib.c. Was this intentional? The current location seems to allow use by core ruby only.

To be usable by extensions the declaration should be in include/ruby/intern.h alongside rbthreadblocking_region.

#10 Updated by Eric Hodel almost 2 years ago

  • Status changed from Closed to Assigned

#11 Updated by Koichi Sasada over 1 year ago

  • Status changed from Assigned to Closed

Now we have include/ruby/thread.h: void rbthreadcallwithgvl(void *(func)(void *), void *data1);

Also available in: Atom PDF