Hi All
I mentioned this briefly during the previous release cycle, but we all
had more pressing things to deal with. Dealing with errors is
something we really  need to get a hold on for PLPlot 6 and one of the
big drivers for considering a major API change. However, I am certain
that the reason why this has been a problem s that propagating those
errors back up through many layers of function calls is tedious and
error prone so it has been much simpler to simply call exit().

Here is one possible solution. We switch the core code to C++ with a C frontend.

I am aware some people on this list know C++ better than others,
however, the actual code changes I am suggesting are relatively small.
It may seem daunting, but I am not considering rewriting everything in
an object oriented way, I am simply advocating using two features of
C++ which will make our lives massively easier. I feel the change
would be less painful that the switch from svn to git, but with much
larger gains so please hear me out. So the following is aimed at those
of us who are a bit wary of C++ that have better C skills. If I'm
teaching my granny to suck eggs then I apologise.

The first feature is throw-catch. It would work like this

#define PLERR int
#define PLERR_NONE 0
#define PLERR_OUTOFMEM 1

void someFunc();

PLERR plapiFunc( /*some parameters*/ )
{
   try
   {
      //Any number of function calls declarations etc down to any level
      //But for example lets call someFunc()
      someFunc();
   }
   catch( PLERR err )
   {
      return err;
   }
}

void someFunc()
{
   PLINT *array=malloc( 100000000000000 *sizeof(PLINT);
   if( array == NULL )
      throw( PLERR_OUTOFMEM );
   //do some stuff
   free( array );
}

So the way this works is that if at any time you call throw, the
function returns to its calling function taking the parameter with it.
If the call was made outside of a try block then it returns again and
again until eventually it finds the try block and enters the catch
block. In this case it assigns the error and returns it. Then
execution continues from that point.

This would mean that we could simply replace all exit calls with throw
calls instead and the job would be done!!!

Well actually that's not quite true. There is one other thing to deal
with. Although we now don't exit, if any memory was allocated between
the call in the try block and the throw then it will leak. This is
still an improvement. Memory leaks are surely better than unexpected
exits. At least now the user has the option to do something like write
recovery data to disk and restart or try to trace the problem.

But there is a solution. We create an array class. and do our memory
allocations in that class. Here we are not talking about anything too
fancy, just a simple class without any inheritance or polymorphism. It
would look something like:

class PLINTArr
{
public:
   PLINTArr(PLINT n);
   ~PLINTArr();
   PLINT &operator[]( PLINT idx );
private:
   PLINT m_*mem;
};

PLINTArr::PLINTArr( PLINT n )
{
   m_mem = malloc( n );
   if ( !m_mem )
      throw( PLERR_OUTOFMEM );
}

PLINTArr::~PLINTArr()
{
   free( m_mem );
}

PLINTArr::PLINT &operator[]( PLINT idx )
{
   return m_mem[idx];
}

How does this help? The joy of an object is that when you create one
the constructor is called and when it goes out of scope the destructor
is called. So we can now have

void someFunc()
{
   PLINTArr arr( 100000000000000 );
}

This calls the constructor PLINTArr::PLINTArr with the number of
elements we want in our array. Checking if the allocation was okay has
been done for us so that saved us a job. And when arr goes out of
scope PLINTArr::~PLINTArr is called and everything gets cleaned up, so
we don't even have to worry about that either.

But what is even better, we can do something like this

void someFunc()
{
   PLINTArr arr( 100 );
   char *filename = getFilename();
   if (strlen( filename ) == 0 )
      throw( PLERR_FILENOTFOUND );
}

If throw gets called then someFunc returns, arr goes out of scope, the
destructor is called which cleans up for us and now we have perfect
error reporting and no memory leaks!!!

The effort required to make these changes is tiny compared to trying
to propagate errors back through the code and track down memory leaks
on the way. So it would be something that I would really like to push
if people are open to it.

Any thoughts?

Phil

------------------------------------------------------------------------------
One dashboard for servers and applications across Physical-Virtual-Cloud 
Widest out-of-the-box monitoring support with 50+ applications
Performance metrics, stats and reports that give you Actionable Insights
Deep dive visibility with transaction tracing using APM Insight.
http://ad.doubleclick.net/ddm/clk/290420510;117567292;y
_______________________________________________
Plplot-devel mailing list
Plplot-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/plplot-devel

Reply via email to