OpenWalnut  1.4.0
WScriptInterpreterPython.h
00001 //---------------------------------------------------------------------------
00002 //
00003 // Project: OpenWalnut ( http://www.openwalnut.org )
00004 //
00005 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
00006 // For more information see http://www.openwalnut.org/copying
00007 //
00008 // This file is part of OpenWalnut.
00009 //
00010 // OpenWalnut is free software: you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as published by
00012 // the Free Software Foundation, either version 3 of the License, or
00013 // (at your option) any later version.
00014 //
00015 // OpenWalnut is distributed in the hope that it will be useful,
00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 // GNU Lesser General Public License for more details.
00019 //
00020 // You should have received a copy of the GNU Lesser General Public License
00021 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
00022 //
00023 //---------------------------------------------------------------------------
00024 
00025 #ifndef WSCRIPTINTERPRETERPYTHON_H
00026 #define WSCRIPTINTERPRETERPYTHON_H
00027 
00028 #ifdef PYTHON_FOUND
00029 
00030 #include <queue>
00031 #include <string>
00032 #include <vector>
00033 
00034 #include <boost/thread/mutex.hpp>
00035 #include <boost/python.hpp>
00036 
00037 #include "../../common/WThreadedRunner.h"
00038 
00039 #include "../wrappers/WLoggerWrapper.h"
00040 #include "../wrappers/WModuleContainerWrapper.h"
00041 
00042 #include "../WScriptInterpreter.h"
00043 
00044 namespace pb = boost::python;
00045 
00046 /**
00047  * \class WScriptInterpreterPython
00048  *
00049  * An interpreter for python scripts.
00050  */
00051 class WScriptInterpreterPython : public WScriptInterpreter
00052 {
00053 public:
00054     /**
00055      * Constructor. Creates the interpreter.
00056      */
00057     explicit WScriptInterpreterPython( boost::shared_ptr< WModuleContainer > const& rootContainer );
00058 
00059     /**
00060      * Destructor. Destroys the interpreter.
00061      */
00062     virtual ~WScriptInterpreterPython();
00063 
00064     /**
00065      * Initializes bindings for OpenWalnut classes. Call this after starting the kernel.
00066      */
00067     virtual void initBindings();
00068 
00069     /**
00070      * Sets the script parameters. These are the parameters you would normally call your script with, e.g.
00071      * "./myscript.py param 1 param2".
00072      *
00073      * \param params The parameters to the script. In our example, they would be "./myscript.py", "param", "1" and "param2".
00074      */
00075     virtual void setParameters( std::vector< std::string > const& params );
00076 
00077     /**
00078      * Execute some python code.
00079      *
00080      * \param line The code to execute.
00081      */
00082     virtual void execute( std::string const& line );
00083 
00084     /**
00085      * Execute a script in a seperate thread. This function returns immediately.
00086      *
00087      * \param script The script to execute.
00088      */
00089     virtual void executeAsync( std::string const& script );
00090 
00091     /**
00092      * Execute a file.
00093      *
00094      * \param filename The script file to execute.
00095      */
00096     virtual void executeFile( std::string const& filename );
00097 
00098     /**
00099      * Execute a script file in a seperate thread. This function returns immediately.
00100      *
00101      * \param filename The script file to execute.
00102      */
00103     virtual void executeFileAsync( std::string const& filename );
00104 
00105     /**
00106      * Get the name of the language interpreted by this interpreter.
00107      *
00108      * \return The name of the script language.
00109      */
00110     virtual std::string const getName() const;
00111 
00112     /**
00113      * Get the default extension for script file belonging to the script interpreter's language.
00114      *
00115      * \return The default file extension.
00116      */
00117     virtual std::string const getExtension() const;
00118 
00119 private:
00120     /**
00121      * A thread that executes scripts from a queue.
00122      */
00123     class ScriptThread : public WThreadedRunner
00124     {
00125     public:
00126         /**
00127          * Create a thread.
00128          */
00129         explicit ScriptThread( WScriptInterpreterPython& interpreter ); // NOLINT reference
00130 
00131         /**
00132          * Destructor.
00133          */
00134         virtual ~ScriptThread();
00135 
00136         /**
00137          * Executes scripts stored in the script queue and sleeps as long as no
00138          * scripts are in the queue.
00139          */
00140         virtual void threadMain();
00141 
00142         /**
00143          * Adds a script string to the queue. This is a thread-safe operation.
00144          *
00145          * \param script The script to add.
00146          */
00147         void addToExecuteQueue( std::string const& script );
00148 
00149         /**
00150          * Request this script thread to stop. Returns immediatly.
00151          */
00152         void requestStop();
00153 
00154     private:
00155         //! A queue for scripts to be executed.
00156         std::queue< std::string > m_scriptQueue;
00157 
00158         //! A mutex for thread-safe adding to the queue.
00159         boost::mutex m_queueMutex;
00160 
00161         //! A condition to be notified when a new script is added.
00162         boost::shared_ptr< WCondition > m_condition;
00163 
00164         //! A condition set used for immidiate returns on wait() if it was notified beforehand.
00165         WConditionSet m_conditionSet;
00166 
00167         //! A reference to the interpreter this thread belongs to.
00168         WScriptInterpreterPython& m_interpreter;
00169     };
00170 
00171     //! The python module.
00172     pb::object m_pyModule;
00173 
00174     //! The namespace where we will be working. Bindings are declared in this workspace.
00175     pb::object m_pyMainNamespace;
00176 
00177     //! A pointer to the kernel's root container. We can use this to manipulate modules.
00178     WModuleContainerWrapper m_rootContainer;
00179 
00180     //! The logger.
00181     WLoggerWrapper m_logger;
00182 
00183     //! The number of args passed when calling the script.
00184     int m_argc;
00185 
00186     //! The args passed to the script.
00187     char** m_argv;
00188 
00189     //! A mutex for safe execution of scripts.
00190     boost::mutex m_mutex;
00191 
00192     //! A thread for asynchronous execution of scripts.
00193     ScriptThread m_scriptThread;
00194 };
00195 
00196 #endif  // PYTHON_FOUND
00197 
00198 #endif  // WSCRIPTINTERPRETERPYTHON_H