PythonTimeDistribution.cc

00001 // Copyright 2008 Michael Marsh, University of Maryland.
00002 //
00003 // This file is part of pydtn.
00004 //
00005 // pydtn is free software: you can redistribute it and/or modify
00006 // it under the terms of the GNU General Public License as published by
00007 // the Free Software Foundation, either version 3 of the License, or
00008 // (at your option) any later version.
00009 //
00010 // pydtn is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU General Public License
00016 // along with pydtn.  If not, see <http://www.gnu.org/licenses/>.
00017 //
00018 // The views and conclusions contained in the software and documentation
00019 // are those of the authors and should not be interpreted as representing
00020 // official policies, either expressed or implied, of the University
00021 // of Maryland.
00022 //
00023 // pydtn extends and embeds the Python interpreter, which is
00024 // Copyright 2001-2006 Python Software Foundation, All Rights Reserved,
00025 // and is released under the PSF License Agreement.
00026 //
00027 // RANLUX random number generation uses the Boost library,
00028 // Copyright 1994-2006 by various authors (details in individual files),
00029 // which is released under the Boost Software License, Version 1.0.
00030 
00031 #include "simlpy/interpreter_defs.h"
00032 
00033 #include "PythonTimeDistribution.h"
00034 #include "simlpy/SimulationException.h"
00035 
00036 #include <iostream>
00037 
00038 PythonTimeDistribution::PythonTimeDistribution() :
00039    m_f( 0 )
00040 {
00041 }
00042 
00043 PythonTimeDistribution::~PythonTimeDistribution()
00044 {
00045    if ( 0 != m_f )
00046    {
00047       Py_DECREF( m_f );
00048    }
00049 }
00050 
00051 Time
00052 PythonTimeDistribution::operator()( const Time& t )
00053 {
00054    if ( 0 == m_f )
00055    {
00056       std::cerr << "No function configured" << std::endl;
00057       throw SimulationException( __FILE__ , __LINE__ );
00058    }
00059    PyObject* l = PyList_New(0);
00060    if ( 0 == l )
00061    {
00062       std::cerr << "Could not allocate a new list" << std::endl;
00063       throw SimulationException( __FILE__ , __LINE__ );
00064    }
00065    PyObject* li = PyLong_FromLong( t.tv.tv_sec );
00066    if ( 0 == li )
00067    {
00068       Py_DECREF(l);
00069       std::cerr << "Could not allocate a new long" << std::endl;
00070       throw SimulationException( __FILE__ , __LINE__ );
00071    }
00072    if ( 0 > PyList_Append(l,li) )
00073    {
00074       Py_DECREF(l);
00075       Py_DECREF(li);
00076       std::cerr << "Error adding to the argument list" << std::endl;
00077       throw SimulationException( __FILE__ , __LINE__ );
00078    }
00079    li = PyLong_FromLong( t.tv.tv_usec );
00080    if ( 0 == li )
00081    {
00082       Py_DECREF(l);
00083       std::cerr << "Could not allocate a new long" << std::endl;
00084       throw SimulationException( __FILE__ , __LINE__ );
00085    }
00086    if ( 0 > PyList_Append(l,li) )
00087    {
00088       Py_DECREF(l);
00089       Py_DECREF(li);
00090       std::cerr << "Error adding to the argument list" << std::endl;
00091       throw SimulationException( __FILE__ , __LINE__ );
00092    }
00093    PyObject* r = PyObject_CallFunctionObjArgs( m_f, l, 0 );
00094    Py_DECREF(l);
00095    if ( 0 == r )
00096    {
00097       std::cerr << "Function generated an error" << std::endl;
00098       throw SimulationException( __FILE__ , __LINE__ );
00099    }
00100    if ( ! PyList_Check(r) )
00101    {
00102       Py_DECREF(r);
00103       std::cerr << "Function should have returned a list, but didn't"
00104                 << std::endl;
00105       throw SimulationException( __FILE__ , __LINE__ );
00106    }
00107    if ( PyList_Size(r) < 2 )
00108    {
00109       Py_DECREF(r);
00110       std::cerr << "Function should have returned a list of length 2"
00111                 << std::endl;
00112       throw SimulationException( __FILE__ , __LINE__ );
00113    }
00114    li = PyList_GetItem(r,0);
00115    if ( ! PyLong_Check( li ) )
00116    {
00117       Py_DECREF(r);
00118       std::cerr << "Returned list should have long int values" << std::endl;
00119       throw SimulationException( __FILE__ , __LINE__ );
00120    }
00121    long s = PyLong_AsLong(li);
00122    li = PyList_GetItem(r,1);
00123    if ( ! PyLong_Check( li ) )
00124    {
00125       Py_DECREF(r);
00126       std::cerr << "Returned list should have long int values" << std::endl;
00127       throw SimulationException( __FILE__ , __LINE__ );
00128    }
00129    long us = PyLong_AsLong(li);
00130    Time retval(s,us);
00131    Py_DECREF(r);
00132    return retval;
00133 }
00134 
00135 void
00136 PythonTimeDistribution::setFunc( PyObject* f )
00137 {
00138    if ( 0 == f )
00139    {
00140       std::cerr << "NULL object passed" << std::endl;
00141       throw SimulationException( __FILE__ , __LINE__ );
00142    }
00143    if ( ! PyCallable_Check( f ) )
00144    {
00145       std::cerr << "Argument is not callable" << std::endl;
00146       throw SimulationException( __FILE__ , __LINE__ );
00147    }
00148    m_f = f;
00149    Py_INCREF(m_f); // take ownership of the reference
00150 }

Generated on Mon Mar 24 11:15:46 2008 for Pydtn Simulator by  doxygen 1.5.4