summaryrefslogtreecommitdiffstats
path: root/xbmc/interfaces/python/CallbackHandler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'xbmc/interfaces/python/CallbackHandler.cpp')
-rw-r--r--xbmc/interfaces/python/CallbackHandler.cpp65
1 files changed, 65 insertions, 0 deletions
diff --git a/xbmc/interfaces/python/CallbackHandler.cpp b/xbmc/interfaces/python/CallbackHandler.cpp
new file mode 100644
index 0000000..8fd31a7
--- /dev/null
+++ b/xbmc/interfaces/python/CallbackHandler.cpp
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2005-2018 Team Kodi
+ * This file is part of Kodi - https://kodi.tv
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * See LICENSES/README.md for more information.
+ */
+
+#include "CallbackHandler.h"
+
+#include "LanguageHook.h"
+
+namespace XBMCAddon
+{
+ namespace Python
+ {
+ /**
+ * We are ASS-U-MEing that this construction is happening
+ * within the context of a Python call. This way we can
+ * store off the PyThreadState to later verify that we're
+ * handling callbacks in the appropriate thread.
+ */
+ PythonCallbackHandler::PythonCallbackHandler()
+ {
+ XBMC_TRACE;
+ objectThreadState = PyThreadState_Get();
+ }
+
+ /**
+ * Now we are answering the question as to whether or not we are in the
+ * PyThreadState that we were in when we started.
+ */
+ bool PythonCallbackHandler::isStateOk(AddonClass* obj)
+ {
+ XBMC_TRACE;
+ PyThreadState* state = PyThreadState_Get();
+ if (objectThreadState == state)
+ {
+ // make sure the interpreter is still active.
+ AddonClass::Ref<XBMCAddon::Python::PythonLanguageHook> lh(XBMCAddon::Python::PythonLanguageHook::GetIfExists(state->interp));
+ if (lh.isNotNull() && lh->HasRegisteredAddonClassInstance(obj) && lh.get() == obj->GetLanguageHook())
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * For this method we expect the PyThreadState to be passed as the user
+ * data for the check.
+ *
+ * @todo This is a stupid way to get this information back to the handler.
+ * there should be a more language neutral means.
+ */
+ bool PythonCallbackHandler::shouldRemoveCallback(AddonClass* obj, void* threadState)
+ {
+ XBMC_TRACE;
+ if (threadState == objectThreadState)
+ return true;
+
+ // we also want to remove the callback if the language hook no longer exists.
+ // this is a belt-and-suspenders cleanup mechanism
+ return ! XBMCAddon::Python::PythonLanguageHook::IsAddonClassInstanceRegistered(obj);
+ }
+ }
+}