Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Gil handling is more flexible now and use of the DelayedCallGuard is …

…not so tempermental. Also added the DelayedCallGuard to the Montior destructor.
  • Loading branch information...
commit 3fd761d14edc4576ef58eb0daeb532eee0d34f13 1 parent 5417cfb
Jim Carroll authored
3  xbmc/interfaces/legacy/Monitor.cpp
View
@@ -36,7 +36,8 @@ namespace XBMCAddon
Monitor::~Monitor()
{
- deallocating();
+ deallocating();
+ DelayedCallGuard dg(languageHook);
// we're shutting down so unregister me.
if (languageHook)
{
57 xbmc/interfaces/python/LanguageHook.cpp
View
@@ -25,6 +25,7 @@
#include "interfaces/legacy/AddonUtils.h"
#include "utils/GlobalsHandling.h"
+#include "PyContext.h"
namespace XBMCAddon
{
@@ -39,12 +40,6 @@ namespace XBMCAddon
// vtab instantiation
LanguageHook::~LanguageHook() { }
- struct MutableInteger
- {
- MutableInteger() : value(0) {}
- int value;
- };
-
void LanguageHook::makePendingCalls()
{
PythonCallbackHandler::makePendingCalls();
@@ -53,59 +48,13 @@ namespace XBMCAddon
void LanguageHook::delayedCallOpen()
{
TRACE;
-
- // TODO: add a check for null of _save. If it's not null there's
- // a problem.
-
- MutableInteger* count = tlsCount.get();
- if (count == NULL)
- {
- count = new MutableInteger();
- tlsCount.set(count);
- }
-
- // increment the count
- count->value++;
- int curlevel = count->value;
- if (curlevel == 1)
- {
- PyThreadState* _save;
- // this macro sets _save
- Py_UNBLOCK_THREADS
- pyThreadStateTls.set(_save);
- }
+ PyGILLock::releaseGil();
}
void LanguageHook::delayedCallClose()
{
TRACE;
-
- // here we ASSUME that the open was called.
- MutableInteger* count = tlsCount.get();
- count->value--;
- int curlevel = count->value;
-
- // this is a hack but ...
- if (curlevel < 0)
- {
- CLog::Log(LOGERROR, "PythonCallbackHandler delay has closed more than opened");
- count->value = 0;
- }
-
- if (curlevel == 0)
- {
- PyThreadState* _save = pyThreadStateTls.get();
- if (_save != NULL)
- {
- Py_BLOCK_THREADS
- }
- _save = NULL;
- pyThreadStateTls.set(_save);
-
- // clear the tlsCount
- tlsCount.set(NULL);
- delete count;
- }
+ PyGILLock::acquireGil();
}
LanguageHook* LanguageHook::getInstance()
2  xbmc/interfaces/python/LanguageHook.h
View
@@ -47,8 +47,6 @@ namespace XBMCAddon
{
LanguageHook() : XBMCAddon::LanguageHook("Python::LanguageHook") { }
- XbmcThreads::ThreadLocal<PyThreadState> pyThreadStateTls;
- XbmcThreads::ThreadLocal<MutableInteger> tlsCount;
public:
virtual ~LanguageHook();
2  xbmc/interfaces/python/Makefile.in
View
@@ -14,7 +14,7 @@ all: $(LIB)
include ../../../codegenerator.mk
SRCS= CallbackHandler.cpp LanguageHook.cpp \
- XBPyThread.cpp XBPython.cpp swig.cpp \
+ XBPyThread.cpp XBPython.cpp swig.cpp PyContext.cpp \
$(GENERATED)
INCLUDES += @PYTHON_CPPFLAGS@
115 xbmc/interfaces/python/PyContext.cpp
View
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2005-2012 Team XBMC
+ * http://www.xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+
+#include <Python.h>
+
+#include "PyContext.h"
+#include "threads/ThreadLocal.h"
+#include "utils/log.h"
+
+namespace XBMCAddon
+{
+ namespace Python
+ {
+ struct PyContextState
+ {
+ inline PyContextState() : value(0), state(NULL), gilReleasedDepth(0) {}
+
+ int value;
+ PyThreadState* state;
+ int gilReleasedDepth;
+ };
+
+ static XbmcThreads::ThreadLocal<PyContextState> tlsPyContextState;
+
+ PyContext::PyContext()
+ {
+ PyContextState* cur = tlsPyContextState.get();
+ if (cur == NULL)
+ {
+ cur = new PyContextState();
+ tlsPyContextState.set(cur);
+ }
+
+ // increment the count
+ cur->value++;
+ }
+
+ PyContext::~PyContext()
+ {
+ // here we ASSUME that the constructor was called.
+ PyContextState* cur = tlsPyContextState.get();
+ cur->value--;
+ int curlevel = cur->value;
+
+ // this is a hack but ...
+ if (curlevel < 0)
+ {
+ CLog::Log(LOGERROR, "FATAL: PyContext closed more than opened");
+ curlevel = cur->value = 0;
+ }
+
+ if (curlevel == 0)
+ {
+ // clear the tlsPyContextState
+ tlsPyContextState.set(NULL);
+ delete cur;
+ }
+ }
+
+ void PyGILLock::releaseGil()
+ {
+ PyContextState* cur = tlsPyContextState.get();
+ if (cur) // this means we're within the python context
+ {
+ if (cur->gilReleasedDepth == 0) // true if we are at the outermost
+ {
+ PyThreadState* _save;
+ // this macro sets _save
+ {
+ Py_UNBLOCK_THREADS
+ }
+ cur->state = _save;
+ }
+ cur->gilReleasedDepth++; // the first time this goes to 1
+ }
+ }
+
+ void PyGILLock::acquireGil()
+ {
+ PyContextState* cur = tlsPyContextState.get(); // this must be non-null given we released the Gil in the constructor
+ if (cur) // we're within a PyContext
+ {
+ // decrement the depth and make sure we're in the right place.
+ cur->gilReleasedDepth--;
+ if (cur->gilReleasedDepth == 0) // are we back to zero?
+ {
+ PyThreadState* _save = cur->state;
+ // This macros uses _save
+ {
+ Py_BLOCK_THREADS
+ }
+ cur->state = NULL; // clear the state to indicate we've reacquired the gil
+ }
+ }
+ }
+ }
+}
53 xbmc/interfaces/python/PyContext.h
View
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2005-2012 Team XBMC
+ * http://www.xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+namespace XBMCAddon
+{
+ namespace Python
+ {
+ /**
+ * These classes should NOT be used with 'new'. They are expected to reside
+ * as stack instances and they act as "Guard" classes that track the
+ * current context.
+ */
+ class PyContext
+ {
+ protected:
+ public:
+ PyContext();
+ ~PyContext();
+ };
+
+ /**
+ * This class supports recursive locking of the GIL. It assumes that
+ * all Python GIL manipulation is done through this class so that it
+ * can monitor the current owner.
+ */
+ class PyGILLock
+ {
+ public:
+ static void releaseGil();
+ static void acquireGil();
+
+ inline PyGILLock() { releaseGil(); }
+ inline ~PyGILLock() { acquireGil(); }
+ };
+ }
+}
6 xbmc/interfaces/python/PythonSwig.cpp.template
View
@@ -488,8 +488,9 @@ Helper.getInsertNodes(module, 'begin').each { %>${Helper.unescape(it)}<% }
#include <Python.h>
#include <string>
-#include "interfaces/python/LanguageHook.h"
-#include "interfaces/python/swig.h"
+#include "LanguageHook.h"
+#include "swig.h"
+#include "PyContext.h"
<%
Helper.getInsertNodes(module, 'header').each { %>${Helper.unescape(it)}<% }
@@ -563,6 +564,7 @@ namespace PythonBindings
${Helper.getOutConversion(param.@type,'result',it,['result' : 'py' + param.@name, 'api' : param.@name])}<%
}
%>
+ XBMCAddon::Python::PyContext pyContext;
PyObject_CallMethod(self,(char*)"${Helper.callingName(it)}",(char*)"(${paramFormatStr})"<%
params.each {
%>, py${it.@name} <%
3  xbmc/interfaces/python/XBPyThread.cpp
View
@@ -51,7 +51,7 @@
#include "interfaces/python/pythreadstate.h"
#include "interfaces/python/swig.h"
#include "utils/CharsetConverter.h"
-
+#include "PyContext.h"
#ifdef _WIN32
extern "C" FILE *fopen_utf8(const char *_Filename, const char *_Mode);
@@ -266,6 +266,7 @@ void XBPyThread::Process()
CLog::Log(LOGDEBUG,"Instantiating addon using automatically obtained id of \"%s\" dependent on version %s of the xbmc.python api",addon->ID().c_str(),version.c_str());
}
Py_DECREF(f);
+ XBMCAddon::Python::PyContext pycontext; // this is a guard class that marks this callstack as being in a python context
PyRun_FileExFlags(fp, CSpecialProtocol::TranslatePath(m_source).c_str(), m_Py_file_input, moduleDict, moduleDict,1,NULL);
}
else
Please sign in to comment.
Something went wrong with that request. Please try again.