docs: Add notes on heap allocation caused by bound method refs.
This commit is contained in:
parent
df078e8213
commit
ec1e9a10a7
@ -112,5 +112,14 @@ Functions
|
|||||||
the heap may be locked) and scheduling a function to call later will lift
|
the heap may be locked) and scheduling a function to call later will lift
|
||||||
those restrictions.
|
those restrictions.
|
||||||
|
|
||||||
There is a finite stack to hold the scheduled functions and `schedule`
|
Note: If `schedule()` is called from a preempting IRQ, when memory
|
||||||
|
allocation is not allowed and the callback to be passed to `schedule()` is
|
||||||
|
a bound method, passing this directly will fail. This is because creating a
|
||||||
|
reference to a bound method causes memory allocation. A solution is to
|
||||||
|
create a reference to the method in the class constructor and to pass that
|
||||||
|
reference to `schedule()`. This is discussed in detail here
|
||||||
|
:ref:`reference documentation <isr_rules>` under "Creation of Python
|
||||||
|
objects".
|
||||||
|
|
||||||
|
There is a finite stack to hold the scheduled functions and `schedule()`
|
||||||
will raise a `RuntimeError` if the stack is full.
|
will raise a `RuntimeError` if the stack is full.
|
||||||
|
@ -124,6 +124,32 @@ A means of creating an object without employing a class or globals is as follows
|
|||||||
The compiler instantiates the default ``buf`` argument when the function is
|
The compiler instantiates the default ``buf`` argument when the function is
|
||||||
loaded for the first time (usually when the module it's in is imported).
|
loaded for the first time (usually when the module it's in is imported).
|
||||||
|
|
||||||
|
An instance of object creation occurs when a reference to a bound method is
|
||||||
|
created. This means that an ISR cannot pass a bound method to a function. One
|
||||||
|
solution is to create a reference to the bound method in the class constructor
|
||||||
|
and to pass that reference in the ISR. For example:
|
||||||
|
|
||||||
|
.. code:: python
|
||||||
|
|
||||||
|
class Foo():
|
||||||
|
def __init__(self):
|
||||||
|
self.bar_ref = self.bar # Allocation occurs here
|
||||||
|
self.x = 0.1
|
||||||
|
tim = pyb.Timer(4)
|
||||||
|
tim.init(freq=2)
|
||||||
|
tim.callback(self.cb)
|
||||||
|
|
||||||
|
def bar(self, _):
|
||||||
|
self.x *= 1.2
|
||||||
|
print(self.x)
|
||||||
|
|
||||||
|
def cb(self, t):
|
||||||
|
# Passing self.bar would cause allocation.
|
||||||
|
micropython.schedule(self.bar_ref, 0)
|
||||||
|
|
||||||
|
Other techniques are to define and instantiate the method in the constructor
|
||||||
|
or to pass :meth:`Foo.bar` with the argument *self*.
|
||||||
|
|
||||||
Use of Python objects
|
Use of Python objects
|
||||||
~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
@ -179,6 +205,9 @@ interrupt occurs while the previous callback is executing, a further instance of
|
|||||||
for execution; this will run after the current instance has completed. A sustained high interrupt repetition
|
for execution; this will run after the current instance has completed. A sustained high interrupt repetition
|
||||||
rate therefore carries a risk of unconstrained queue growth and eventual failure with a ``RuntimeError``.
|
rate therefore carries a risk of unconstrained queue growth and eventual failure with a ``RuntimeError``.
|
||||||
|
|
||||||
|
If the callback to be passed to `schedule()` is a bound method, consider the
|
||||||
|
note in "Creation of Python objects".
|
||||||
|
|
||||||
Exceptions
|
Exceptions
|
||||||
----------
|
----------
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user