Пример #1
0
int
mkheap_putAndGet_reader(MKHeap *mkheap, MKEntry *out)
{
	int			n;
	bool		fOK;
	int			ins;

	/* First, check to see if the heap is empty */
	MKEntry    *e = mkheap_peek(mkheap);

	if (!e)
	{
		mke_set_empty(out);
		return -1;
	}

	Assert(!mke_is_empty(e));

	/* _reader code is not compatible with the run code */
	Assert(mke_get_run(e) == 0);

	/* Figure out the reader that provided the current top of the heap */
	n = mke_get_reader(e);
	Assert(n >= 0 && n < mkheap->nreader);

	/* Read in a new one that will replenish the current top of the heap */
	fOK = mkheap->readers[n].reader(mkheap->readers[n].mkhr_ctxt, out);
	if (fOK)
	{
		mke_set_reader(out, n);
	}
	else
	{
		mke_set_empty(out);
	}
	Assert(mke_get_run(out) == 0);

	/*
	 * now insert it and pop the top of the heap or, if equal to the top, just
	 * don't do the insert
	 *
	 * So, on success (ins >= 0) then *out will refer to the element which is
	 * NOT in the heap (which could be either the result of mkheap_peek above
	 * OR the result of the .reader() call, depending)
	 */
	ins = mkheap_putAndGet_impl(mkheap, out);

	Assert(ins >= 0);
	Assert(mke_get_reader(out) == n);
	Assert(!mke_is_empty(out));

	return ins;
}
Пример #2
0
void mk_qsort_impl(MKEntry *a, int left, int right, int lv, bool lvdown, MKContext *ctxt, bool seenNull)
{
	int lastInLow;
	int firstInHigh;

	Assert(ctxt);
	Assert(lv < ctxt->total_lv);

    CHECK_FOR_INTERRUPTS();

	if(right <= left)
		return;
	
	/* Prepare at level lv */
	if(lvdown)
        mk_prepare_array(a, left, right, lv, ctxt);

	/* 
	 * According to Bentley & McIlroy [1] (1993), using insert sort for case 
	 * n < 7 is a significant saving.  However, according to Sedgewick & 
	 * Bentley [2] (2002), the wisdom of new millenium is not to special case
	 * smaller cases.  Here, we do not special case it because we want to save
	 * memtuple_getattr, and expensive comparisons that has been prepared.
	 *
	 * XXX Find out why we have a new wisdom in [2] and impl. & compare.
	 */
	mk_qsort_part3(a, left, right, lv, ctxt, &lastInLow, &firstInHigh);

	/* recurse to left chunk */
	mk_qsort_impl(a, left, lastInLow, lv, false, ctxt, seenNull);

	/* recurse to middle (equal) chunk */
	if(lv < ctxt->total_lv-1)
	{
		/*
		 * [lastInLow+1,firstInHigh-1] defines the pivot region which was all equal at level lv.  So increase the level and compare that region!
		 */
		mk_qsort_impl(a, lastInLow+1, firstInHigh-1, lv+1, true, ctxt, seenNull || mke_is_null(a+lastInLow+1)); /* a + lastInLow + 1 points to the pivot */
	}
	else
	{
		/* values are all equal to the deepest level...no need for more compares, but check uniqueness if requested */
		if(firstInHigh-1 > lastInLow+1 &&
				!seenNull &&
				!mke_is_null(a+lastInLow+1)) /* a + lastInLow + 1 points to the pivot */
		{
			if ( ctxt->enforceUnique )
			{
			    ERROR_UNIQUENESS_VIOLATED();
			}
			else if ( ctxt->unique)
			{
				int toFreeIndex;
				for ( toFreeIndex = lastInLow + 2; toFreeIndex < firstInHigh; toFreeIndex++) /* +2 because we want to keep one around! */
				{
					MKEntry *toFree = a + toFreeIndex;
					if ( ctxt->cpfr)
						ctxt->cpfr(toFree, NULL, ctxt->lvctxt + lv); // todo: verify off-by-one
					ctxt->freeTup(toFree);
					mke_set_empty(toFree);
				}
			}
		}
	}

	/* recurse to right chunk */
	mk_qsort_impl(a, firstInHigh, right, lv, false, ctxt, seenNull);

#ifdef MKQSORT_VERIFY 
	if(lv == 0)
		mkqsort_verify(a, left, right, ctxt);
#endif
}