Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
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
View
3  xbmc/interfaces/legacy/Monitor.cpp
@@ -36,7 +36,8 @@ namespace XBMCAddon
Monitor::~Monitor()
{
- deallocating();
+ deallocating();
+ DelayedCallGuard dg(languageHook);
// we're shutting down so unregister me.
if (languageHook)
{
View
57 xbmc/interfaces/python/LanguageHook.cpp
@@ -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()
View
2  xbmc/interfaces/python/LanguageHook.h
@@ -47,8 +47,6 @@ namespace XBMCAddon
{
LanguageHook() : XBMCAddon::LanguageHook("Python::LanguageHook") { }
- XbmcThreads::ThreadLocal<PyThreadState> pyThreadStateTls;
- XbmcThreads::ThreadLocal<MutableInteger> tlsCount;
public:
virtual ~LanguageHook();
View
2  xbmc/interfaces/python/Makefile.in
@@ -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@
View
115 xbmc/interfaces/python/PyContext.cpp
@@ -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
+ }
+ }
+ }
+ }
+}
View
53 xbmc/interfaces/python/PyContext.h
@@ -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(); }
+ };
+ }
+}
View
6 xbmc/interfaces/python/PythonSwig.cpp.template
@@ -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} <%
View
3  xbmc/interfaces/python/XBPyThread.cpp
@@ -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.