@@ -181,7 +181,11 @@ cdef extern from "parser/tokenizer.h":
181
181
PyObject * skipfunc
182
182
int64_t skip_first_N_rows
183
183
int skipfooter
184
- double (* converter)(const char * , char ** , char , char , char , int ) nogil
184
+ # pick one, depending on whether the converter requires GIL
185
+ double (* double_converter_nogil)(const char * , char ** ,
186
+ char , char , char , int ) nogil
187
+ double (* double_converter_withgil)(const char * , char ** ,
188
+ char , char , char , int )
185
189
186
190
# error handling
187
191
char * warn_msg
@@ -482,11 +486,14 @@ cdef class TextReader:
482
486
483
487
self .verbose = verbose
484
488
self .low_memory = low_memory
485
- self .parser.converter = xstrtod
489
+ self .parser.double_converter_nogil = xstrtod
490
+ self .parser.double_converter_withgil = NULL
486
491
if float_precision == ' high' :
487
- self .parser.converter = precise_xstrtod
488
- elif float_precision == ' round_trip' :
489
- self .parser.converter = round_trip
492
+ self .parser.double_converter_nogil = precise_xstrtod
493
+ self .parser.double_converter_withgil = NULL
494
+ elif float_precision == ' round_trip' : # avoid gh-15140
495
+ self .parser.double_converter_nogil = NULL
496
+ self .parser.double_converter_withgil = round_trip
490
497
491
498
# encoding
492
499
if encoding is not None :
@@ -1699,17 +1706,31 @@ cdef _try_double(parser_t *parser, int col, int line_start, int line_end,
1699
1706
result = np.empty(lines, dtype = np.float64)
1700
1707
data = < double * > result.data
1701
1708
na_fset = kset_float64_from_list(na_flist)
1702
- with nogil:
1703
- error = _try_double_nogil(parser, col, line_start, line_end,
1709
+ if parser.double_converter_nogil != NULL : # if it can run without the GIL
1710
+ with nogil:
1711
+ error = _try_double_nogil(parser, parser.double_converter_nogil,
1712
+ col, line_start, line_end,
1713
+ na_filter, na_hashset, use_na_flist,
1714
+ na_fset, NA, data, & na_count)
1715
+ else :
1716
+ assert parser.double_converter_withgil != NULL
1717
+ error = _try_double_nogil(parser,
1718
+ < double (* )(const char * , char ** ,
1719
+ char , char , char , int )
1720
+ nogil> parser.double_converter_withgil,
1721
+ col, line_start, line_end,
1704
1722
na_filter, na_hashset, use_na_flist,
1705
1723
na_fset, NA, data, & na_count)
1706
1724
kh_destroy_float64(na_fset)
1707
1725
if error != 0 :
1708
1726
return None , None
1709
1727
return result, na_count
1710
1728
1711
- cdef inline int _try_double_nogil(parser_t * parser, int col,
1712
- int line_start, int line_end,
1729
+ cdef inline int _try_double_nogil(parser_t * parser,
1730
+ double (* double_converter)(
1731
+ const char * , char ** , char ,
1732
+ char , char , int ) nogil,
1733
+ int col, int line_start, int line_end,
1713
1734
bint na_filter, kh_str_t * na_hashset,
1714
1735
bint use_na_flist,
1715
1736
const kh_float64_t * na_flist,
@@ -1739,7 +1760,7 @@ cdef inline int _try_double_nogil(parser_t *parser, int col,
1739
1760
na_count[0 ] += 1
1740
1761
data[0 ] = NA
1741
1762
else :
1742
- data[0 ] = parser.converter (word, & p_end, parser.decimal,
1763
+ data[0 ] = double_converter (word, & p_end, parser.decimal,
1743
1764
parser.sci, parser.thousands, 1 )
1744
1765
if errno != 0 or p_end[0 ] or p_end == word:
1745
1766
if (strcasecmp(word, cinf) == 0 or
@@ -1760,7 +1781,7 @@ cdef inline int _try_double_nogil(parser_t *parser, int col,
1760
1781
else :
1761
1782
for i in range (lines):
1762
1783
COLITER_NEXT(it, word)
1763
- data[0 ] = parser.converter (word, & p_end, parser.decimal,
1784
+ data[0 ] = double_converter (word, & p_end, parser.decimal,
1764
1785
parser.sci, parser.thousands, 1 )
1765
1786
if errno != 0 or p_end[0 ] or p_end == word:
1766
1787
if (strcasecmp(word, cinf) == 0 or
0 commit comments