9393//! let locals = pyo3_async_runtimes::TaskLocals::with_running_loop(py)?.copy_context(py)?;
9494//!
9595//! // Convert the async move { } block to a Python awaitable
96- //! pyo3_async_runtimes::tokio::future_into_py_with_locals(py, locals.clone_ref(py ), async move {
96+ //! pyo3_async_runtimes::tokio::future_into_py_with_locals(py, locals.clone( ), async move {
9797//! let py_sleep = Python::attach(|py| {
9898//! // Sometimes we need to call other async Python functions within
9999//! // this future. In order for this to work, we need to track the
162162//!
163163//! pyo3_async_runtimes::tokio::future_into_py_with_locals(
164164//! py,
165- //! locals.clone_ref(py ),
165+ //! locals.clone( ),
166166//! // Store the current locals in task-local data
167- //! pyo3_async_runtimes::tokio::scope(locals.clone_ref(py ), async move {
167+ //! pyo3_async_runtimes::tokio::scope(locals.clone( ), async move {
168168//! let py_sleep = Python::attach(|py| {
169169//! pyo3_async_runtimes::into_future_with_locals(
170170//! // Now we can get the current locals through task-local data
189189//!
190190//! pyo3_async_runtimes::tokio::future_into_py_with_locals(
191191//! py,
192- //! locals.clone_ref(py ),
192+ //! locals.clone( ),
193193//! // Store the current locals in task-local data
194- //! pyo3_async_runtimes::tokio::scope(locals.clone_ref(py ), async move {
194+ //! pyo3_async_runtimes::tokio::scope(locals.clone( ), async move {
195195//! let py_sleep = Python::attach(|py| {
196196//! pyo3_async_runtimes::into_future_with_locals(
197197//! &pyo3_async_runtimes::tokio::get_current_locals(py)?,
@@ -395,6 +395,7 @@ pub mod doc_test {
395395}
396396
397397use std:: future:: Future ;
398+ use std:: sync:: Arc ;
398399
399400use futures:: channel:: oneshot;
400401use pyo3:: { call:: PyCallArgs , prelude:: * , sync:: PyOnceLock , types:: PyDict } ;
@@ -468,22 +469,26 @@ fn copy_context(py: Python) -> PyResult<Bound<PyAny>> {
468469 contextvars ( py) ?. call_method0 ( "copy_context" )
469470}
470471
471- /// Task-local data to store for Python conversions .
472+ /// Task-local inner structure .
472473#[ derive( Debug ) ]
473- pub struct TaskLocals {
474+ struct TaskLocalsInner {
474475 /// Track the event loop of the Python task
475476 event_loop : Py < PyAny > ,
476477 /// Track the contextvars of the Python task
477478 context : Py < PyAny > ,
478479}
479480
481+ /// Task-local data to store for Python conversions.
482+ #[ derive( Debug ) ]
483+ pub struct TaskLocals ( Arc < TaskLocalsInner > ) ;
484+
480485impl TaskLocals {
481486 /// At a minimum, TaskLocals must store the event loop.
482487 pub fn new ( event_loop : Bound < PyAny > ) -> Self {
483- Self {
488+ Self ( Arc :: new ( TaskLocalsInner {
484489 context : event_loop. py ( ) . None ( ) ,
485490 event_loop : event_loop. into ( ) ,
486- }
491+ } ) )
487492 }
488493
489494 /// Construct TaskLocals with the event loop returned by `get_running_loop`
@@ -493,10 +498,10 @@ impl TaskLocals {
493498
494499 /// Manually provide the contextvars for the current task.
495500 pub fn with_context ( self , context : Bound < PyAny > ) -> Self {
496- Self {
501+ Self ( Arc :: new ( TaskLocalsInner {
502+ event_loop : self . 0 . event_loop . clone_ref ( context. py ( ) ) ,
497503 context : context. into ( ) ,
498- ..self
499- }
504+ } ) )
500505 }
501506
502507 /// Capture the current task's contextvars
@@ -506,21 +511,26 @@ impl TaskLocals {
506511
507512 /// Get a reference to the event loop
508513 pub fn event_loop < ' p > ( & self , py : Python < ' p > ) -> Bound < ' p , PyAny > {
509- self . event_loop . clone_ref ( py) . into_bound ( py)
514+ self . 0 . event_loop . clone_ref ( py) . into_bound ( py)
510515 }
511516
512517 /// Get a reference to the python context
513518 pub fn context < ' p > ( & self , py : Python < ' p > ) -> Bound < ' p , PyAny > {
514- self . context . clone_ref ( py) . into_bound ( py)
519+ self . 0 . context . clone_ref ( py) . into_bound ( py)
515520 }
516521
517- /// Create a clone of the TaskLocals by incrementing the reference counters of the event loop and
518- /// contextvars.
519- pub fn clone_ref ( & self , py : Python < ' _ > ) -> Self {
520- Self {
521- event_loop : self . event_loop . clone_ref ( py) ,
522- context : self . context . clone_ref ( py) ,
523- }
522+ /// Create a clone of the TaskLocals. No longer uses the runtime, use `clone` instead.
523+ #[ deprecated( note = "please use `clone` instead" ) ]
524+ pub fn clone_ref ( & self , _py : Python < ' _ > ) -> Self {
525+ self . clone ( )
526+ }
527+ }
528+
529+ impl Clone for TaskLocals {
530+ /// Create a clone of the TaskLocals by incrementing the reference counter of the inner
531+ /// structure.
532+ fn clone ( & self ) -> Self {
533+ Self ( self . 0 . clone ( ) )
524534 }
525535}
526536
0 commit comments