You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Each Erlang process can have an isolated Python namespace within an event loop. These namespaces are tracked in a linked list protected by `namespaces_mutex`.
249
249
250
+
### Usage
251
+
252
+
Define functions and state for async tasks in your process's namespace:
253
+
254
+
```erlang
255
+
%% Get event loop reference
256
+
{ok, Loop} = py_event_loop:get_loop(),
257
+
LoopRef = py_event_loop:get_nif_ref(Loop),
258
+
259
+
%% Define async functions in this process's namespace
260
+
ok = py_nif:event_loop_exec(LoopRef, <<"
261
+
import asyncio
262
+
263
+
async def process_data(items):
264
+
results = []
265
+
for item in items:
266
+
await asyncio.sleep(0.01) # Simulate async I/O
267
+
results.append(item * 2)
268
+
return results
269
+
270
+
# State persists across calls
271
+
call_count = 0
272
+
273
+
async def tracked_call(x):
274
+
global call_count
275
+
call_count += 1
276
+
return {'result': x, 'call_number': call_count}
277
+
">>),
278
+
279
+
%% Use the functions via create_task with __main__ module
Copy file name to clipboardExpand all lines: docs/process-bound-envs.md
+155-1Lines changed: 155 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -39,6 +39,158 @@ spawn(fun() ->
39
39
end).
40
40
```
41
41
42
+
## OWN_GIL Mode
43
+
44
+
OWN_GIL contexts (Python 3.12+) provide true parallel execution with dedicated pthreads. Process-bound environments work with OWN_GIL, allowing multiple Erlang processes to share a single OWN_GIL context while maintaining isolated Python namespaces.
45
+
46
+
### Explicit Environment Creation
47
+
48
+
For OWN_GIL contexts, you can explicitly create and manage environments:
|**Explicit**|`create_local_env` + `py_nif:context_*`| OWN_GIL, fine-grained control, multiple envs per process |
108
+
109
+
**Use implicit (py:exec)** when:
110
+
- Using worker or subinterp modes
111
+
- One environment per process is sufficient
112
+
- You want automatic lifecycle management
113
+
114
+
**Use explicit (create_local_env)** when:
115
+
- Using OWN_GIL mode for parallel execution
116
+
- Need multiple environments in a single process
117
+
- Want to pass environments between processes
118
+
- Need direct NIF-level control
119
+
120
+
## Event Loop Environments
121
+
122
+
The event loop API also supports per-process namespaces. Each Erlang process gets an isolated namespace within the event loop, allowing you to define functions and state that persist across async task calls.
123
+
124
+
### Defining Functions for Async Tasks
125
+
126
+
```erlang
127
+
%% Get the event loop reference
128
+
{ok, Loop} =py_event_loop:get_loop(),
129
+
LoopRef=py_event_loop:get_nif_ref(Loop),
130
+
131
+
%% Define a function in this process's namespace
132
+
ok=py_nif:event_loop_exec(LoopRef, <<"
133
+
import asyncio
134
+
135
+
async def my_async_function(x):
136
+
await asyncio.sleep(0.1)
137
+
return x * 2
138
+
139
+
counter = 0
140
+
141
+
async def increment_and_get():
142
+
global counter
143
+
counter += 1
144
+
return counter
145
+
">>),
146
+
147
+
%% Call the function via create_task - uses __main__ module
Event loop namespaces are automatically cleaned up when the Erlang process exits. The event loop monitors each process that creates a namespace and removes it on process termination.
193
+
42
194
## Building Python Actors
43
195
44
196
The process-bound model enables a pattern we call "Python actors" - Erlang processes that encapsulate Python state and expose it through message passing.
@@ -277,6 +429,8 @@ This design prioritizes safety over avoiding minor memory leaks during edge case
277
429
278
430
## See Also
279
431
432
+
-[OWN_GIL Internals](owngil_internals.md) - Architecture and safety mechanisms for OWN_GIL mode
433
+
-[Scalability](scalability.md) - Mode comparison (owngil vs subinterp vs worker)
0 commit comments