/*
    Copyright (C) 1998 by Jorrit Tyberghein
  
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.
  
    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.
  
    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#ifndef POLYPOOL_H
#define POLYPOOL_H

#include "csgeom/poly2d.h"

class Dumper;

/**
 * This is an object pool which holds objects of type
 * csPolygon2D. You can ask new instances from this pool.
 * If needed it will allocate one for you but ideally it can
 * give you one which was allocated earlier.
 */
class csPoly2DPool
{
  friend class Dumper;

private:
  struct PoolObj
  {
    PoolObj* next;
    csPoly2D* pol2d;
  };
  /// List of allocated polygons.
  PoolObj* alloced;
  /// List of previously allocated, but now unused polygons.
  PoolObj* freed;

  // Factory for creating new polygons.
  csPoly2DFactory* factory;

public:
  /// Create an empty pool.
  csPoly2DPool (csPoly2DFactory* fact) : alloced (NULL), freed (NULL),
  	factory (fact) { }

  /// Destroy pool and all objects in the pool.
  ~csPoly2DPool ()
  {
    while (alloced)
    {
      PoolObj* n = alloced->next;
      CHK (delete alloced->pol2d);
      CHK (delete alloced);
      alloced = n;
    }
    while (freed)
    {
      PoolObj* n = freed->next;
      CHK (delete freed->pol2d);
      CHK (delete freed);
      freed = n;
    }
  }

  /// Allocate a new object in the pool.
  csPoly2D* Alloc ()
  {
    PoolObj* pnew;
    if (freed)
    {
      pnew = freed;
      freed = freed->next;
    }
    else
    {
      CHK (pnew = new PoolObj ());
      pnew->pol2d = factory->Create ();
    }
    pnew->next = alloced;
    alloced = pnew;
    return pnew->pol2d;
  }

  /**
   * Free an object and put it back in the pool.
   * Note that it is only legal to free objects which were allocated
   * from the pool.
   */
  void Free (csPoly2D* pol)
  {
    if (alloced)
    {
      PoolObj* po = alloced;
      alloced = alloced->next;
      po->pol2d = pol;
      po->next = freed;
      freed = po;
    }
    else
    {
      // Cannot happen!
    }
  }
};


#endif /*POLYPOOL_H*/
