Simplify bulk_get_filesystem

Only release python GIL while waiting for messages
This commit is contained in:
Kovid Goyal 2021-04-23 10:41:00 +05:30
parent 93ee37c872
commit ddc405a337
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C

View File

@ -12,7 +12,7 @@
namespace wpd { namespace wpd {
static int static int
_pump_waiting_messages() { pump_waiting_messages() {
UINT firstMsg = 0, lastMsg = 0; UINT firstMsg = 0, lastMsg = 0;
MSG msg; MSG msg;
int result = 0; int result = 0;
@ -153,12 +153,8 @@ private:
unsigned int level; unsigned int level;
HANDLE complete; HANDLE complete;
ULONG self_ref; ULONG self_ref;
PyThreadState *thread_state;
PyObject *callback; PyObject *callback;
void release_python_gil() { if (thread_state == NULL) thread_state = PyEval_SaveThread(); }
void acquire_python_gil() { PyEval_RestoreThread(thread_state); thread_state = NULL; }
void do_one_object(CComPtr<IPortableDeviceValues> &properties) { void do_one_object(CComPtr<IPortableDeviceValues> &properties) {
com_wchar_raii property; com_wchar_raii property;
if (!SUCCEEDED(properties->GetStringValue(WPD_OBJECT_ID, property.unsafe_address()))) return; if (!SUCCEEDED(properties->GetStringValue(WPD_OBJECT_ID, property.unsafe_address()))) return;
@ -183,19 +179,15 @@ private:
DWORD num = 0; DWORD num = 0;
if (!items) return; if (!items) return;
if (!SUCCEEDED(values->GetCount(&num))) return; if (!SUCCEEDED(values->GetCount(&num))) return;
acquire_python_gil();
for (DWORD i = 0; i < num; i++) { for (DWORD i = 0; i < num; i++) {
CComPtr<IPortableDeviceValues> properties; CComPtr<IPortableDeviceValues> properties;
if (SUCCEEDED(values->GetAt(i, &properties))) do_one_object(properties); if (SUCCEEDED(values->GetAt(i, &properties))) do_one_object(properties);
} }
release_python_gil();
} }
public: public:
GetBulkPropertiesCallback() : items(NULL), subfolders(NULL), level(0), complete(INVALID_HANDLE_VALUE), self_ref(0), thread_state(NULL), callback(NULL) {} GetBulkPropertiesCallback() : items(NULL), subfolders(NULL), level(0), complete(INVALID_HANDLE_VALUE), self_ref(0), callback(NULL) {}
~GetBulkPropertiesCallback() { if (complete != INVALID_HANDLE_VALUE) CloseHandle(complete); complete = INVALID_HANDLE_VALUE; } ~GetBulkPropertiesCallback() { if (complete != INVALID_HANDLE_VALUE) CloseHandle(complete); complete = INVALID_HANDLE_VALUE; }
bool start_processing(PyObject *items, PyObject *subfolders, unsigned int level, PyObject *callback) { bool start_processing(PyObject *items, PyObject *subfolders, unsigned int level, PyObject *callback) {
@ -208,7 +200,7 @@ public:
} }
void end_processing() { void end_processing() {
if (complete != INVALID_HANDLE_VALUE) CloseHandle(complete); if (complete != INVALID_HANDLE_VALUE) CloseHandle(complete);
items = NULL; subfolders = NULL; level = 0; complete = INVALID_HANDLE_VALUE; callback = NULL; thread_state = NULL; items = NULL; subfolders = NULL; level = 0; complete = INVALID_HANDLE_VALUE; callback = NULL;
} }
HRESULT __stdcall OnStart(REFGUID Context) { return S_OK; } HRESULT __stdcall OnStart(REFGUID Context) { return S_OK; }
@ -239,18 +231,13 @@ public:
} }
DWORD wait_for_messages(int seconds=60) { DWORD wait_for_messages(int seconds=60) {
release_python_gil(); DWORD wait_result;
DWORD wait_result = MsgWaitForMultipleObjects(1, &complete, FALSE, seconds * 1000, QS_ALLEVENTS); Py_BEGIN_ALLOW_THREADS;
acquire_python_gil(); wait_result = MsgWaitForMultipleObjects(1, &complete, FALSE, seconds * 1000, QS_ALLEVENTS);
Py_END_ALLOW_THREADS;
return wait_result; return wait_result;
} }
int pump_waiting_messages() {
release_python_gil();
int pump_result = _pump_waiting_messages();
acquire_python_gil();
return pump_result;
}
}; };
@ -291,11 +278,10 @@ bulk_get_filesystem(
while (!PyErr_Occurred()) { while (!PyErr_Occurred()) {
DWORD wait_result = bulk_properties_callback->wait_for_messages(); DWORD wait_result = bulk_properties_callback->wait_for_messages();
if (wait_result == WAIT_OBJECT_0) { if (wait_result == WAIT_OBJECT_0) {
break; // Event was signalled, bulk operation complete break; // Event was signalled, bulk operation complete
} else if (wait_result == WAIT_OBJECT_0 + 1) { // Messages need to be dispatched } else if (wait_result == WAIT_OBJECT_0 + 1) { // Messages need to be dispatched
int pump_result = bulk_properties_callback->pump_waiting_messages(); int pump_result = pump_waiting_messages();
if (pump_result == 1) PyErr_SetString(PyExc_RuntimeError, "Application has been asked to quit."); if (pump_result == 1) PyErr_SetString(PyExc_RuntimeError, "Application has been asked to quit.");
} else if (wait_result == WAIT_TIMEOUT) { } else if (wait_result == WAIT_TIMEOUT) {
// 60 seconds with no updates, looks bad // 60 seconds with no updates, looks bad
@ -311,7 +297,7 @@ bulk_get_filesystem(
bulk_properties_callback->end_processing(); bulk_properties_callback->end_processing();
if (PyErr_Occurred()) { if (PyErr_Occurred()) {
bulk_properties->Cancel(guid_context); bulk_properties->Cancel(guid_context);
bulk_properties_callback->pump_waiting_messages(); pump_waiting_messages();
} }
return PyErr_Occurred() ? false : true; return PyErr_Occurred() ? false : true;
} }