When is it necessary to declare mutable VALUEs in Ruby C extensions?

I cannot find much documentation when it would be advisable to declare VALUE as volatile in Ruby extensions in order to avoid premature garbage collection in used objects.

Here is what I have learned so far. Can anyone fill in the blanks?

If volatile does not need to be used:

  • in C ++ objects (because they are never on the stack?)
  • in C / C ++ methods that do not call the Ruby API (since the GC does not turn on before the Ruby API is called)

If volatile need to use

  • in C / C ++ methods that call any Ruby ALLOC or malloc macros / functions (since they can trigger GC when the memory is heavily fragmented)
  • in C / C ++ methods that call any Ruby functions (e.g. rb_funcall , rb_ary_new , etc.)

Other methods to prevent GC

  • mark VALUE that are used
  • disable GC when creating an object and then turn it back on
  • Do not use Ruby distribution methods (risky).

Is everything right? What details do I miss? Other than labeling, is volatile only way?

+6
source share
2 answers

Marking a variable as volatile prevents the C / C ++ compiler from applying certain optimizations based on the assumption that variables cannot change values ​​"on their own." Wikipedia: volatile variable

I think it should be used when VALUE is shared or can be changed using Ruby code outside of the C extension so that the compiler knows about this fact. Check out this example .

0
source

I would say that the practical rule is that the value of your variable can be changed at any time at runtime, and you don't know when, use the volatile keyword. This includes interruptions. For example, you have an interrupt callback function that counts how many times a user has pressed something on the keyboard. Your program does not know WHEN the user presses a button on the keyboard, so the counter variable must be declared with the volatile keyword.

As mentioned earlier, it disables some compiler optimizations for the variable. For instance:

 int a = 5; while(a == 5){ //do something } 

The compiler optimizes the while(a == 5) statement into while(true) , because it sees that the variable a cannot change at run time, and it does not make sense to check the value of a each cycle. So you end up in an endless loop. But if you add the volatile keyword:

 volatile int a = 5; while(a == 5){ //do something } 

You simply tell the compiler to leave the variable as it is. Do not make any optimizations, some interrupts can change its value. And on this, everything works just fine.

0
source

Source: https://habr.com/ru/post/955216/


All Articles