@@ -1063,6 +1063,43 @@ This is useful for:
10631063- Allowing other Erlang processes to run
10641064- Cooperative multitasking
10651065
1066+ #### erlang.schedule_inline(module, func, args=None, kwargs=None)
1067+
1068+ Release the dirty scheduler and continue by calling a Python function via ` enif_schedule_nif() ` - bypassing Erlang messaging entirely.
1069+
1070+ ``` python
1071+ import erlang
1072+
1073+ def process_chunk (data , offset = 0 , results = None ):
1074+ """ Process data in chunks with inline continuations."""
1075+ if results is None :
1076+ results = []
1077+
1078+ chunk_end = min (offset + 100 , len (data))
1079+ for i in range (offset, chunk_end):
1080+ results.append(transform(data[i]))
1081+
1082+ if chunk_end < len (data):
1083+ # Continue inline - no Erlang messaging overhead
1084+ return erlang.schedule_inline(
1085+ ' __main__' , ' process_chunk' ,
1086+ args = [data, chunk_end, results]
1087+ )
1088+
1089+ return results
1090+ ```
1091+
1092+ ** When to use ` schedule_inline ` vs ` schedule_py ` :**
1093+
1094+ | Aspect | ` schedule_inline ` | ` schedule_py ` |
1095+ | --------| -------------------| ---------------|
1096+ | Flow | Python -> NIF -> enif_schedule_nif -> Python | Python -> NIF -> Erlang message -> Python |
1097+ | Speed | ~ 3x faster for tight loops | Slower due to messaging |
1098+ | Use case | Pure Python chains, no Erlang interaction | When you need Erlang messaging between steps |
1099+ | Overhead | Minimal (direct NIF continuation) | Higher (gen_server call) |
1100+
1101+ ** Important:** ` schedule_inline ` captures the caller's globals/locals, ensuring correct namespace resolution even with subinterpreters.
1102+
10661103#### erlang.consume_time_slice(percent)
10671104
10681105Check if the NIF time slice is exhausted. Returns ` True ` if you should yield, ` False ` if more time remains.
@@ -1099,7 +1136,8 @@ def long_computation(items, start_idx=0):
10991136| ---------| ----------| -----------------|
11001137| ` erlang.call() ` | Quick operations or callbacks that use ` receive ` | Held (unless callback suspends via ` receive ` ) |
11011138| ` erlang.schedule() ` | Need to call Erlang callback and always release scheduler | Released |
1102- | ` erlang.schedule_py() ` | Long Python computation, cooperative scheduling | Released |
1139+ | ` erlang.schedule_py() ` | Long Python computation, need Erlang interaction between steps | Released |
1140+ | ` erlang.schedule_inline() ` | Tight Python loops, no Erlang interaction needed (~ 3x faster) | Released |
11031141| ` consume_time_slice() ` | Fine-grained control over yielding | N/A (checks time slice) |
11041142
11051143### Example: Cooperative Long-Running Task
0 commit comments