Commit 2a2a530c authored by Dick Hollenbeck's avatar Dick Hollenbeck
Browse files

improvements to python's GIL acquisition and release, but not done yet, since...

improvements to python's GIL acquisition and release, but not done yet, since I think the GIL needs to be acquired even when not involving wxPython.
parent a88d067a
Loading
Loading
Loading
Loading
+3 −4
Original line number Diff line number Diff line
@@ -55,7 +55,7 @@
#include <dialog_helpers.h>
#include <convert_from_iu.h>

#ifdef KICAD_SCRIPTING
#if defined(KICAD_SCRIPTING) || defined(KICAD_SCRIPTING_WXPYTHON)
#include <python_scripting.h>
#endif

@@ -426,7 +426,6 @@ PCB_EDIT_FRAME::PCB_EDIT_FRAME( wxWindow* parent, const wxString& title,
    m_pythonPanelHidden = true;
#endif


    ReFillLayerWidget();        // this is near end because contents establish size

    m_Layers->ReFillRender();   // Update colors in Render after the config is read
+120 −125
Original line number Diff line number Diff line
@@ -8,49 +8,52 @@

#include <stdio.h>


PYTHON_FOOTPRINT_WIZARD::PYTHON_FOOTPRINT_WIZARD( PyObject* aWizard )
{
    PyLOCK  lock;

    this->m_PyWizard= aWizard;
    Py_XINCREF( aWizard );
}


PYTHON_FOOTPRINT_WIZARD::~PYTHON_FOOTPRINT_WIZARD()
{
    PyLOCK  lock;

    Py_XDECREF( this->m_PyWizard );
}


PyObject* PYTHON_FOOTPRINT_WIZARD::CallMethod( const char* aMethod, PyObject* aArglist )
{
     PyObject *pFunc;
    PyLOCK  lock;

    /* pFunc is a new reference to the desired method */
    pFunc = PyObject_GetAttrString( this->m_PyWizard, aMethod );
    // pFunc is a new reference to the desired method
    PyObject* pFunc = PyObject_GetAttrString( this->m_PyWizard, aMethod );

    if( pFunc && PyCallable_Check( pFunc ) )
    {
        PyObject *result;

        PY_BLOCK_THREADS( blocked );

        result = PyObject_CallObject( pFunc, aArglist );
        PyObject* result = PyObject_CallObject( pFunc, aArglist );

        if( PyErr_Occurred() )
        {
            PyObject *t, *v, *b;
            PyObject* t;
            PyObject* v;
            PyObject* b;

            PyErr_Fetch( &t, &v, &b );
            printf ( "calling %s()\n", aMethod );
            printf ( "Exception: %s\n", PyString_AsString( PyObject_Str( v ) ) );
            printf ( "         : %s\n", PyString_AsString( PyObject_Str( b ) ) );
        }

        PY_UNBLOCK_THREADS( blocked );

        if( result )
        {
            Py_XDECREF( pFunc );
            return result;
        }

    }
    else
    {
@@ -63,32 +66,31 @@ PyObject* PYTHON_FOOTPRINT_WIZARD::CallMethod(const char* aMethod, PyObject *aAr
    return NULL;
}


wxString PYTHON_FOOTPRINT_WIZARD::CallRetStrMethod( const char* aMethod, PyObject* aArglist )
{
    wxString    ret;
    PyLOCK      lock;

    ret.Clear();
    PyObject* result = CallMethod( aMethod, aArglist );
    if( result )
    {
         PY_BLOCK_THREADS( blocked );
         const char* str_res = PyString_AsString( result );
         ret  = wxString::FromUTF8( str_res );
         Py_DECREF( result );

         PY_UNBLOCK_THREADS( blocked );
    }
    return ret;
}


wxArrayString PYTHON_FOOTPRINT_WIZARD::CallRetArrayStrMethod
                        ( const char* aMethod, PyObject* aArglist )
{
    PyObject *result, *element;
    wxArrayString ret;
    wxString    str_item;
    PyLOCK      lock;

    result = CallMethod( aMethod, aArglist );
    PyObject* result = CallMethod( aMethod, aArglist );

    if( result )
    {
@@ -99,99 +101,97 @@ wxArrayString PYTHON_FOOTPRINT_WIZARD::CallRetArrayStrMethod
             return ret;
         }

         PY_BLOCK_THREADS( blocked );

         int list_size = PyList_Size( result );

         for ( int n=0; n<list_size; n++ )
         {
            element = PyList_GetItem( result, n );
            PyObject*  element = PyList_GetItem( result, n );

            const char* str_res = PyString_AsString( element );

            str_item  = wxString::FromUTF8( str_res );
            ret.Add( str_item, 1 );
         }

         Py_DECREF( result );

         PY_UNBLOCK_THREADS( blocked );
    }



    return ret;

}


wxString PYTHON_FOOTPRINT_WIZARD::GetName()
{
    PyLOCK      lock;

    return CallRetStrMethod( "GetName" );
}


wxString PYTHON_FOOTPRINT_WIZARD::GetImage()
{
    PyLOCK      lock;

    return CallRetStrMethod( "GetImage" );
}


wxString PYTHON_FOOTPRINT_WIZARD::GetDescription()
{
    PyLOCK      lock;

    return CallRetStrMethod( "GetDescription" );
}


int PYTHON_FOOTPRINT_WIZARD::GetNumParameterPages()
{
    int         ret = 0;
    PyObject *result;
    PyLOCK      lock;

    /* Time to call the callback */
    result = CallMethod( "GetNumParameterPages" , NULL );
    // Time to call the callback
    PyObject*   result = CallMethod( "GetNumParameterPages" , NULL );

    if( result )
    {
         if( !PyInt_Check( result ) )
            return -1;

         PY_BLOCK_THREADS( blocked );

         ret = PyInt_AsLong( result );
         Py_DECREF( result );

         PY_UNBLOCK_THREADS( blocked );
    }

    return ret;
}


wxString PYTHON_FOOTPRINT_WIZARD::GetParameterPageName( int aPage )
{
    wxString    ret;
    PyObject *arglist;
    PyObject *result;
    PyLOCK      lock;

    // Time to call the callback
    PyObject* arglist = Py_BuildValue( "( i )", aPage );
    PyObject* result  = CallMethod( "GetParameterPageName", arglist );

    /* Time to call the callback */
    arglist = Py_BuildValue( "(i)", aPage );
    result = CallMethod( "GetParameterPageName", arglist );
    Py_DECREF( arglist );

    if( result )
    {
         PY_BLOCK_THREADS( blocked );

         const char* str_res = PyString_AsString( result );
         ret  = wxString::FromUTF8( str_res );
         Py_DECREF( result );

         PY_UNBLOCK_THREADS( blocked );
    }
    return ret;
}


wxArrayString PYTHON_FOOTPRINT_WIZARD::GetParameterNames( int aPage )
{

    PyObject *arglist;
    wxArrayString ret;
    PyLOCK  lock;

    arglist = Py_BuildValue( "(i)", aPage );
    PyObject* arglist = Py_BuildValue( "( i )", aPage );
    ret = CallRetArrayStrMethod( "GetParameterNames", arglist );
    Py_DECREF( arglist );

@@ -205,17 +205,16 @@ wxArrayString PYTHON_FOOTPRINT_WIZARD::GetParameterNames( int aPage )
        }
    }


    return ret;
}


wxArrayString PYTHON_FOOTPRINT_WIZARD::GetParameterTypes( int aPage )
{

    PyObject *arglist;
    wxArrayString   ret;
    PyLOCK          lock;

    arglist = Py_BuildValue( "(i)", aPage );
    PyObject* arglist = Py_BuildValue( "( i )", aPage );
    ret = CallRetArrayStrMethod( "GetParameterNames", arglist );
    Py_DECREF( arglist );

@@ -225,27 +224,26 @@ wxArrayString PYTHON_FOOTPRINT_WIZARD::GetParameterTypes( int aPage )
        wxString item = ret[i];
        if( item.StartsWith( wxT( "*" ), &rest ) )
        {
            ret[i]=wxT( "UNITS" ); /* units */
            ret[i] = wxT( "UNITS" );    // units
        }
        else
        {
            ret[i]=wxT( "IU" ); /* internal units */
            ret[i] = wxT( "IU" );       // internal units
        }
    }


    return ret;
}



wxArrayString PYTHON_FOOTPRINT_WIZARD::GetParameterValues( int aPage )
{
    PyObject *arglist;
    wxArrayString ret;
    PyLOCK  lock;

    PyObject* arglist = Py_BuildValue( "( i )", aPage );

    wxArrayString ret = CallRetArrayStrMethod( "GetParameterValues", arglist );

    arglist = Py_BuildValue( "(i)", aPage );
    ret = CallRetArrayStrMethod( "GetParameterValues", arglist );
    Py_DECREF( arglist );

    return ret;
@@ -253,23 +251,24 @@ wxArrayString PYTHON_FOOTPRINT_WIZARD::GetParameterValues( int aPage )

wxArrayString PYTHON_FOOTPRINT_WIZARD::GetParameterErrors( int aPage )
{
    PyObject *arglist;
    wxArrayString ret;
    PyLOCK  lock;

    arglist = Py_BuildValue( "(i)", aPage );
    ret = CallRetArrayStrMethod( "GetParameterErrors", arglist );
    PyObject* arglist = Py_BuildValue( "( i )", aPage );

    wxArrayString ret = CallRetArrayStrMethod( "GetParameterErrors", arglist );
    Py_DECREF( arglist );

    return ret;
}


wxString PYTHON_FOOTPRINT_WIZARD::SetParameterValues( int aPage, wxArrayString& aValues )
{

    int len = aValues.size();
    PyObject *py_list;

    py_list = PyList_New( len );
    PyLOCK  lock;

    PyObject* py_list = PyList_New( len );

    for ( int i=0; i<len ; i++ )
    {
@@ -287,20 +286,21 @@ wxString PYTHON_FOOTPRINT_WIZARD::SetParameterValues( int aPage, wxArrayString&
    return res;
}

/* this is a SWIG function declaration -from module.i*/

// this is a SWIG function declaration -from module.i
MODULE* PyModule_to_MODULE( PyObject* obj0 );


MODULE* PYTHON_FOOTPRINT_WIZARD::GetModule()
{
    PyObject *result, *obj;
    result = CallMethod( "GetModule", NULL );
    PyLOCK      lock;

    PyObject*   result = CallMethod( "GetModule", NULL );

    if( !result )
        return NULL;

    PY_BLOCK_THREADS( blocked );

    obj = PyObject_GetAttrString( result, "this" );
    PyObject* obj = PyObject_GetAttrString( result, "this" );

    if( PyErr_Occurred() )
    {
@@ -313,7 +313,6 @@ MODULE *PYTHON_FOOTPRINT_WIZARD::GetModule()
        */
        PyErr_Print();
    }
    PY_UNBLOCK_THREADS( blocked );

    MODULE* mod = PyModule_to_MODULE( obj );

@@ -323,9 +322,7 @@ MODULE *PYTHON_FOOTPRINT_WIZARD::GetModule()

void PYTHON_FOOTPRINT_WIZARDS::register_wizard( PyObject* aPyWizard )
{
    PYTHON_FOOTPRINT_WIZARD *fw;

    fw = new PYTHON_FOOTPRINT_WIZARD( aPyWizard );
    PYTHON_FOOTPRINT_WIZARD* fw = new PYTHON_FOOTPRINT_WIZARD( aPyWizard );


    //printf( "Registered python footprint wizard '%s'\n",
@@ -338,7 +335,7 @@ void PYTHON_FOOTPRINT_WIZARDS::register_wizard(PyObject* aPyWizard)
    fw->register_wizard();

#if 0
    /* just to test if it works correctly */
    // just to test if it works correctly
    int pages = fw->GetNumParameterPages();
    printf( "             %d pages\n",pages );

@@ -350,5 +347,3 @@ void PYTHON_FOOTPRINT_WIZARDS::register_wizard(PyObject* aPyWizard)
#endif

}

+15 −20
Original line number Diff line number Diff line
@@ -130,7 +130,6 @@ PyThreadState *g_PythonMainTState;

bool pcbnewInitPythonScripting()
{

    swigAddBuiltin();           // add builtin functions
    swigAddModules();           // add our own modules
    swigSwitchPythonBuiltin();  // switch the python builtin modules to our new list
@@ -158,16 +157,18 @@ bool pcbnewInitPythonScripting()

    // load pcbnew inside python, and load all the user plugins, TODO: add system wide plugins

    PY_BLOCK_THREADS( blocked );
#endif

    {
        PyLOCK  lock;

        PyRun_SimpleString( "import sys\n"
                            "sys.path.append(\".\")\n"
                            "import pcbnew\n"
                            "pcbnew.LoadPlugins()"
                            );
    }

    PY_UNBLOCK_THREADS( blocked );
    return true;
}

@@ -180,7 +181,7 @@ void pcbnewFinishPythonScripting()
}


#ifdef KICAD_SCRIPTING_WXPYTHON
#if defined(KICAD_SCRIPTING_WXPYTHON)

void RedirectStdio()
{
@@ -193,9 +194,8 @@ import wx\n\
output = wx.PyOnDemandOutputWindow()\n\
c sys.stderr = output\n";

    PY_BLOCK_THREADS( blocked );
    PyLOCK  lock;
    PyRun_SimpleString( python_redirect );
    PY_UNBLOCK_THREADS( blocked );
}


@@ -228,7 +228,7 @@ def makeWindow(parent):\n\
    PyObject* result;

    // As always, first grab the GIL
    PY_BLOCK_THREADS( blocked );
    PyLOCK  lock;

    // Now make a dictionary to serve as the global namespace when the code is
    // executed.  Put a reference to the builtins module in it.
@@ -245,7 +245,6 @@ def makeWindow(parent):\n\
    if( !result )
    {
        PyErr_Print();
        PY_UNBLOCK_THREADS( blocked );
        return NULL;
    }
    Py_DECREF(result);
@@ -285,10 +284,6 @@ def makeWindow(parent):\n\
    Py_DECREF( globals );
    Py_DECREF( tuple );

    // Finally, after all Python stuff is done, release the GIL
    PY_UNBLOCK_THREADS( blocked );

    return window;
}
#endif
+36 −22
Original line number Diff line number Diff line
@@ -17,7 +17,6 @@
#endif
#endif


/* Function pcbnewInitPythonScripting
 * Initializes the Python engine inside pcbnew
 */
@@ -26,20 +25,35 @@ bool pcbnewInitPythonScripting();
void pcbnewFinishPythonScripting();



#ifdef KICAD_SCRIPTING_WXPYTHON

void RedirectStdio();
wxWindow* CreatePythonShellWindow( wxWindow* parent );

#define PY_BLOCK_THREADS(name)    wxPyBlock_t name = wxPyBeginBlockThreads()
#define PY_UNBLOCK_THREADS(name)    wxPyEndBlockThreads(name)
class PyLOCK
{
    wxPyBlock_t     b;

public:

    // @todo, find out why these are wxPython specific.  We need the GIL regardless.
    // Should never assume python will only have one thread calling it.
    PyLOCK()    { b = wxPyBeginBlockThreads(); }
    ~PyLOCK()   { wxPyEndBlockThreads( b ); }
};


#else

#define PY_BLOCK_THREADS(name)    
#define PY_UNBLOCK_THREADS(name) 
class PyLOCK
{
public:
    // @todo: this is wrong, python docs clearly say we need the GIL,
    // irrespective of wxPython.
    PyLOCK()    {}
    ~PyLOCK()   {}
};

#endif

#endif
#endif  // __PYTHON_SCRIPTING_H
+4 −4

File changed.

Contains only whitespace changes.