mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Daniel Santos <daniel.santos@pobox.com>
To: Daniel Santos <daniel.santos@pobox.com>,
	Pavel Pisa <pisa@cmp.felk.cvut.cz>,
	Richard Weinberger <richard@nod.at>,
	LKML <linux-kernel@vger.kernel.org>,
	Michel Lespinasse <walken@google.com>,
	Andrea Arcangeli <aarcange@redhat.com>,
	Peter Zijlstra <a.p.zijlstra@chello.nl>,
	Rik van Riel <riel@redhat.com>
Subject: [PATCH v5 25/25] rbtree.h: (optional?) Add RB_INSERT_DUPE_RIGHT flag
Date: Tue, 25 Sep 2012 18:32:35 -0500	[thread overview]
Message-ID: <1348615955-10788-1-git-send-email-daniel.santos@pobox.com> (raw)
In-Reply-To: <1348615467-9850-1-git-send-email-daniel.santos@pobox.com>

I'm not sure if this is needed anywhere in the kernel. If not, it will
cause inserts run on older compilers to slow down very slightly.

This flag affects the behavior of inserts in trees where duplicate keys
are allowed.  It's generally assumed that the new node will be added to
the head of a group of nodes with the same key value.  However, this
behavior may not always be desired and this flag offers the option to
choose them to be inserted at the tail of such a group.

Signed-off-by: Daniel Santos <daniel.santos@pobox.com>
---
 include/linux/rbtree.h |   79 ++++++++++++++++++++++++++++++++++++-----------
 1 files changed, 60 insertions(+), 19 deletions(-)

diff --git a/include/linux/rbtree.h b/include/linux/rbtree.h
index f1fbdea..2ca553b 100644
--- a/include/linux/rbtree.h
+++ b/include/linux/rbtree.h
@@ -264,6 +264,11 @@ static inline void rb_link_node(struct rb_node * node, struct rb_node * parent,
  * @RB_INSERT_REPLACES:	When set, the rb_insert() will replace a value if it
  * 			matches the supplied one (valid only when
  * 			RB_UNIQUE_KEYS is set).
+ * @RB_INSERT_DUPE_RIGHT: Normally, when inserting a duplicate value into a
+ * 			tree with non-unique keys, the new value is inserted at
+ * 			the the head of the group same-value objects.  This
+ * 			flag causes inserts in such cases to put the new value
+ * 			at the tail of the group.
  * @RB_IS_AUGMENTED:	is an augmented tree
  * @RB_VERIFY_USAGE:	Perform checks upon node insertion for a small run-time
  * 			overhead. This has other usage restrictions, so read
@@ -300,12 +305,14 @@ enum rb_flags {
 	RB_HAS_COUNT		= 0x00000004,
 	RB_UNIQUE_KEYS		= 0x00000008,
 	RB_INSERT_REPLACES	= 0x00000010,
+	RB_INSERT_DUPE_RIGHT	= 0x00000020,
 	RB_IS_AUGMENTED		= 0x00000040,
 	RB_VERIFY_USAGE		= 0x00000080 & __RB_DEBUG_ENABLE_MASK,
 	RB_VERIFY_INTEGRITY	= 0x00000100 & __RB_DEBUG_ENABLE_MASK,
 	RB_ALL_FLAGS		= RB_HAS_LEFTMOST | RB_HAS_RIGHTMOST
 			| RB_HAS_COUNT | RB_UNIQUE_KEYS
 			| RB_INSERT_REPLACES | RB_IS_AUGMENTED
+			| RB_INSERT_DUPE_RIGHT
 			| RB_VERIFY_USAGE | RB_VERIFY_INTEGRITY,
 };
 
@@ -504,15 +511,19 @@ void __rb_assert_good_rel(const struct rb_relationship *rel)
 	/* Due to a bug in versions of gcc prior to 4.6, the following
 	 * expressions are always evalulated at run-time:
 	 *
+	 * ((rel->flags & RB_UNIQUE_KEYS) && (rel->flags & RB_INSERT_DUPE_RIGHT))
 	 * (!(rel->flags & RB_UNIQUE_KEYS) && (rel->flags & RB_INSERT_REPLACES))
 	 *
 	 * The work-around for this bug is separate each bitwise AND test using
 	 * an if/else construct and evaluate only the last test with the
 	 * BUILD_BUG_ON macro.
 	 */
-
-	if (rel->flags & RB_INSERT_REPLACES)
-		BUILD_BUG_ON42(!(rel->flags & RB_UNIQUE_KEYS));
+	if (rel->flags & RB_UNIQUE_KEYS)
+		/* only with non-unique keys */
+		BUILD_BUG_ON42(rel->flags & RB_INSERT_DUPE_RIGHT);
+	else
+		/* only with unique keys */
+		BUILD_BUG_ON42(rel->flags & RB_INSERT_REPLACES);
 }
 
 
@@ -840,6 +851,7 @@ struct rb_node *__rb_find_subtree(
 				 */
 				break;
 			else if (!diff) {
+				/* FIXME: non-unique keys broken here on inserts */
 				/* exact match */
 				*matched = go_left
 					 ? RB_MATCH_LEFT
@@ -1022,16 +1034,34 @@ struct rb_node *rb_insert(
 
 		parent = *p;
 
-		if (diff > 0) {
-			p = &(*p)->rb_right;
-			if (rel->flags & RB_HAS_LEFTMOST)
-				leftmost = 0;
-		} else if (!(rel->flags & RB_UNIQUE_KEYS) || diff < 0) {
-			p = &(*p)->rb_left;
-			if (rel->flags & RB_HAS_RIGHTMOST)
-				rightmost = 0;
-		} else
-			break;
+		/* when using non-unique keys, a new same-key objects is
+		 * inserted at the head of any existing same-key objects unless
+		 * RB_INSERT_DUPE_RIGHT is specified, which causes them to be
+		 * inserted at the tail.
+		 */
+		if (rel->flags & RB_INSERT_DUPE_RIGHT) {
+			if (diff < 0) {
+				p = &(*p)->rb_left;
+				if (rel->flags & RB_HAS_RIGHTMOST)
+					rightmost = 0;
+			} else if (!(rel->flags & RB_UNIQUE_KEYS) || diff > 0) {
+				p = &(*p)->rb_right;
+				if (rel->flags & RB_HAS_LEFTMOST)
+					leftmost = 0;
+			} else
+				break;
+		} else {
+			if (diff > 0) {
+				p = &(*p)->rb_right;
+				if (rel->flags & RB_HAS_LEFTMOST)
+					leftmost = 0;
+			} else if (!(rel->flags & RB_UNIQUE_KEYS) || diff < 0) {
+				p = &(*p)->rb_left;
+				if (rel->flags & RB_HAS_RIGHTMOST)
+					rightmost = 0;
+			} else
+				break;
+		}
 	}
 
 	if ((rel->flags & RB_HAS_LEFTMOST) && leftmost) {
@@ -1087,12 +1117,23 @@ struct rb_node *rb_insert_near(
 			diff   = rel->compare(__rb_node_to_key(*p, rel), key);
 			parent = *p;
 
-			if (diff > 0)
-				p = &(*p)->rb_right;
-			else if (!(rel->flags & RB_UNIQUE_KEYS) || diff < 0)
-				p = &(*p)->rb_left;
-			else
-				break;
+			if (rel->flags & RB_INSERT_REPLACES) {
+				if (diff < 0)
+					p = &(*p)->rb_left;
+				else if (!(rel->flags & RB_UNIQUE_KEYS) ||
+						diff > 0)
+					p = &(*p)->rb_right;
+				else
+					break;
+			} else {
+				if (diff > 0)
+					p = &(*p)->rb_right;
+				else if (!(rel->flags & RB_UNIQUE_KEYS) ||
+						diff < 0)
+					p = &(*p)->rb_left;
+				else
+					break;
+			}
 		}
 		ret = *p;
 	}
-- 
1.7.3.4


  parent reply	other threads:[~2012-09-25 23:32 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <1348615467-9850-1-git-send-email-daniel.santos@pobox.com>
2012-09-25 23:29 ` [PATCH v5 1/25] compiler-gcc4.h: Correct verion check for __compiletime_error Daniel Santos
2012-09-25 23:30 ` [PATCH v5 2/25] compiler-gcc4.h: Reorder macros based upon gcc ver Daniel Santos
2012-09-25 23:30 ` [PATCH v5 3/25] compiler-gcc.h: Add gcc-recommended GCC_VERSION macro Daniel Santos
2012-09-25 23:30 ` [PATCH v5 4/25] compiler-gcc{3,4}.h: Use " Daniel Santos
2012-09-25 23:30 ` [PATCH v5 5/25] compiler{,-gcc4}.h: Remove duplicate macros Daniel Santos
2012-09-25 23:30 ` [PATCH v5 6/25] bug.h: Replace __linktime_error with __compiletime_error Daniel Santos
2012-09-25 23:30 ` [PATCH v5 7/25] compiler{,-gcc4}.h: Introduce __flatten function attribute Daniel Santos
2012-09-25 23:30 ` [PATCH v5 8/25] bug.h: Make BUILD_BUG_ON generate compile-time error Daniel Santos
2012-09-25 23:30 ` [PATCH v5 9/25] bug.h: Add BUILD_BUG_ON_NON_CONST macro Daniel Santos
2012-09-25 23:31 ` [PATCH v5 10/25] bug.h: Add gcc 4.2+ versions of BUILD_BUG_ON_* macros Daniel Santos
2012-09-25 23:31 ` [PATCH v5 11/25] rbtree.h: Generic Red-Black Trees Daniel Santos
2012-09-25 23:31 ` [PATCH v5 12/25] rbtree.h: include kconfig.h Daniel Santos
2012-09-25 23:31 ` [PATCH v5 13/25] fair.c: Use generic rbtree impl in fair scheduler Daniel Santos
2012-09-25 23:31 ` [PATCH v5 15/25] kernel-doc: bugfix - multi-line macros Daniel Santos
2012-09-25 23:31 ` [PATCH v5 16/25] kernel-doc: bugfix - empty line in Example section Daniel Santos
2012-09-25 23:31 ` [PATCH v5 17/25] kernel-doc: Don't mangle whitespace " Daniel Santos
2012-09-25 23:31 ` [PATCH v5 19/25] rbtree.h: add doc comments for struct rb_node Daniel Santos
2012-09-25 23:32 ` [PATCH v5 20/25] selftest: Add generic tree self-test common code Daniel Santos
2012-09-25 23:32 ` [PATCH v5 21/25] selftest: Add userspace test program Daniel Santos
2012-09-25 23:32 ` [PATCH v5 22/25] selftest: Add script to compile & run " Daniel Santos
2012-09-25 23:32 ` [PATCH v5 23/25] selftest: Add basic compiler iterator test script Daniel Santos
2012-09-25 23:32 ` [PATCH v5 24/25] selftest: report generation script for test results Daniel Santos
2012-09-25 23:32 ` Daniel Santos [this message]
     [not found] ` <1348618742.22822.39.camel@gandalf.local.home>
2012-09-26  1:02   ` [PATCH v5 0/25] Generic Red-Black Trees (still WIP) Daniel Santos
2012-09-26  1:28     ` Steven Rostedt
2012-09-26  5:07 ` Daniel Santos

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1348615955-10788-1-git-send-email-daniel.santos@pobox.com \
    --to=daniel.santos@pobox.com \
    --cc=a.p.zijlstra@chello.nl \
    --cc=aarcange@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=pisa@cmp.felk.cvut.cz \
    --cc=richard@nod.at \
    --cc=riel@redhat.com \
    --cc=walken@google.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®