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