Skip to content

Commit 3d6752b

Browse files
feat: Replace thread unsafe GilOnceCell with Mutex (#21927)
1 parent c538836 commit 3d6752b

File tree

6 files changed

+22
-81
lines changed

6 files changed

+22
-81
lines changed

Cargo.lock

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/polars-python/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ chrono = { workspace = true }
3636
chrono-tz = { workspace = true }
3737
either = { workspace = true }
3838
flate2 = { workspace = true }
39+
hashbrown = { workspace = true }
3940
itoa = { workspace = true }
4041
libc = { workspace = true }
4142
ndarray = { workspace = true }

crates/polars-python/src/conversion/any_value.rs

+20-23
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,20 @@
11
use std::borrow::{Borrow, Cow};
2-
use std::sync::Arc;
2+
use std::sync::{Arc, Mutex};
33

44
use chrono::{
55
DateTime, Datelike, FixedOffset, NaiveDate, NaiveDateTime, NaiveTime, TimeDelta, Timelike,
66
};
77
use chrono_tz::Tz;
8+
use hashbrown::HashMap;
89
#[cfg(feature = "object")]
910
use polars::chunked_array::object::PolarsObjectSafe;
1011
#[cfg(feature = "object")]
1112
use polars::datatypes::OwnedObject;
12-
use polars::datatypes::{DataType, Field, PlHashMap, TimeUnit};
13+
use polars::datatypes::{DataType, Field, TimeUnit};
1314
use polars::prelude::{AnyValue, PlSmallStr, Series};
1415
use polars_core::utils::any_values_to_supertype_and_n_dtypes;
1516
use polars_core::utils::arrow::temporal_conversions::date32_to_date;
17+
use polars_utils::aliases::PlFixedStateQuality;
1618
use pyo3::exceptions::{PyOverflowError, PyTypeError, PyValueError};
1719
use pyo3::prelude::*;
1820
use pyo3::pybacked::PyBackedStr;
@@ -186,8 +188,8 @@ impl std::hash::Hash for TypeObjectKey {
186188
}
187189

188190
type InitFn = for<'py> fn(&Bound<'py, PyAny>, bool) -> PyResult<AnyValue<'py>>;
189-
pub(crate) static LUT: crate::gil_once_cell::GILOnceCell<PlHashMap<TypeObjectKey, InitFn>> =
190-
crate::gil_once_cell::GILOnceCell::new();
191+
pub(crate) static LUT: Mutex<HashMap<TypeObjectKey, InitFn, PlFixedStateQuality>> =
192+
Mutex::new(HashMap::with_hasher(PlFixedStateQuality::with_seed(0)));
191193

192194
/// Convert a Python object to an [`AnyValue`].
193195
pub(crate) fn py_object_to_any_value<'py>(
@@ -474,11 +476,8 @@ pub(crate) fn py_object_to_any_value<'py>(
474476
///
475477
/// Note: This function is only ran if the object's type is not already in the
476478
/// lookup table.
477-
fn get_conversion_function(
478-
ob: &Bound<'_, PyAny>,
479-
py: Python<'_>,
480-
allow_object: bool,
481-
) -> PyResult<InitFn> {
479+
fn get_conversion_function(ob: &Bound<'_, PyAny>, allow_object: bool) -> PyResult<InitFn> {
480+
let py = ob.py();
482481
if ob.is_none() {
483482
Ok(get_null)
484483
}
@@ -549,20 +548,18 @@ pub(crate) fn py_object_to_any_value<'py>(
549548
let py_type = ob.get_type();
550549
let py_type_address = py_type.as_ptr() as usize;
551550

552-
Python::with_gil(move |py| {
553-
LUT.with_gil(py, move |lut| {
554-
if !lut.contains_key(&py_type_address) {
555-
let k = TypeObjectKey::new(py_type.clone().unbind());
556-
557-
assert_eq!(k.address, py_type_address);
551+
let conversion_func = {
552+
if let Some(cached_func) = LUT.lock().unwrap().get(&py_type_address) {
553+
*cached_func
554+
} else {
555+
let k = TypeObjectKey::new(py_type.clone().unbind());
556+
assert_eq!(k.address, py_type_address);
558557

559-
unsafe {
560-
lut.insert_unique_unchecked(k, get_conversion_function(ob, py, allow_object)?);
561-
}
562-
}
558+
let func = get_conversion_function(ob, allow_object)?;
559+
LUT.lock().unwrap().insert(k, func);
560+
func
561+
}
562+
};
563563

564-
let conversion_func = *lut.get(&py_type_address).unwrap();
565-
conversion_func(ob, strict)
566-
})
567-
})
564+
conversion_func(ob, strict)
568565
}

crates/polars-python/src/gil_once_cell.rs

-50
This file was deleted.

crates/polars-python/src/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ pub mod expr;
2121
pub mod file;
2222
#[cfg(feature = "pymethods")]
2323
pub mod functions;
24-
pub mod gil_once_cell;
2524
pub mod interop;
2625
pub mod lazyframe;
2726
pub mod lazygroupby;

crates/polars-python/src/on_startup.rs

-7
Original file line numberDiff line numberDiff line change
@@ -113,12 +113,5 @@ pub unsafe fn register_startup_deps(catch_keyboard_interrupt: bool) {
113113
if catch_keyboard_interrupt {
114114
register_polars_keyboard_interrupt_hook();
115115
}
116-
117-
Python::with_gil(|py| {
118-
// Init AnyValue LUT.
119-
crate::conversion::any_value::LUT
120-
.set(py, Default::default())
121-
.unwrap();
122-
});
123116
});
124117
}

0 commit comments

Comments
 (0)