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 Original line Diff line number Diff line
@@ -55,7 +55,7 @@
#include <dialog_helpers.h>
#include <dialog_helpers.h>
#include <convert_from_iu.h>
#include <convert_from_iu.h>


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


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



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


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


#include <stdio.h>
#include <stdio.h>



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

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



PYTHON_FOOTPRINT_WIZARD::~PYTHON_FOOTPRINT_WIZARD()
PYTHON_FOOTPRINT_WIZARD::~PYTHON_FOOTPRINT_WIZARD()
{
{
    PyLOCK  lock;

    Py_XDECREF( this->m_PyWizard );
    Py_XDECREF( this->m_PyWizard );
}
}



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


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


    if( pFunc && PyCallable_Check( pFunc ) )
    if( pFunc && PyCallable_Check( pFunc ) )
    {
    {
        PyObject *result;
        PyObject* result = PyObject_CallObject( pFunc, aArglist );

        PY_BLOCK_THREADS( blocked );

        result = PyObject_CallObject( pFunc, aArglist );


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

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


        PY_UNBLOCK_THREADS( blocked );

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

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



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


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

         PY_UNBLOCK_THREADS( blocked );
    }
    }
    return ret;
    return ret;
}
}



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


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


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


         PY_BLOCK_THREADS( blocked );

         int list_size = PyList_Size( result );
         int list_size = PyList_Size( result );


         for ( int n=0; n<list_size; n++ )
         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 );
            const char* str_res = PyString_AsString( element );

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


         Py_DECREF( result );
         Py_DECREF( result );

         PY_UNBLOCK_THREADS( blocked );
    }
    }




    return ret;
    return ret;

}
}



wxString PYTHON_FOOTPRINT_WIZARD::GetName()
wxString PYTHON_FOOTPRINT_WIZARD::GetName()
{
{
    PyLOCK      lock;

    return CallRetStrMethod( "GetName" );
    return CallRetStrMethod( "GetName" );
}
}



wxString PYTHON_FOOTPRINT_WIZARD::GetImage()
wxString PYTHON_FOOTPRINT_WIZARD::GetImage()
{
{
    PyLOCK      lock;

    return CallRetStrMethod( "GetImage" );
    return CallRetStrMethod( "GetImage" );
}
}



wxString PYTHON_FOOTPRINT_WIZARD::GetDescription()
wxString PYTHON_FOOTPRINT_WIZARD::GetDescription()
{
{
    PyLOCK      lock;

    return CallRetStrMethod( "GetDescription" );
    return CallRetStrMethod( "GetDescription" );
}
}



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


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


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


         PY_BLOCK_THREADS( blocked );

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

         PY_UNBLOCK_THREADS( blocked );
    }
    }

    return ret;
    return ret;
}
}



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

    // 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 );
    Py_DECREF( arglist );


    if( result )
    if( result )
    {
    {
         PY_BLOCK_THREADS( blocked );

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

         PY_UNBLOCK_THREADS( blocked );
    }
    }
    return ret;
    return ret;
}
}



wxArrayString PYTHON_FOOTPRINT_WIZARD::GetParameterNames( int aPage )
wxArrayString PYTHON_FOOTPRINT_WIZARD::GetParameterNames( int aPage )
{
{

    PyObject *arglist;
    wxArrayString ret;
    wxArrayString ret;
    PyLOCK  lock;


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


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



    return ret;
    return ret;
}
}



wxArrayString PYTHON_FOOTPRINT_WIZARD::GetParameterTypes( int aPage )
wxArrayString PYTHON_FOOTPRINT_WIZARD::GetParameterTypes( int aPage )
{
{

    PyObject *arglist;
    wxArrayString   ret;
    wxArrayString   ret;
    PyLOCK          lock;


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


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



    return ret;
    return ret;
}
}





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

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

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


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


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


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


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

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


    return ret;
    return ret;
}
}



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

    int len = aValues.size();
    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++ )
    for ( int i=0; i<len ; i++ )
    {
    {
@@ -287,20 +286,21 @@ wxString PYTHON_FOOTPRINT_WIZARD::SetParameterValues( int aPage, wxArrayString&
    return res;
    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* PyModule_to_MODULE( PyObject* obj0 );



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

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


    if( !result )
    if( !result )
        return NULL;
        return NULL;


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

    obj = PyObject_GetAttrString( result, "this" );


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


    MODULE* mod = PyModule_to_MODULE( obj );
    MODULE* mod = PyModule_to_MODULE( obj );


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


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

    fw = new PYTHON_FOOTPRINT_WIZARD( aPyWizard );




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


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


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


}
}

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


bool pcbnewInitPythonScripting()
bool pcbnewInitPythonScripting()
{
{

    swigAddBuiltin();           // add builtin functions
    swigAddBuiltin();           // add builtin functions
    swigAddModules();           // add our own modules
    swigAddModules();           // add our own modules
    swigSwitchPythonBuiltin();  // switch the python builtin modules to our new list
    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
    // load pcbnew inside python, and load all the user plugins, TODO: add system wide plugins


    PY_BLOCK_THREADS( blocked );
#endif
#endif


    {
        PyLOCK  lock;

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


    PY_UNBLOCK_THREADS( blocked );
    return true;
    return true;
}
}


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




#ifdef KICAD_SCRIPTING_WXPYTHON
#if defined(KICAD_SCRIPTING_WXPYTHON)


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


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




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


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


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

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



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





#ifdef KICAD_SCRIPTING_WXPYTHON
#ifdef KICAD_SCRIPTING_WXPYTHON


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


#define PY_BLOCK_THREADS(name)    wxPyBlock_t name = wxPyBeginBlockThreads()
class PyLOCK
#define PY_UNBLOCK_THREADS(name)    wxPyEndBlockThreads(name)
{
    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
#else


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


#endif
#endif


#endif
#endif  // __PYTHON_SCRIPTING_H
+4 −4

File changed.

Contains only whitespace changes.