Skip to content

Commit

Permalink
Merge branch 'stable'
Browse files Browse the repository at this point in the history
  • Loading branch information
YannickJadoul committed Aug 1, 2024
2 parents eb2f2d1 + f788a39 commit f394e3e
Show file tree
Hide file tree
Showing 9 changed files with 261 additions and 21 deletions.
7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a

_Nothing yet_

## [0.4.4] - 2024-07-30
### Fixed
- Fixed compatibility with NumPy 2.

## [0.4.3] - 2022-12-24
### Fixed
- Fixed source distribution failing to build, due to `scikit-build` & `setuptools` version mismatch in `pyproject.toml`.
Expand Down Expand Up @@ -119,7 +123,8 @@ _Nothing yet_
- Main functionality of `Thing`, `Data`, `Matrix`, `Vector`, `Sound`, `Spectrum`, `Spectrogram`, and `Intensity` classes. Preliminary implementations of `Pitch`, `Harmonicity`, `Formant`, and `MFCC`.
- Basic Travis CI configuration.

[Unreleased]: https://github.com/YannickJadoul/Parselmouth/compare/v0.4.3...HEAD
[Unreleased]: https://github.com/YannickJadoul/Parselmouth/compare/v0.4.4...HEAD
[0.4.4]: https://github.com/YannickJadoul/Parselmouth/compare/v0.4.3...v0.4.4
[0.4.3]: https://github.com/YannickJadoul/Parselmouth/compare/v0.4.2...v0.4.3
[0.4.2]: https://github.com/YannickJadoul/Parselmouth/compare/v0.4.1...v0.4.2
[0.4.1]: https://github.com/YannickJadoul/Parselmouth/compare/v0.4.0...v0.4.1
Expand Down
2 changes: 1 addition & 1 deletion docs/examples/pitch_manipulation.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@
"version": "3.8.7"
},
"nbsphinx": {
"timeout": 60
"timeout": 60
}
},
"nbformat": 4,
Expand Down
1 change: 1 addition & 0 deletions pybind11/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ set(PYBIND11_HEADERS
include/pybind11/eigen.h
include/pybind11/embed.h
include/pybind11/eval.h
include/pybind11/gil_safe_call_once.h
include/pybind11/iostream.h
include/pybind11/functional.h
include/pybind11/numpy.h
Expand Down
11 changes: 10 additions & 1 deletion pybind11/include/pybind11/cast.h
Original file line number Diff line number Diff line change
Expand Up @@ -1202,7 +1202,7 @@ template <> class type_caster<bool> {
if (!src) return false;
else if (src.ptr() == Py_True) { value = true; return true; }
else if (src.ptr() == Py_False) { value = false; return true; }
else if (convert || !strcmp("numpy.bool_", Py_TYPE(src.ptr())->tp_name)) {
else if (convert || is_numpy_bool(src)) {
// (allow non-implicit conversion for numpy booleans)

Py_ssize_t res = -1;
Expand Down Expand Up @@ -1236,6 +1236,15 @@ template <> class type_caster<bool> {
return handle(src ? Py_True : Py_False).inc_ref();
}
PYBIND11_TYPE_CASTER(bool, _("bool"));

private:
// Test if an object is a NumPy boolean (without fetching the type).
static inline bool is_numpy_bool(handle object) {
const char *type_name = Py_TYPE(object.ptr())->tp_name;
// Name changed to `numpy.bool` in NumPy 2, `numpy.bool_` is needed for 1.x support
return std::strcmp("numpy.bool", type_name) == 0
|| std::strcmp("numpy.bool_", type_name) == 0;
}
};

// Helper class for UTF-{8,16,32} C++ stl strings:
Expand Down
12 changes: 12 additions & 0 deletions pybind11/include/pybind11/detail/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,14 @@
# endif
#endif

#if defined(PYBIND11_CPP20)
# define PYBIND11_CONSTINIT constinit
# define PYBIND11_DTOR_CONSTEXPR constexpr
#else
# define PYBIND11_CONSTINIT
# define PYBIND11_DTOR_CONSTEXPR
#endif

// Compiler version assertions
#if defined(__INTEL_COMPILER)
# if __INTEL_COMPILER < 1800
Expand Down Expand Up @@ -150,6 +158,10 @@
# undef copysign
#endif

#if defined(PYBIND11_NUMPY_1_ONLY)
# define PYBIND11_INTERNAL_NUMPY_1_ONLY_DETECTED
#endif

#if defined(_MSC_VER)
# if defined(PYBIND11_DEBUG_MARKER)
# define _DEBUG
Expand Down
85 changes: 85 additions & 0 deletions pybind11/include/pybind11/gil_safe_call_once.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// Copyright (c) 2023 The pybind Community.

#pragma once

#include "detail/common.h"
//#include "gil.h"

#include <cassert>
#include <mutex>

PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)

// Use the `gil_safe_call_once_and_store` class below instead of the naive
//
// static auto imported_obj = py::module_::import("module_name"); // BAD, DO NOT USE!
//
// which has two serious issues:
//
// 1. Py_DECREF() calls potentially after the Python interpreter was finalized already, and
// 2. deadlocks in multi-threaded processes (because of missing lock ordering).
//
// The following alternative avoids both problems:
//
// PYBIND11_CONSTINIT static py::gil_safe_call_once_and_store<py::object> storage;
// auto &imported_obj = storage // Do NOT make this `static`!
// .call_once_and_store_result([]() {
// return py::module_::import("module_name");
// })
// .get_stored();
//
// The parameter of `call_once_and_store_result()` must be callable. It can make
// CPython API calls, and in particular, it can temporarily release the GIL.
//
// `T` can be any C++ type, it does not have to involve CPython API types.
//
// The behavior with regard to signals, e.g. `SIGINT` (`KeyboardInterrupt`),
// is not ideal. If the main thread is the one to actually run the `Callable`,
// then a `KeyboardInterrupt` will interrupt it if it is running normal Python
// code. The situation is different if a non-main thread runs the
// `Callable`, and then the main thread starts waiting for it to complete:
// a `KeyboardInterrupt` will not interrupt the non-main thread, but it will
// get processed only when it is the main thread's turn again and it is running
// normal Python code. However, this will be unnoticeable for quick call-once
// functions, which is usually the case.
template <typename T>
class gil_safe_call_once_and_store {
public:
// PRECONDITION: The GIL must be held when `call_once_and_store_result()` is called.
template <typename Callable>
gil_safe_call_once_and_store &call_once_and_store_result(Callable &&fn) {
if (!is_initialized_) { // This read is guarded by the GIL.
// Multiple threads may enter here, because the GIL is released in the next line and
// CPython API calls in the `fn()` call below may release and reacquire the GIL.
gil_scoped_release gil_rel; // Needed to establish lock ordering.
std::call_once(once_flag_, [&] {
// Only one thread will ever enter here.
gil_scoped_acquire gil_acq;
::new (storage_) T(fn()); // fn may release, but will reacquire, the GIL.
is_initialized_ = true; // This write is guarded by the GIL.
});
// All threads will observe `is_initialized_` as true here.
}
// Intentionally not returning `T &` to ensure the calling code is self-documenting.
return *this;
}

// This must only be called after `call_once_and_store_result()` was called.
T &get_stored() {
assert(is_initialized_);
return *reinterpret_cast<T *>(storage_);
}

constexpr gil_safe_call_once_and_store() = default;
PYBIND11_DTOR_CONSTEXPR ~gil_safe_call_once_and_store() = default;

private:
alignas(T) char storage_[sizeof(T)] = {};
std::once_flag once_flag_ = {};
bool is_initialized_ = false;
// The `is_initialized_`-`storage_` pair is very similar to `std::optional`,
// but the latter does not have the triviality properties of former,
// therefore `std::optional` is not a viable alternative here.
};

PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
Loading

0 comments on commit f394e3e

Please sign in to comment.