@ -1054,13 +1054,20 @@ protected:
@@ -1054,13 +1054,20 @@ protected:
- delegate translation to the next translator by throwing a new type of exception .
*/
auto & local_exception_translators
= get_local_internals ( ) . registered_exception_translators ;
if ( detail : : apply_exception_translators ( local_exception_translators ) ) {
return nullptr ;
}
auto & exception_translators = get_internals ( ) . registered_exception_translators ;
if ( detail : : apply_exception_translators ( exception_translators ) ) {
bool handled = with_internals ( [ & ] ( internals & internals ) {
auto & local_exception_translators
= get_local_internals ( ) . registered_exception_translators ;
if ( detail : : apply_exception_translators ( local_exception_translators ) ) {
return true ;
}
auto & exception_translators = internals . registered_exception_translators ;
if ( detail : : apply_exception_translators ( exception_translators ) ) {
return true ;
}
return false ;
} ) ;
if ( handled ) {
return nullptr ;
}
@ -1199,6 +1206,16 @@ struct handle_type_name<cpp_function> {
@@ -1199,6 +1206,16 @@ struct handle_type_name<cpp_function> {
PYBIND11_NAMESPACE_END ( detail )
// Use to activate Py_MOD_GIL_NOT_USED.
class mod_gil_not_used {
public :
explicit mod_gil_not_used ( bool flag = true ) : flag_ ( flag ) { }
bool flag ( ) const { return flag_ ; }
private :
bool flag_ ;
} ;
/// Wrapper for Python extension modules
class module_ : public object {
public :
@ -1299,7 +1316,11 @@ public:
@@ -1299,7 +1316,11 @@ public:
` ` def ` ` should point to a statically allocated module_def .
\ endrst */
static module_ create_extension_module ( const char * name , const char * doc , module_def * def ) {
static module_ create_extension_module ( const char * name ,
const char * doc ,
module_def * def ,
mod_gil_not_used gil_not_used
= mod_gil_not_used ( false ) ) {
// module_def is PyModuleDef
// Placement new (not an allocation).
def = new ( def )
@ -1319,6 +1340,11 @@ public:
@@ -1319,6 +1340,11 @@ public:
}
pybind11_fail ( " Internal error in module_::create_extension_module() " ) ;
}
if ( gil_not_used . flag ( ) ) {
# ifdef Py_GIL_DISABLED
PyUnstable_Module_SetGIL ( m , Py_MOD_GIL_NOT_USED ) ;
# endif
}
// TODO: Should be reinterpret_steal for Python 3, but Python also steals it again when
// returned from PyInit_...
// For Python 2, reinterpret_borrow was correct.
@ -1397,15 +1423,16 @@ protected:
@@ -1397,15 +1423,16 @@ protected:
tinfo - > default_holder = rec . default_holder ;
tinfo - > module_local = rec . module_local ;
auto & internals = get_internals ( ) ;
auto tindex = std : : type_index ( * rec . type ) ;
tinfo - > direct_conversions = & internals . direct_conversions [ tindex ] ;
if ( rec . module_local ) {
get_local_internals ( ) . registered_types_cpp [ tindex ] = tinfo ;
} else {
internals . registered_types_cpp [ tindex ] = tinfo ;
}
internals . registered_types_py [ ( PyTypeObject * ) m_ptr ] = { tinfo } ;
with_internals ( [ & ] ( internals & internals ) {
auto tindex = std : : type_index ( * rec . type ) ;
tinfo - > direct_conversions = & internals . direct_conversions [ tindex ] ;
if ( rec . module_local ) {
get_local_internals ( ) . registered_types_cpp [ tindex ] = tinfo ;
} else {
internals . registered_types_cpp [ tindex ] = tinfo ;
}
internals . registered_types_py [ ( PyTypeObject * ) m_ptr ] = { tinfo } ;
} ) ;
if ( rec . bases . size ( ) > 1 | | rec . multiple_inheritance ) {
mark_parents_nonsimple ( tinfo - > type ) ;
@ -1618,10 +1645,12 @@ public:
@@ -1618,10 +1645,12 @@ public:
generic_type : : initialize ( record ) ;
if ( has_alias ) {
auto & instances = record . module_local ? get_local_internals ( ) . registered_types_cpp
: get_internals ( ) . registered_types_cpp ;
instances [ std : : type_index ( typeid ( type_alias ) ) ]
= instances [ std : : type_index ( typeid ( type ) ) ] ;
with_internals ( [ & ] ( internals & internals ) {
auto & instances = record . module_local ? get_local_internals ( ) . registered_types_cpp
: internals . registered_types_cpp ;
instances [ std : : type_index ( typeid ( type_alias ) ) ]
= instances [ std : : type_index ( typeid ( type ) ) ] ;
} ) ;
}
}
@ -2336,28 +2365,32 @@ keep_alive_impl(size_t Nurse, size_t Patient, function_call &call, handle ret) {
@@ -2336,28 +2365,32 @@ keep_alive_impl(size_t Nurse, size_t Patient, function_call &call, handle ret) {
inline std : : pair < decltype ( internals : : registered_types_py ) : : iterator , bool >
all_type_info_get_cache ( PyTypeObject * type ) {
auto res = get_internals ( )
. registered_types_py
auto res = with_internals ( [ type ] ( internals & internals ) {
return internals
. registered_types_py
# ifdef __cpp_lib_unordered_map_try_emplace
. try_emplace ( type ) ;
. try_emplace ( type ) ;
# else
. emplace ( type , std : : vector < detail : : type_info * > ( ) ) ;
. emplace ( type , std : : vector < detail : : type_info * > ( ) ) ;
# endif
} ) ;
if ( res . second ) {
// New cache entry created; set up a weak reference to automatically remove it if the type
// gets destroyed:
weakref ( ( PyObject * ) type , cpp_function ( [ type ] ( handle wr ) {
get_internals ( ) . registered_types_py . erase ( type ) ;
// TODO consolidate the erasure code in pybind11_meta_dealloc() in class.h
auto & cache = get_internals ( ) . inactive_override_cache ;
for ( auto it = cache . begin ( ) , last = cache . end ( ) ; it ! = last ; ) {
if ( it - > first = = reinterpret_cast < PyObject * > ( type ) ) {
it = cache . erase ( it ) ;
} else {
+ + it ;
with_internals ( [ type ] ( internals & internals ) {
internals . registered_types_py . erase ( type ) ;
// TODO consolidate the erasure code in pybind11_meta_dealloc() in class.h
auto & cache = internals . inactive_override_cache ;
for ( auto it = cache . begin ( ) , last = cache . end ( ) ; it ! = last ; ) {
if ( it - > first = = reinterpret_cast < PyObject * > ( type ) ) {
it = cache . erase ( it ) ;
} else {
+ + it ;
}
}
}
} ) ;
wr . dec_ref ( ) ;
} ) )
@ -2562,7 +2595,11 @@ void implicitly_convertible() {
@@ -2562,7 +2595,11 @@ void implicitly_convertible() {
~ set_flag ( ) { flag = false ; }
} ;
auto implicit_caster = [ ] ( PyObject * obj , PyTypeObject * type ) - > PyObject * {
# ifdef Py_GIL_DISABLED
thread_local bool currently_used = false ;
# else
static bool currently_used = false ;
# endif
if ( currently_used ) { // implicit conversions are non-reentrant
return nullptr ;
}
@ -2587,8 +2624,10 @@ void implicitly_convertible() {
@@ -2587,8 +2624,10 @@ void implicitly_convertible() {
}
inline void register_exception_translator ( ExceptionTranslator & & translator ) {
detail : : get_internals ( ) . registered_exception_translators . push_front (
std : : forward < ExceptionTranslator > ( translator ) ) ;
detail : : with_internals ( [ & ] ( detail : : internals & internals ) {
internals . registered_exception_translators . push_front (
std : : forward < ExceptionTranslator > ( translator ) ) ;
} ) ;
}
/**
@ -2598,8 +2637,11 @@ inline void register_exception_translator(ExceptionTranslator &&translator) {
@@ -2598,8 +2637,11 @@ inline void register_exception_translator(ExceptionTranslator &&translator) {
* the exception .
*/
inline void register_local_exception_translator ( ExceptionTranslator & & translator ) {
detail : : get_local_internals ( ) . registered_exception_translators . push_front (
std : : forward < ExceptionTranslator > ( translator ) ) ;
detail : : with_internals ( [ & ] ( detail : : internals & internals ) {
( void ) internals ;
detail : : get_local_internals ( ) . registered_exception_translators . push_front (
std : : forward < ExceptionTranslator > ( translator ) ) ;
} ) ;
}
/**
@ -2756,14 +2798,19 @@ get_type_override(const void *this_ptr, const type_info *this_type, const char *
@@ -2756,14 +2798,19 @@ get_type_override(const void *this_ptr, const type_info *this_type, const char *
/* Cache functions that aren't overridden in Python to avoid
many costly Python dictionary lookups below */
auto & cache = get_internals ( ) . inactive_override_cache ;
if ( cache . find ( key ) ! = cache . end ( ) ) {
bool not_overridden = with_internals ( [ & key ] ( internals & internals ) {
auto & cache = internals . inactive_override_cache ;
return cache . find ( key ) ! = cache . end ( ) ;
} ) ;
if ( not_overridden ) {
return function ( ) ;
}
function override = getattr ( self , name , function ( ) ) ;
if ( override . is_cpp_function ( ) ) {
cache . insert ( std : : move ( key ) ) ;
with_internals ( [ & ] ( internals & internals ) {
internals . inactive_override_cache . insert ( std : : move ( key ) ) ;
} ) ;
return function ( ) ;
}