[mathic] 15/62: Added support to PairQueue for the user to control how construction and destruction of PairData happens.

Doug Torrance dtorrance-guest at moszumanska.debian.org
Wed Apr 1 11:36:18 UTC 2015


This is an automated email from the git hooks/post-receive script.

dtorrance-guest pushed a commit to branch master
in repository mathic.

commit 3b29b87b856ebc736a686bd336f0cec5c99126b6
Author: Bjarke Hammersholt Roune <bjarkehr.code at gmail.com>
Date:   Sun Jul 15 00:16:30 2012 -0400

    Added support to PairQueue for the user to control how construction and destruction of PairData happens.
---
 src/mathic/PairQueue.h | 177 ++++++++++++++++++++++++++++++++++++-------------
 src/test/PairQueue.cpp |  37 ++++++++++-
 2 files changed, 166 insertions(+), 48 deletions(-)

diff --git a/src/mathic/PairQueue.h b/src/mathic/PairQueue.h
index 4cde729..deaccd2 100755
--- a/src/mathic/PairQueue.h
+++ b/src/mathic/PairQueue.h
@@ -54,17 +54,56 @@ namespace mathic {
   template<class Configuration>
   class PairQueue;
 
+  namespace PairQueueNamespace {
+	typedef unsigned int Index;
+
+	// Used by PairData<Configuration> to construct a PairData object
+	// to hold data for (col, row). PairData is not constructed in any
+	// other way than to call this function.
+	//
+	// The default implementation default-constructs the PairData and
+	// then calls Configuration::computePairData. Specialize (do not
+	// overload) this template function for your particular
+	// configuration type if you want something else to happen -- for
+	// example you might not want default construction to occur.
+	template<class Configuration>
+	void constructPairData
+	(void* memory, Index col, Index row, Configuration& conf) {
+	  MATHIC_ASSERT(memory != 0);
+	  MATHIC_ASSERT(col > row);
+	  typename Configuration::PairData* pd =
+		new (memory) typename Configuration::PairData();
+	  conf.computePairData(col, row, *pd);
+	}
+
+	// Used by PairData<Configuration> to destruct a PairData object
+	// currently holding data for (col, row). PairData is not
+	// destructed in any other way than to call this function.
+	//
+	// The default implementation just calls the
+	// destructor. Specialize (do not overload) this template function
+	// for your particular configuration type if you want something
+	// else to happen -- for example PairData might hold memory
+	// allocated from a memory pool that you want to return to the
+	// pool but you do not want to put a reference to the memory pool
+	// inside every PairData.
+	template<class Configuration>
+	void destructPairData
+	(typename Configuration::PairData* pd,
+	 Index col, Index row, Configuration& conf) {
+	  MATHIC_ASSERT(pd != 0);
+	  MATHIC_ASSERT(col > row);
+	  typedef typename Configuration::PairData PairData;
+	  pd->~PairData();
+	}
+  }
+
   template<class C>
   class PairQueue {
   public:
 	typedef C Configuration;
 	typedef typename C::PairData PairData;
-	typedef unsigned int Index;
-	struct ColumnEntry {
-	  ColumnEntry(const PairData& pd, Index r): pairData(pd), row(r) {}
-	  PairData pairData;
-	  Index row;
-	};
+	typedef PairQueueNamespace::Index Index;
 
 	// PairQueue stores a copy of the passed in configuration.
 	PairQueue(const Configuration& conf);
@@ -116,7 +155,7 @@ namespace mathic {
     class Column {
 	public:
 	  template<class Iter>
-	  Column
+	  static Column* create
 	  (Index col, Iter rowsBegin, Iter rowsEnd, C& conf, memt::Arena& arena);
 
 	  const PairData& pairData() {MATHIC_ASSERT(!empty()); return mPairData;}
@@ -127,9 +166,32 @@ namespace mathic {
 	  bool empty() const;
 	  size_t size() const; // number of pairs remaining in this column
 
+	  void destruct(C& conf) {
+		// if empty then we already destructed the data
+		if (!empty())
+		  destruct(rowIndex(), conf);
+	  }
+
 	private:
+	  // Do not call contructors on Column as that would construct the
+	  // PairData directly which is not allowed -- instead call the
+	  // factory function.
+	  Column(); // not available
+	  Column(const Column&); // not available
+	  void operator=(const Column&); // not available
+
+	  // Do not call the destructor as that would destruct the
+	  // PairData directly which is not allowed -- instead call
+	  // destruct(conf).
+	  ~Column(); // not available
+
+	  void destruct(Index row, C& conf) {
+		PairQueueNamespace::
+		  destructPairData(&mPairData, columnIndex(), row, conf);
+	  }
+
 	  PairData mPairData; // pairData of (columnIndex(), rowIndex())
-	  Index const mColumnIndex; // all pairs here have this column index
+	  Index mColumnIndex; // all pairs here have this column index
 	  
 	  bool big() const; // returns true if we need to use big part of union
 	  union { // the current row index is *begin
@@ -156,10 +218,13 @@ namespace mathic {
 
 	class ColumnDestructor {
 	public:
+	  ColumnDestructor(C& conf): mConf(conf) {}
 	  bool proceed(Column* const column) {
-		column->~Column();
+		column->destruct(mConf);
 		return true;
 	  }
+	private:
+	  C& mConf;
 	};
 
 	class QueueConfiguration : TourTreeSuggestedOptions {
@@ -184,78 +249,87 @@ namespace mathic {
 
 	ColumnQueue mColumnQueue;
 	size_t mColumnCount;
-	std::vector<Column*> mColumns;
 	memt::Arena mArena;
 	memt::Arena mScratchArena;
 	Configuration mConf;
-	std::vector<ColumnEntry> mColumnEntries;
   };
 
   //// Implementation
   template<class C>
   template<class Iter>
-  PairQueue<C>::Column::Column
+  typename PairQueue<C>::Column* PairQueue<C>::Column::create
   (Index const col,
    Iter const rowsBegin, Iter const rowsEnd,
    C& conf,
-   memt::Arena& arena):
-	mColumnIndex(col)
-  {
+   memt::Arena& arena) {
+	Column* column = arena.allocObjectNoCon<Column>();
+	column->mColumnIndex = col;
+
 #ifdef MATHIC_DEBUG
 	// check that the passed in range is weakly descending according
 	// to the custom order.
 	if (rowsBegin != rowsEnd) {
 	  Iter prevIt = rowsBegin;
 	  Iter it = rowsBegin;
-	  PairData prevPd;
-	  conf.computePairData(columnIndex(), *rowsBegin, prevPd);
-	  PairData currentPd;
 	  for (++it; it != rowsEnd; ++it, ++prevIt) {
-		conf.computePairData(columnIndex(), *it, currentPd);
+		memt::Arena::PtrNoConNoDecon<PairData> prevPd(arena);
+		memt::Arena::PtrNoConNoDecon<PairData> currentPd(arena);
+
+		PairQueueNamespace::constructPairData(prevPd.get(), col, *prevIt, conf);
+		try {
+		  PairQueueNamespace::constructPairData
+			(currentPd.get(), col, *it, conf);
+		} catch (...) {
+		  PairQueueNamespace::
+			destructPairData(prevPd.get(), col, *prevIt, conf);
+		  throw;
+		}
+
 		// check prev >= current, which is equivalent to !(prev < current)
 		MATHIC_ASSERT
-		  (!conf.cmpLessThan(conf.compare(columnIndex(), *prevIt, prevPd,
-										  columnIndex(), *it, currentPd)));
-		// !(currentPd < prevPd) 
-		prevPd = currentPd;
+		  (!conf.cmpLessThan(conf.compare(col, *prevIt, *prevPd,
+										  col, *it, *currentPd)));
+		PairQueueNamespace::
+		  destructPairData(currentPd.get(), col, *prevIt, conf);
+		PairQueueNamespace::destructPairData(prevPd.get(), col, *prevIt, conf);
 	  }
 	}
 #endif
 
 	size_t const entryCount = std::distance(rowsBegin, rowsEnd);
-	if (big()) {
+	if (column->big()) {
 	  std::pair<Index*, Index*> const range =
 		arena.allocArrayNoCon<Index>(entryCount);
-	  bigBegin = range.first;
-	  bigEnd = range.second;
+	  column->bigBegin = range.first;
+	  column->bigEnd = range.second;
 	  Index* rangeIt = range.first;
 	  Iter rowsIt = rowsBegin;
 	  for (; rangeIt != range.second; ++rangeIt, ++rowsIt) {
 		MATHIC_ASSERT(rowsIt != rowsEnd);
-		MATHIC_ASSERT(*rowsIt < mColumnIndex);
+		MATHIC_ASSERT(*rowsIt < col);
 		MATHIC_ASSERT(*rowsIt < std::numeric_limits<Index>::max());
 		*rangeIt = static_cast<Index>(*rowsIt);
 	  }
 	  MATHIC_ASSERT(rowsIt == rowsEnd);
-	  bigBegin = range.first;
-	  bigEnd = range.second;
 	} else {
 	  std::pair<SmallIndex*, SmallIndex*> range =
 		arena.allocArrayNoCon<SmallIndex>(entryCount);
-	  smallBegin = range.first;
-	  smallEnd = range.second;
+	  column->smallBegin = range.first;
+	  column->smallEnd = range.second;
 	  SmallIndex* rangeIt = range.first;
 	  Iter rowsIt = rowsBegin;
 	  for (; rangeIt != range.second; ++rangeIt, ++rowsIt) {
 		MATHIC_ASSERT(rowsIt != rowsEnd);
-		MATHIC_ASSERT(*rowsIt < mColumnIndex);
+		MATHIC_ASSERT(*rowsIt < col);
 		MATHIC_ASSERT(*rowsIt < std::numeric_limits<SmallIndex>::max());
 		*rangeIt = static_cast<SmallIndex>(*rowsIt);
 	  }
 	}
-	MATHIC_ASSERT(size() == entryCount);
-	MATHIC_ASSERT(empty() == (entryCount == 0));
-	conf.computePairData(columnIndex(), rowIndex(), mPairData);
+	MATHIC_ASSERT(column->size() == entryCount);
+	MATHIC_ASSERT(column->empty() == (entryCount == 0));
+	PairQueueNamespace::constructPairData
+	  (&column->mPairData, col, *rowsBegin, conf);
+	return column;
   }
 
   template<class C>
@@ -270,12 +344,23 @@ namespace mathic {
   template<class C>
   void PairQueue<C>::Column::incrementRowIndex(C& conf) {
 	MATHIC_ASSERT(!empty());
-	if (big())
+	if (big()) {
 	  ++bigBegin;
-	else
+	  if (bigBegin == bigEnd) {
+		MATHIC_ASSERT(empty());
+		destruct(*(bigBegin - 1), conf);
+		return;
+	  }
+	} else {
 	  ++smallBegin;
-	if (!empty())
-	  conf.computePairData(columnIndex(), rowIndex(), mPairData);
+	  if (smallBegin == smallEnd) {
+		MATHIC_ASSERT(empty());
+		destruct(*(smallBegin - 1), conf);
+		return;
+	  }
+	}
+	MATHIC_ASSERT(!empty());
+	conf.computePairData(columnIndex(), rowIndex(), mPairData);
   }
 
   template<class C>
@@ -296,7 +381,7 @@ namespace mathic {
 
   template<class C>
   bool PairQueue<C>::Column::big() const {
-	return columnIndex() >
+	return columnIndex() >=
 	  static_cast<size_t>(std::numeric_limits<SmallIndex>::max());
   }
 
@@ -309,7 +394,7 @@ namespace mathic {
 
   template<class C>
   PairQueue<C>::~PairQueue() {
-	ColumnDestructor destructor;
+	ColumnDestructor destructor(mConf);
 	mColumnQueue.forAll(destructor);
   }
 
@@ -336,19 +421,17 @@ namespace mathic {
 	++mColumnCount;
 	if (sortedRowsBegin == sortedRowsEnd)
 	  return;
-	mColumns.reserve(mColumns.size() + 1);
 	memt::Arena::Guard guard(mArena);
 
-	Column* column = new (mArena.allocObjectNoCon<Column>())
-	  Column(newColumnIndex, sortedRowsBegin, sortedRowsEnd, mConf, mArena);
+	Column* column = Column::create
+	  (newColumnIndex, sortedRowsBegin, sortedRowsEnd, mConf, mArena);
 
 	try {
 	  mColumnQueue.push(column);
 	} catch (...) {
-	  column->~Column();
+	  column->destruct(mConf);
 	  throw;
 	}
-	mColumns.push_back(column); // does not throw due to reserve above
 	guard.release();
   }
 
@@ -364,7 +447,7 @@ namespace mathic {
 	// actions: top(), change top element in-place, do decreaseTop/pop.
 	topColumn->incrementRowIndex(mConf);
 	if (topColumn->empty()) {
-	  topColumn->~Column();
+	  topColumn->destruct(mConf);
 	  mColumnQueue.pop();
 	} else
 	  mColumnQueue.decreaseTop(topColumn);
diff --git a/src/test/PairQueue.cpp b/src/test/PairQueue.cpp
index 64b5f76..17f0511 100755
--- a/src/test/PairQueue.cpp
+++ b/src/test/PairQueue.cpp
@@ -210,7 +210,14 @@ namespace {
 	// better not have two of these objects around at the same time!
 	PQConDeconCounterConf() {mLive.clear();}
 
-	struct PairData {
+	class PairData {
+	  friend class PQConDeconCounterConf;
+	private:
+	  // only the configuration should call any method on PairData, in
+	  // this case even including the constructor and destructor
+	  // because we specialized
+	  // mathic::PairQueueNamespace::constructPairData and
+	  // mathic::PairQueueNamespace::destructPairData (see below).
 	  PairData() {makeLive();}
 	  ~PairData() {makeDead();}
 
@@ -239,6 +246,14 @@ namespace {
 	  size_t row;
 	};
 
+	void construct(void* memory) {
+	  new (memory) PairData();
+	}
+
+	void destruct(PairData* pd) {
+	  pd->~PairData();
+	}
+
 	void computePairData(size_t col, size_t row, PairData& pd) {
 	  MATHIC_ASSERT(pd.live());
 	  pd.row = row;
@@ -261,6 +276,26 @@ namespace {
   std::set<PQConDeconCounterConf::PairData const*> PQConDeconCounterConf::mLive;
 }
 
+namespace mathic {
+  namespace PairQueueNamespace {
+	template<>
+	void constructPairData
+	(void* memory, Index col, Index row, PQConDeconCounterConf& conf) {
+	  PQConDeconCounterConf::PairData* pd =
+		static_cast<PQConDeconCounterConf::PairData*>(memory);
+	  conf.construct(pd);
+	  conf.computePairData(col, row, *pd);
+	}
+
+	template<>
+	void destructPairData
+	(PQConDeconCounterConf::PairData* pd,
+	 Index col, Index row, PQConDeconCounterConf& conf) {
+	  conf.destruct(pd);
+	}
+  }
+}
+
 // check that all PairQueue properly constructs and deconstructs
 // all PairData objects.
 TEST(PairQueue, ConDeconOfPairData) {

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/mathic.git



More information about the debian-science-commits mailing list