kudu-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From dral...@apache.org
Subject [2/4] incubator-kudu git commit: Add ComputeIfAbsent methods to map-util
Date Mon, 11 Jul 2016 18:25:10 GMT
Add ComputeIfAbsent methods to map-util

This adds two new ComputeIfAbsent methods to map-util, inspired by java's implementation,
which can be found here:

https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ConcurrentHashMap.html#computeIfAbsent-K-java.util.function.Function-

The first one, ComputeIfAbsent, is a simple c++ implementation of the exact same
concept: Retreive a value from a map; if it doesn't exist compute it using a lambda
function and insert it first.

The second one is a slight variation that returns a pair instead of a pointer to the
value. The pair includes the pointer to the value, but also a bool indicating whether
the value was initially absent.

Change-Id: Iba9fa8038e699e66d34ce541cd02c77f46691315
Reviewed-on: http://gerrit.cloudera.org:8080/3593
Reviewed-by: Todd Lipcon <todd@apache.org>
Tested-by: Kudu Jenkins


Project: http://git-wip-us.apache.org/repos/asf/incubator-kudu/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-kudu/commit/a22795aa
Tree: http://git-wip-us.apache.org/repos/asf/incubator-kudu/tree/a22795aa
Diff: http://git-wip-us.apache.org/repos/asf/incubator-kudu/diff/a22795aa

Branch: refs/heads/master
Commit: a22795aa6fd2be93ad3fc22892849c808eade007
Parents: 1a971a1
Author: dralves <dralves@apache.org>
Authored: Thu Jul 7 16:20:25 2016 -0700
Committer: David Ribeiro Alves <dralves@apache.org>
Committed: Mon Jul 11 18:09:53 2016 +0000

----------------------------------------------------------------------
 src/kudu/gutil/map-util.h      | 50 +++++++++++++++++++++++++++++++++++++
 src/kudu/util/map-util-test.cc | 20 +++++++++++++++
 2 files changed, 70 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-kudu/blob/a22795aa/src/kudu/gutil/map-util.h
----------------------------------------------------------------------
diff --git a/src/kudu/gutil/map-util.h b/src/kudu/gutil/map-util.h
index 0682c27..8c7574e 100644
--- a/src/kudu/gutil/map-util.h
+++ b/src/kudu/gutil/map-util.h
@@ -767,4 +767,54 @@ void AppendValuesFromMap(const MapContainer& map_container,
   }
 }
 
+// Compute and insert new value if it's absent from the map. Return a pair with a reference
to the
+// value and a bool indicating whether it was absent at first.
+//
+// This inspired on a similar java construct (url split in two lines):
+// https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ConcurrentHashMap.html
+// #computeIfAbsent-K-java.util.function.Function
+//
+// It takes a reference to the key and a lambda function. If the key exists in the map, returns
+// a pair with a pointer to the current value and 'false'. If the key does not exist in the
map,
+// it uses the lambda function to create a value, inserts it into the map, and returns a
pair with
+// a pointer to the new value and 'true'.
+//
+// Example usage:
+//
+// auto result = ComputeIfAbsentReturnAbsense(&my_collection,
+//                                            my_key,
+//                                            [] { return new_value; });
+// MyValue* const value = result.first;
+// if (result.second) ....
+//
+template <class MapContainer, typename Function>
+pair<typename MapContainer::mapped_type* const, bool>
+ComputeIfAbsentReturnAbsense(MapContainer* container,
+                             const typename MapContainer::key_type& key,
+                             Function compute_func) {
+  typename MapContainer::iterator iter = container->find(key);
+  bool new_value = iter == container->end();
+  if (new_value) {
+    pair<typename MapContainer::iterator, bool> result = container->emplace(key,
compute_func());
+    DCHECK(result.second) << "duplicate key: " << key;
+    iter = result.first;
+  }
+  return make_pair(&iter->second, new_value);
+};
+
+// Like the above but doesn't return a pair, just returns a pointer to the value.
+// Example usage:
+//
+// MyValue* const value = ComputeIfAbsent(&my_collection,
+//                                        my_key,
+//                                        [] { return new_value; });
+//
+template <class MapContainer, typename Function>
+typename MapContainer::mapped_type* const
+ComputeIfAbsent(MapContainer* container,
+                const typename MapContainer::key_type& key,
+                Function compute_func) {
+  return ComputeIfAbsentReturnAbsense(container, key, compute_func).first;
+};
+
 #endif  // UTIL_GTL_MAP_UTIL_H_

http://git-wip-us.apache.org/repos/asf/incubator-kudu/blob/a22795aa/src/kudu/util/map-util-test.cc
----------------------------------------------------------------------
diff --git a/src/kudu/util/map-util-test.cc b/src/kudu/util/map-util-test.cc
index 4001f98..270c509 100644
--- a/src/kudu/util/map-util-test.cc
+++ b/src/kudu/util/map-util-test.cc
@@ -21,8 +21,11 @@
 
 #include <gtest/gtest.h>
 #include <map>
+#include <memory>
 
 using std::map;
+using std::string;
+using std::unique_ptr;
 
 namespace kudu {
 
@@ -42,7 +45,24 @@ TEST(FloorTest, TestMapUtil) {
   ASSERT_EQ(1, *FindFloorOrNull(my_map, 4));
   ASSERT_EQ(1, *FindFloorOrNull(my_map, 1));
   ASSERT_EQ(nullptr, FindFloorOrNull(my_map, 0));
+}
+
+TEST(ComputeIfAbsentTest, TestComputeIfAbsent) {
+  map<string, string> my_map;
+  auto result = ComputeIfAbsent(&my_map, "key", []{ return "hello_world"; });
+  ASSERT_EQ(*result, "hello_world");
+  auto result2 = ComputeIfAbsent(&my_map, "key", [] { return "hello_world2"; });
+  ASSERT_EQ(*result2, "hello_world");
+}
 
+TEST(ComputeIfAbsentTest, TestComputeIfAbsentAndReturnAbsense) {
+  map<string, string> my_map;
+  auto result = ComputeIfAbsentReturnAbsense(&my_map, "key", []{ return "hello_world";
});
+  ASSERT_TRUE(result.second);
+  ASSERT_EQ(*result.first, "hello_world");
+  auto result2 = ComputeIfAbsentReturnAbsense(&my_map, "key", [] { return "hello_world2";
});
+  ASSERT_FALSE(result2.second);
+  ASSERT_EQ(*result2.first, "hello_world");
 }
 
 } // namespace kudu


Mime
View raw message