run a thread for each call
This commit is contained in:
parent
125aee7153
commit
68e9c82758
@ -128,23 +128,22 @@ void PythonIntegrationPlugin::initPython()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Spawn a event loop for python
|
||||
// // Spawn a event loop for python
|
||||
s_asyncio = PyImport_ImportModule("asyncio");
|
||||
PyObject *get_event_loop = PyObject_GetAttrString(s_asyncio, "get_event_loop");
|
||||
PyObject *loop = PyObject_CallFunctionObjArgs(get_event_loop, nullptr);
|
||||
PyObject *run_forever = PyObject_GetAttrString(loop, "run_forever");
|
||||
// PyObject *get_event_loop = PyObject_GetAttrString(s_asyncio, "get_event_loop");
|
||||
// PyObject *loop = PyObject_CallFunctionObjArgs(get_event_loop, nullptr);
|
||||
// PyObject *run_forever = PyObject_GetAttrString(loop, "run_forever");
|
||||
|
||||
|
||||
// QtConcurrent::run([=](){
|
||||
// PyGILState_STATE s = PyGILState_Ensure();
|
||||
// PyObject_CallFunctionObjArgs(run_forever, nullptr);
|
||||
// PyGILState_Release(s);
|
||||
// });
|
||||
|
||||
|
||||
// Need to release ths lock from the main thread before spawning the new thread
|
||||
s_mainThread = PyEval_SaveThread();
|
||||
|
||||
QtConcurrent::run([=](){
|
||||
PyGILState_STATE s = PyGILState_Ensure();
|
||||
PyObject_CallFunctionObjArgs(run_forever, nullptr);
|
||||
PyGILState_Release(s);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
bool PythonIntegrationPlugin::loadScript(const QString &scriptFile)
|
||||
@ -205,11 +204,14 @@ void PythonIntegrationPlugin::init()
|
||||
|
||||
void PythonIntegrationPlugin::discoverThings(ThingDiscoveryInfo *info)
|
||||
{
|
||||
PyThingDiscoveryInfo *pyInfo = reinterpret_cast<PyThingDiscoveryInfo*>(_PyObject_New(&PyThingDiscoveryInfoType));
|
||||
PyThingDiscoveryInfo *pyInfo = PyObject_New(PyThingDiscoveryInfo, &PyThingDiscoveryInfoType);
|
||||
pyInfo->ptrObj = info;
|
||||
|
||||
connect(info, &ThingDiscoveryInfo::finished, this, [=](){
|
||||
PyObject_Free(pyInfo);
|
||||
connect(info, &ThingDiscoveryInfo::destroyed, this, [=](){
|
||||
PyGILState_STATE s = PyGILState_Ensure();
|
||||
pyInfo->ptrObj = nullptr;
|
||||
PyObject_Del(pyInfo);
|
||||
PyGILState_Release(s);
|
||||
});
|
||||
|
||||
callPluginFunction("discoverThings", reinterpret_cast<PyObject*>(pyInfo));
|
||||
@ -217,18 +219,34 @@ void PythonIntegrationPlugin::discoverThings(ThingDiscoveryInfo *info)
|
||||
|
||||
void PythonIntegrationPlugin::setupThing(ThingSetupInfo *info)
|
||||
{
|
||||
PyThing *pyThing = reinterpret_cast<PyThing*>(_PyObject_New(&PyThingType));
|
||||
PyThing *pyThing = PyObject_New(PyThing, &PyThingType);
|
||||
pyThing->ptrObj = info->thing();
|
||||
m_things.insert(info->thing(), pyThing);
|
||||
Py_INCREF(pyThing);
|
||||
|
||||
PyThingSetupInfo *pyInfo = reinterpret_cast<PyThingSetupInfo*>(_PyObject_New(&PyThingSetupInfoType));
|
||||
PyThingSetupInfo *pyInfo = PyObject_New(PyThingSetupInfo, &PyThingSetupInfoType);
|
||||
pyInfo->ptrObj = info;
|
||||
pyInfo->thing = pyThing;
|
||||
|
||||
|
||||
connect(info, &ThingSetupInfo::finished, this, [=](){
|
||||
PyObject_Free(pyInfo);
|
||||
if (info->status() == Thing::ThingErrorNoError) {
|
||||
m_things.insert(info->thing(), pyThing);
|
||||
} else {
|
||||
PyGILState_STATE s = PyGILState_Ensure();
|
||||
Py_DECREF(pyThing);
|
||||
PyGILState_Release(s);
|
||||
}
|
||||
});
|
||||
connect(info, &ThingSetupInfo::aborted, this, [=](){
|
||||
PyGILState_STATE s = PyGILState_Ensure();
|
||||
Py_DECREF(pyThing);
|
||||
PyGILState_Release(s);
|
||||
});
|
||||
connect(info, &ThingSetupInfo::destroyed, this, [=](){
|
||||
PyGILState_STATE s = PyGILState_Ensure();
|
||||
PyObject_Del(pyInfo);
|
||||
PyGILState_Release(s);
|
||||
});
|
||||
|
||||
|
||||
callPluginFunction("setupThing", reinterpret_cast<PyObject*>(pyInfo));
|
||||
}
|
||||
@ -390,14 +408,14 @@ void PythonIntegrationPlugin::exportBrowserItemActionTypes(const ActionTypes &ac
|
||||
|
||||
void PythonIntegrationPlugin::callPluginFunction(const QString &function, PyObject *param)
|
||||
{
|
||||
PyGILState_STATE s = PyGILState_Ensure();
|
||||
PyEval_RestoreThread(s_mainThread);
|
||||
|
||||
qCDebug(dcThingManager()) << "Calling python plugin function" << function;
|
||||
PyObject *pFunc = PyObject_GetAttrString(m_module, function.toUtf8());
|
||||
if(!pFunc || !PyCallable_Check(pFunc)) {
|
||||
Py_XDECREF(pFunc);
|
||||
qCWarning(dcThingManager()) << "Python plugin does not implement" << function;
|
||||
PyGILState_Release(s);
|
||||
s_mainThread = PyEval_SaveThread();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -411,20 +429,21 @@ void PythonIntegrationPlugin::callPluginFunction(const QString &function, PyObje
|
||||
if (PyErr_Occurred()) {
|
||||
qCWarning(dcThingManager()) << "Error calling python method:";
|
||||
dumpError();
|
||||
PyGILState_Release(s);
|
||||
s_mainThread = PyEval_SaveThread();
|
||||
return;
|
||||
}
|
||||
|
||||
if (QByteArray(future->ob_type->tp_name) != "coroutine") {
|
||||
PyGILState_Release(s);
|
||||
s_mainThread = PyEval_SaveThread();
|
||||
return;
|
||||
}
|
||||
|
||||
PyObject *get_event_loop = PyObject_GetAttrString(s_asyncio, "get_event_loop");
|
||||
PyObject *loop = PyObject_CallFunctionObjArgs(get_event_loop, nullptr);
|
||||
// Spawn a event loop for python
|
||||
PyObject *new_event_loop = PyObject_GetAttrString(s_asyncio, "new_event_loop");
|
||||
PyObject *loop = PyObject_CallFunctionObjArgs(new_event_loop, nullptr);
|
||||
|
||||
PyObject *run_coroutine_threadsafe = PyObject_GetAttrString(s_asyncio, "run_coroutine_threadsafe");
|
||||
PyObject *task = PyObject_CallFunctionObjArgs(run_coroutine_threadsafe, future, loop, nullptr);
|
||||
PyObject *run_coroutine_threadsafe = PyObject_GetAttrString(loop, "create_task");
|
||||
PyObject *task = PyObject_CallFunctionObjArgs(run_coroutine_threadsafe, future, nullptr);
|
||||
dumpError();
|
||||
|
||||
PyObject *add_done_callback = PyObject_GetAttrString(task, "add_done_callback");
|
||||
@ -434,14 +453,20 @@ void PythonIntegrationPlugin::callPluginFunction(const QString &function, PyObje
|
||||
PyObject *result = PyObject_CallFunctionObjArgs(add_done_callback, task_done, nullptr);
|
||||
dumpError();
|
||||
|
||||
Py_DECREF(get_event_loop);
|
||||
PyObject *run_forever = PyObject_GetAttrString(loop, "run_until_complete");
|
||||
QtConcurrent::run([=](){
|
||||
PyGILState_STATE s = PyGILState_Ensure();
|
||||
PyObject_CallFunctionObjArgs(run_forever, task, nullptr);
|
||||
PyGILState_Release(s);
|
||||
});
|
||||
|
||||
Py_DECREF(new_event_loop);
|
||||
Py_DECREF(loop);
|
||||
Py_DECREF(run_coroutine_threadsafe);
|
||||
Py_DECREF(task);
|
||||
Py_DECREF(add_done_callback);
|
||||
Py_DECREF(get_event_loop);
|
||||
Py_DECREF(result);
|
||||
|
||||
PyGILState_Release(s);
|
||||
s_mainThread = PyEval_SaveThread();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user