http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/02f3e3fc/be/src/gutil/map-util.h ---------------------------------------------------------------------- diff --git a/be/src/gutil/map-util.h b/be/src/gutil/map-util.h index 9368a5a..6fffedf 100644 --- a/be/src/gutil/map-util.h +++ b/be/src/gutil/map-util.h @@ -72,7 +72,8 @@ using std::pair; using std::vector; #include <glog/logging.h> -#include "gutil/logging-inl.h" + +#include "kudu/gutil/logging-inl.h" // // Find*() @@ -94,29 +95,29 @@ using std::vector; // This version assumes the key is printable, and includes it in the fatal log // message. template <class Collection> -const typename Collection::value_type::second_type& +const typename Collection::mapped_type& FindOrDie(const Collection& collection, - const typename Collection::value_type::first_type& key) { - typename Collection::const_iterator it = collection.find(key); + const typename Collection::key_type& key) { + auto it = collection.find(key); CHECK(it != collection.end()) << "Map key not found: " << key; return it->second; } // Same as above, but returns a non-const reference. template <class Collection> -typename Collection::value_type::second_type& +typename Collection::mapped_type& FindOrDie(Collection& collection, // NOLINT - const typename Collection::value_type::first_type& key) { - typename Collection::iterator it = collection.find(key); + const typename Collection::key_type& key) { + auto it = collection.find(key); CHECK(it != collection.end()) << "Map key not found: " << key; return it->second; } // Same as FindOrDie above, but doesn't log the key on failure. template <class Collection> -const typename Collection::value_type::second_type& +const typename Collection::mapped_type& FindOrDieNoPrint(const Collection& collection, - const typename Collection::value_type::first_type& key) { + const typename Collection::key_type& key) { typename Collection::const_iterator it = collection.find(key); CHECK(it != collection.end()) << "Map key not found"; return it->second; @@ -124,9 +125,9 @@ FindOrDieNoPrint(const Collection& collection, // Same as above, but returns a non-const reference. template <class Collection> -typename Collection::value_type::second_type& +typename Collection::mapped_type& FindOrDieNoPrint(Collection& collection, // NOLINT - const typename Collection::value_type::first_type& key) { + const typename Collection::key_type& key) { typename Collection::iterator it = collection.find(key); CHECK(it != collection.end()) << "Map key not found"; return it->second; @@ -142,11 +143,11 @@ FindOrDieNoPrint(Collection& collection, // NOLINT // string values, and you pass a char* as the default "value," either use the // returned value immediately or store it in a string (not string&). Details: template <class Collection> -const typename Collection::value_type::second_type& +const typename Collection::mapped_type& FindWithDefault(const Collection& collection, - const typename Collection::value_type::first_type& key, - const typename Collection::value_type::second_type& value) { - typename Collection::const_iterator it = collection.find(key); + const typename Collection::key_type& key, + const typename Collection::mapped_type& value) { + auto it = collection.find(key); if (it == collection.end()) { return value; } @@ -156,10 +157,10 @@ FindWithDefault(const Collection& collection, // Returns a pointer to the const value associated with the given key if it // exists, or NULL otherwise. template <class Collection> -const typename Collection::value_type::second_type* +const typename Collection::mapped_type* FindOrNull(const Collection& collection, - const typename Collection::value_type::first_type& key) { - typename Collection::const_iterator it = collection.find(key); + const typename Collection::key_type& key) { + auto it = collection.find(key); if (it == collection.end()) { return 0; } @@ -168,16 +169,62 @@ FindOrNull(const Collection& collection, // Same as above but returns a pointer to the non-const value. template <class Collection> -typename Collection::value_type::second_type* +typename Collection::mapped_type* FindOrNull(Collection& collection, // NOLINT - const typename Collection::value_type::first_type& key) { - typename Collection::iterator it = collection.find(key); + const typename Collection::key_type& key) { + auto it = collection.find(key); if (it == collection.end()) { return 0; } return &it->second; } +// Returns a pointer to the const value associated with the greatest key +// that's less than or equal to the given key, or NULL if no such key exists. +template <class Collection> +const typename Collection::mapped_type* +FindFloorOrNull(const Collection& collection, + const typename Collection::key_type& key) { + auto it = collection.upper_bound(key); + if (it == collection.begin()) { + return 0; + } + return &(--it)->second; +} + +// Same as above but returns a pointer to the non-const value. +template <class Collection> +typename Collection::mapped_type* +FindFloorOrNull(Collection& collection, // NOLINT + const typename Collection::key_type& key) { + auto it = collection.upper_bound(key); + if (it == collection.begin()) { + return 0; + } + return &(--it)->second; +} + +// Returns a const-reference to the value associated with the greatest key +// that's less than or equal to the given key, or crashes if it does not exist. +template <class Collection> +const typename Collection::mapped_type& +FindFloorOrDie(const Collection& collection, + const typename Collection::key_type& key) { + auto it = collection.upper_bound(key); + CHECK(it != collection.begin()); + return (--it)->second; +} + +// Same as above, but returns a non-const reference. +template <class Collection> +typename Collection::mapped_type& +FindFloorOrDie(Collection& collection, + const typename Collection::key_type& key) { + auto it = collection.upper_bound(key); + CHECK(it != collection.begin()); + return (--it)->second; +} + // Returns the pointer value associated with the given key. If none is found, // NULL is returned. The function is designed to be used with a map of keys to // pointers. @@ -185,12 +232,12 @@ FindOrNull(Collection& collection, // NOLINT // This function does not distinguish between a missing key and a key mapped // to a NULL value. template <class Collection> -typename Collection::value_type::second_type +typename Collection::mapped_type FindPtrOrNull(const Collection& collection, - const typename Collection::value_type::first_type& key) { - typename Collection::const_iterator it = collection.find(key); + const typename Collection::key_type& key) { + auto it = collection.find(key); if (it == collection.end()) { - return typename Collection::value_type::second_type(0); + return typename Collection::mapped_type(0); } return it->second; } @@ -200,23 +247,38 @@ FindPtrOrNull(const Collection& collection, // This function is needed for containers that propagate constness to the // pointee, such as boost::ptr_map. template <class Collection> -typename Collection::value_type::second_type +typename Collection::mapped_type FindPtrOrNull(Collection& collection, // NOLINT - const typename Collection::value_type::first_type& key) { - typename Collection::iterator it = collection.find(key); + const typename Collection::key_type& key) { + auto it = collection.find(key); if (it == collection.end()) { - return typename Collection::value_type::second_type(0); + return typename Collection::mapped_type(0); } return it->second; } +// FindPtrOrNull like function for maps whose value is a smart pointer like shared_ptr or +// unique_ptr. +// Returns the raw pointer contained in the smart pointer for the first found key, if it exists, +// or null if it doesn't. +template <class Collection> +typename Collection::mapped_type::element_type* +FindPointeeOrNull(const Collection& collection, // NOLINT, + const typename Collection::key_type& key) { + auto it = collection.find(key); + if (it == collection.end()) { + return nullptr; + } + return it->second.get(); +} + // Finds the value associated with the given key and copies it to *value (if not // NULL). Returns false if the key was not found, true otherwise. template <class Collection, class Key, class Value> bool FindCopy(const Collection& collection, const Key& key, Value* const value) { - typename Collection::const_iterator it = collection.find(key); + auto it = collection.find(key); if (it == collection.end()) { return false; } @@ -233,7 +295,7 @@ bool FindCopy(const Collection& collection, // Returns true iff the given collection contains the given key. template <class Collection, class Key> bool ContainsKey(const Collection& collection, const Key& key) { - typename Collection::const_iterator it = collection.find(key); + auto it = collection.find(key); return it != collection.end(); } @@ -274,8 +336,8 @@ bool InsertOrUpdate(Collection* const collection, // Same as above, except that the key and value are passed separately. template <class Collection> bool InsertOrUpdate(Collection* const collection, - const typename Collection::value_type::first_type& key, - const typename Collection::value_type::second_type& value) { + const typename Collection::key_type& key, + const typename Collection::mapped_type& value) { return InsertOrUpdate( collection, typename Collection::value_type(key, value)); } @@ -297,8 +359,8 @@ void InsertOrUpdateMany(Collection* const collection, template <class Collection> bool InsertAndDeleteExisting( Collection* const collection, - const typename Collection::value_type::first_type& key, - const typename Collection::value_type::second_type& value) { + const typename Collection::key_type& key, + const typename Collection::mapped_type& value) { pair<typename Collection::iterator, bool> ret = collection->insert(typename Collection::value_type(key, value)); if (!ret.second) { @@ -323,8 +385,8 @@ bool InsertIfNotPresent(Collection* const collection, template <class Collection> bool InsertIfNotPresent( Collection* const collection, - const typename Collection::value_type::first_type& key, - const typename Collection::value_type::second_type& value) { + const typename Collection::key_type& key, + const typename Collection::mapped_type& value) { return InsertIfNotPresent( collection, typename Collection::value_type(key, value)); } @@ -347,9 +409,8 @@ void InsertOrDieNoPrint(Collection* const collection, // present. template <class Collection> void InsertOrDie(Collection* const collection, - const typename Collection::value_type::first_type& key, - const typename Collection::value_type::second_type& data) { - typedef typename Collection::value_type value_type; + const typename Collection::key_type& key, + const typename Collection::mapped_type& data) { CHECK(InsertIfNotPresent(collection, key, data)) << "duplicate key: " << key; } @@ -358,9 +419,8 @@ void InsertOrDie(Collection* const collection, template <class Collection> void InsertOrDieNoPrint( Collection* const collection, - const typename Collection::value_type::first_type& key, - const typename Collection::value_type::second_type& data) { - typedef typename Collection::value_type value_type; + const typename Collection::key_type& key, + const typename Collection::mapped_type& data) { CHECK(InsertIfNotPresent(collection, key, data)) << "duplicate key."; } @@ -371,12 +431,12 @@ void InsertOrDieNoPrint( // SomeProto& proto = InsertKeyOrDie(&m, 3); // proto.set_field("foo"); template <class Collection> -typename Collection::value_type::second_type& InsertKeyOrDie( +typename Collection::mapped_type& InsertKeyOrDie( Collection* const collection, - const typename Collection::value_type::first_type& key) { + const typename Collection::key_type& key) { typedef typename Collection::value_type value_type; pair<typename Collection::iterator, bool> res = - collection->insert(value_type(key, typename value_type::second_type())); + collection->insert(value_type(key, typename Collection::mapped_type())); CHECK(res.second) << "duplicate key: " << key; return res.first->second; } @@ -389,7 +449,7 @@ typename Collection::value_type::second_type& InsertKeyOrDie( // pair if it's not already present. Returns a reference to the value associated // with the key. template <class Collection> -typename Collection::value_type::second_type& +typename Collection::mapped_type& LookupOrInsert(Collection* const collection, const typename Collection::value_type& vt) { return collection->insert(vt).first->second; @@ -397,10 +457,10 @@ LookupOrInsert(Collection* const collection, // Same as above except the key-value are passed separately. template <class Collection> -typename Collection::value_type::second_type& +typename Collection::mapped_type& LookupOrInsert(Collection* const collection, - const typename Collection::value_type::first_type& key, - const typename Collection::value_type::second_type& value) { + const typename Collection::key_type& key, + const typename Collection::mapped_type& value) { return LookupOrInsert( collection, typename Collection::value_type(key, value)); } @@ -418,13 +478,13 @@ LookupOrInsert(Collection* const collection, template <typename Sequence, typename Collection> void AddTokenCounts( const Sequence& sequence, - const typename Collection::value_type::second_type& increment, + const typename Collection::mapped_type& increment, Collection* const count_map) { for (typename Sequence::const_iterator it = sequence.begin(); it != sequence.end(); ++it) { - typename Collection::value_type::second_type& value = + typename Collection::mapped_type& value = LookupOrInsert(count_map, *it, - typename Collection::value_type::second_type()); + typename Collection::mapped_type()); value += increment; } } @@ -448,13 +508,13 @@ void MapUtilAssignNewInstance(T** location, const Arg &arg) { // inserting a new key, value pair involves constructing a new heap-allocated // Value, and storing a pointer to that in the collection. template <class Collection> -typename Collection::value_type::second_type& +typename Collection::mapped_type& LookupOrInsertNew(Collection* const collection, - const typename Collection::value_type::first_type& key) { + const typename Collection::key_type& key) { pair<typename Collection::iterator, bool> ret = collection->insert( typename Collection::value_type(key, - static_cast<typename Collection::value_type::second_type>(NULL))); + static_cast<typename Collection::mapped_type>(NULL))); if (ret.second) { // This helper is needed to 'extract' the Value type from the type of the // container value, which is (Value*). @@ -466,15 +526,15 @@ LookupOrInsertNew(Collection* const collection, // Same as above but constructs the value using the single-argument constructor // and the given "arg". template <class Collection, class Arg> -typename Collection::value_type::second_type& +typename Collection::mapped_type& LookupOrInsertNew(Collection* const collection, - const typename Collection::value_type::first_type& key, + const typename Collection::key_type& key, const Arg& arg) { pair<typename Collection::iterator, bool> ret = collection->insert( typename Collection::value_type( key, - static_cast<typename Collection::value_type::second_type>(NULL))); + static_cast<typename Collection::mapped_type>(NULL))); if (ret.second) { // This helper is needed to 'extract' the Value type from the type of the // container value, which is (Value*). @@ -497,12 +557,12 @@ LookupOrInsertNew(Collection* const collection, // LookupOrInsertNewLinkedPtr, this function returns the shared_ptr instead of // the raw pointer. Value::element_type must be default constructable. template <class Collection> -typename Collection::value_type::second_type& +typename Collection::mapped_type& LookupOrInsertNewSharedPtr( Collection* const collection, - const typename Collection::value_type::first_type& key) { - typedef typename Collection::value_type::second_type SharedPtr; - typedef typename Collection::value_type::second_type::element_type Element; + const typename Collection::key_type& key) { + typedef typename Collection::mapped_type SharedPtr; + typedef typename Collection::mapped_type::element_type Element; pair<typename Collection::iterator, bool> ret = collection->insert(typename Collection::value_type(key, SharedPtr())); if (ret.second) { @@ -517,13 +577,13 @@ LookupOrInsertNewSharedPtr( // here. On the other hand it does not matter how expensive the construction of // the actual stored value is, as that only occurs if necessary. template <class Collection, class Arg> -typename Collection::value_type::second_type& +typename Collection::mapped_type& LookupOrInsertNewSharedPtr( Collection* const collection, - const typename Collection::value_type::first_type& key, + const typename Collection::key_type& key, const Arg& arg) { - typedef typename Collection::value_type::second_type SharedPtr; - typedef typename Collection::value_type::second_type::element_type Element; + typedef typename Collection::mapped_type SharedPtr; + typedef typename Collection::mapped_type::element_type Element; pair<typename Collection::iterator, bool> ret = collection->insert(typename Collection::value_type(key, SharedPtr())); if (ret.second) { @@ -545,9 +605,9 @@ LookupOrInsertNewSharedPtr( // address of an already existing value, rather than updating it. template <class Collection> bool UpdateReturnCopy(Collection* const collection, - const typename Collection::value_type::first_type& key, - const typename Collection::value_type::second_type& value, - typename Collection::value_type::second_type* previous) { + const typename Collection::key_type& key, + const typename Collection::mapped_type& value, + typename Collection::mapped_type* previous) { pair<typename Collection::iterator, bool> ret = collection->insert(typename Collection::value_type(key, value)); if (!ret.second) { @@ -565,7 +625,7 @@ bool UpdateReturnCopy(Collection* const collection, template <class Collection> bool UpdateReturnCopy(Collection* const collection, const typename Collection::value_type& vt, - typename Collection::value_type::second_type* previous) { + typename Collection::mapped_type* previous) { pair<typename Collection::iterator, bool> ret = collection->insert(vt); if (!ret.second) { @@ -587,7 +647,7 @@ bool UpdateReturnCopy(Collection* const collection, // twice. Unlike UpdateReturnCopy this also does not come with the issue of an // undefined previous* in case new data was inserted. template <class Collection> -typename Collection::value_type::second_type* const +typename Collection::mapped_type* const InsertOrReturnExisting(Collection* const collection, const typename Collection::value_type& vt) { pair<typename Collection::iterator, bool> ret = collection->insert(vt); @@ -600,11 +660,11 @@ InsertOrReturnExisting(Collection* const collection, // Same as above, except for explicit key and data. template <class Collection> -typename Collection::value_type::second_type* const +typename Collection::mapped_type* const InsertOrReturnExisting( Collection* const collection, - const typename Collection::value_type::first_type& key, - const typename Collection::value_type::second_type& data) { + const typename Collection::key_type& key, + const typename Collection::mapped_type& data) { return InsertOrReturnExisting(collection, typename Collection::value_type(key, data)); } @@ -638,15 +698,17 @@ void ReverseMap(const Collection& collection, // if (value_ptr.get()) // value_ptr->DoSomething(); // +// Note: if 'collection' is a multimap, this will only erase and return the +// first value. template <class Collection> -typename Collection::value_type::second_type EraseKeyReturnValuePtr( +typename Collection::mapped_type EraseKeyReturnValuePtr( Collection* const collection, - const typename Collection::value_type::first_type& key) { - typename Collection::iterator it = collection->find(key); + const typename Collection::key_type& key) { + auto it = collection->find(key); if (it == collection->end()) { - return NULL; + return typename Collection::mapped_type(); } - typename Collection::value_type::second_type v = it->second; + typename Collection::mapped_type v = std::move(it->second); collection->erase(it); return v; } @@ -738,10 +800,59 @@ void AppendValuesFromMap(const MapContainer& map_container, if (value_container->empty()) { value_container->reserve(map_container.size()); } - for (typename MapContainer::const_iterator it = map_container.begin(); - it != map_container.end(); ++it) { - value_container->push_back(it->second); + for (const auto& entry : map_container) { + value_container->push_back(entry.second); } } +// 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-impala/blob/02f3e3fc/be/src/gutil/mathlimits.cc ---------------------------------------------------------------------- diff --git a/be/src/gutil/mathlimits.cc b/be/src/gutil/mathlimits.cc index 0311d0d..dcc261d 100644 --- a/be/src/gutil/mathlimits.cc +++ b/be/src/gutil/mathlimits.cc @@ -1,24 +1,29 @@ // Copyright 2005 Google Inc. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. // // --- // // -#include "gutil/mathlimits.h" +#include "kudu/gutil/mathlimits.h" -#include "gutil/integral_types.h" +#include "kudu/gutil/integral_types.h" // MSVC++ 2005 thinks the header declaration was a definition, and // erroneously flags these as a duplicate definition. @@ -107,9 +112,6 @@ DEF_UNSIGNED_INT_LIMITS(uint16) DEF_UNSIGNED_INT_LIMITS(uint32) DEF_UNSIGNED_INT_LIMITS(uint64) -DEF_SIGNED_INT_LIMITS(long int) -DEF_UNSIGNED_INT_LIMITS(unsigned long int) - DEF_FP_LIMITS(float, FLT) DEF_FP_LIMITS(double, DBL) DEF_FP_LIMITS(long double, LDBL); http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/02f3e3fc/be/src/gutil/mathlimits.h ---------------------------------------------------------------------- diff --git a/be/src/gutil/mathlimits.h b/be/src/gutil/mathlimits.h index 48f1d8e..9d69733 100644 --- a/be/src/gutil/mathlimits.h +++ b/be/src/gutil/mathlimits.h @@ -1,16 +1,21 @@ // Copyright 2005 Google Inc. // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. // // --- // @@ -29,6 +34,7 @@ #include <math.h> #include <string.h> #include <cfloat> +#include <cmath> // ========================================================================= // @@ -203,11 +209,11 @@ DECL_UNSIGNED_INT_LIMITS(unsigned long long int) static bool IsNegInf(const Type x) { return _fpclass(x) == _FPCLASS_NINF; } #else #define DECL_FP_LIMIT_FUNCS \ - static bool IsFinite(const Type x) { return !isinf(x) && !isnan(x); } \ - static bool IsNaN(const Type x) { return isnan(x); } \ - static bool IsInf(const Type x) { return isinf(x); } \ - static bool IsPosInf(const Type x) { return isinf(x) && x > 0; } \ - static bool IsNegInf(const Type x) { return isinf(x) && x < 0; } + static bool IsFinite(const Type x) { return !std::isinf(x) && !std::isnan(x); } \ + static bool IsNaN(const Type x) { return std::isnan(x); } \ + static bool IsInf(const Type x) { return std::isinf(x); } \ + static bool IsPosInf(const Type x) { return std::isinf(x) && x > 0; } \ + static bool IsNegInf(const Type x) { return std::isinf(x) && x < 0; } #endif // We can't put floating-point constant values in the header here because http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/02f3e3fc/be/src/gutil/move.h ---------------------------------------------------------------------- diff --git a/be/src/gutil/move.h b/be/src/gutil/move.h index d2cd3df..1765108 100644 --- a/be/src/gutil/move.h +++ b/be/src/gutil/move.h @@ -105,8 +105,8 @@ // // // Foo f(MakeFoo()); // R-value so alternate conversion executed. -// Foo f_copy(f.Pass()); // R-value so alternate conversion executed. -// f = f_copy.Pass(); // R-value so alternate conversion executed. +// Foo f_copy(std::move(f)); // R-value so alternate conversion executed. +// f = std::move(f_copy); // R-value so alternate conversion executed. // // // IMPLEMENTATION SUBTLETIES WITH RValue @@ -136,6 +136,16 @@ // choose the one that adheres to the standard. // // +// WHY HAVE typedef void MoveOnlyTypeForCPP03 +// +// Callback<>/Bind() needs to understand movable-but-not-copyable semantics +// to call .Pass() appropriately when it is expected to transfer the value. +// The cryptic typedef MoveOnlyTypeForCPP03 is added to make this check +// easy and automatic in helper templates for Callback<>/Bind(). +// See IsMoveOnlyType template and its usage in base/callback_internal.h +// for more details. +// +// // COMPARED TO C++11 // // In C++11, you would implement this functionality using an r-value reference @@ -202,6 +212,7 @@ public: \ operator rvalue_type() { return rvalue_type(this); } \ type Pass() { return type(rvalue_type(this)); } \ + typedef void MoveOnlyTypeForCPP03; \ private: #endif // BASE_MOVE_H_ http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/02f3e3fc/be/src/gutil/once.cc ---------------------------------------------------------------------- diff --git a/be/src/gutil/once.cc b/be/src/gutil/once.cc index a50c34a..1b97f8f 100644 --- a/be/src/gutil/once.cc +++ b/be/src/gutil/once.cc @@ -1,10 +1,10 @@ // Copyright 2008 Google Inc. All Rights Reserved. #include <glog/logging.h> -#include "gutil/logging-inl.h" -#include "gutil/once.h" -#include "gutil/dynamic_annotations.h" -#include "gutil/spinlock_internal.h" +#include "kudu/gutil/logging-inl.h" +#include "kudu/gutil/once.h" +#include "kudu/gutil/dynamic_annotations.h" +#include "kudu/gutil/spinlock_internal.h" // All modifications to a GoogleOnceType occur inside GoogleOnceInternalInit. // The fast path reads the variable with an acquire-load.. http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/02f3e3fc/be/src/gutil/once.h ---------------------------------------------------------------------- diff --git a/be/src/gutil/once.h b/be/src/gutil/once.h index c81e871..ff161c5 100644 --- a/be/src/gutil/once.h +++ b/be/src/gutil/once.h @@ -24,12 +24,12 @@ #ifndef BASE_ONCE_H_ #define BASE_ONCE_H_ -#include "gutil/atomicops.h" -#include "gutil/integral_types.h" -#include "gutil/dynamic_annotations.h" -#include "gutil/macros.h" -#include "gutil/port.h" -#include "gutil/type_traits.h" +#include "kudu/gutil/atomicops.h" +#include "kudu/gutil/integral_types.h" +#include "kudu/gutil/dynamic_annotations.h" +#include "kudu/gutil/macros.h" +#include "kudu/gutil/port.h" +#include "kudu/gutil/type_traits.h" // The following enum values are not for use by clients enum { http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/02f3e3fc/be/src/gutil/paranoid.h ---------------------------------------------------------------------- diff --git a/be/src/gutil/paranoid.h b/be/src/gutil/paranoid.h index 53159a0..01f34b7 100644 --- a/be/src/gutil/paranoid.h +++ b/be/src/gutil/paranoid.h @@ -7,7 +7,8 @@ #define BASE_PARANOID_H_ #include <glog/logging.h> -#include "gutil/logging-inl.h" + +#include "kudu/gutil/logging-inl.h" // Sanitize a bool value which might be sour. // http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/02f3e3fc/be/src/gutil/port.h ---------------------------------------------------------------------- diff --git a/be/src/gutil/port.h b/be/src/gutil/port.h index c9f19f4..6222cca 100644 --- a/be/src/gutil/port.h +++ b/be/src/gutil/port.h @@ -18,7 +18,7 @@ #include <malloc.h> // for memalign() #endif -#include "gutil/integral_types.h" +#include "kudu/gutil/integral_types.h" // Must happens before inttypes.h inclusion */ #if defined(__APPLE__) @@ -223,66 +223,6 @@ typedef int uid_t; // Linux has this in <linux/errno.h> #define EXFULL ENOMEM // not really that great a translation... -// Mach-O supports sections (albeit with small names), but doesn't have -// vars at the beginning and end. Instead you should call the function -// getsectdata("__DATA", name, &size). -#define HAVE_ATTRIBUTE_SECTION 1 - -// Any function with ATTRIBUTE_SECTION must not be inlined, or it will -// be placed into whatever section its caller is placed into. -#define ATTRIBUTE_SECTION(name) \ - __attribute__ ((section ("__DATA, " #name))) __attribute__ ((noinline)) - -#define ENUM_DYLD_BOOL // so that we don't pollute the global namespace -extern "C" { - #include <mach-o/getsect.h> - #include <mach-o/dyld.h> -} -class AssignAttributeStartEnd { - public: - AssignAttributeStartEnd(const char* name, char** pstart, char** pend) { - // Find out what dynamic library name is defined in - for (int i = _dyld_image_count() - 1; i >= 0; --i) { - const mach_header* hdr = _dyld_get_image_header(i); - uint32_t len; - *pstart = getsectdatafromheader(hdr, "__DATA", name, &len); - if (*pstart) { // NULL if not defined in this dynamic library - *pstart += _dyld_get_image_vmaddr_slide(i); // correct for reloc - *pend = *pstart + len; - return; - } - } - // If we get here, not defined in a dll at all. See if defined statically. - unsigned long len; // don't ask me why this type isn't uint32_t too... - *pstart = getsectdata("__DATA", name, &len); - *pend = *pstart + len; - } -}; - -// 1) DEFINE_ATTRIBUTE_SECTION_VARS: must be called once per unique -// name. You want to make sure this is executed before any -// DECLARE_ATTRIBUTE_SECTION_VARS; the easiest way is to put them -// in the same .cc file. Put this call at the global level. -// 2) INIT_ATTRIBUTE_SECTION_VARS: you can scatter calls to this in -// multiple places to help ensure execution before any -// DECLARE_ATTRIBUTE_SECTION_VARS. You must have at least one -// DEFINE, but you can have many INITs. Put each in its own scope. -// 3) DECLARE_ATTRIBUTE_SECTION_VARS: must be called before using -// ATTRIBUTE_SECTION_START or ATTRIBUTE_SECTION_STOP on a name. -// Put this call at the global level. -#define DECLARE_ATTRIBUTE_SECTION_VARS(name) \ - extern char* __start_##name; \ - extern char* __stop_##name; - -#define INIT_ATTRIBUTE_SECTION_VARS(name) \ - DECLARE_ATTRIBUTE_SECTION_VARS(name); \ - static const AssignAttributeStartEnd __assign_##name( \ - #name, &__start_##name, &__stop_##name) - -#define DEFINE_ATTRIBUTE_SECTION_VARS(name) \ - char* __start_##name, *__stop_##name; \ - INIT_ATTRIBUTE_SECTION_VARS(name) - // Darwin doesn't have strnlen. No comment. inline size_t strnlen(const char *s, size_t maxlen) { const char* end = (const char *)memchr(s, '\0', maxlen); @@ -434,6 +374,17 @@ inline void* memrchr(const void* bytes, int find_char, size_t len) { #define ATTRIBUTE_WEAK __attribute__ ((weak)) #define HAVE_ATTRIBUTE_WEAK 1 +// For deprecated functions or variables, generate a warning at usage sites. +// Verified to work as early as GCC 3.1.1 and clang 3.2 (so we'll assume any +// clang is new enough). +#if defined(__clang__) || \ + (defined(COMPILER_GCC) && \ + (__GNUC__ * 10000 + __GNUC_MINOR__ * 100) >= 30200) +#define ATTRIBUTE_DEPRECATED(msg) __attribute__ ((deprecated (msg) )) +#else +#define ATTRIBUTE_DEPRECATED(msg) +#endif + // Tell the compiler to use "initial-exec" mode for a thread-local variable. // See http://people.redhat.com/drepper/tls.pdf for the gory details. #define ATTRIBUTE_INITIAL_EXEC __attribute__ ((tls_model ("initial-exec"))) @@ -462,54 +413,20 @@ inline void* memrchr(const void* bytes, int find_char, size_t len) { #define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS #endif +// Tell ThreadSanitizer to ignore a given function. This can dramatically reduce +// the running time and memory requirements for racy code when TSAN is active. +// GCC does not support this attribute at the time of this writing (GCC 4.8). +#if defined(__llvm__) +#define ATTRIBUTE_NO_SANITIZE_THREAD \ + __attribute__((no_sanitize_thread)) +#else +#define ATTRIBUTE_NO_SANITIZE_THREAD +#endif #ifndef HAVE_ATTRIBUTE_SECTION // may have been pre-set to 0, e.g. for Darwin #define HAVE_ATTRIBUTE_SECTION 1 #endif -#if HAVE_ATTRIBUTE_SECTION // define section support for the case of GCC - -// -// Tell the compiler/linker to put a given function into a section and define -// "__start_ ## name" and "__stop_ ## name" symbols to bracket the section. -// Sections can not span more than none compilation unit. -// This functionality is supported by GNU linker. -// Any function with ATTRIBUTE_SECTION must not be inlined, or it will -// be placed into whatever section its caller is placed into. -// -#ifndef ATTRIBUTE_SECTION -#define ATTRIBUTE_SECTION(name) \ - __attribute__ ((section (#name))) __attribute__ ((noinline)) -#endif - -// -// Weak section declaration to be used as a global declaration -// for ATTRIBUTE_SECTION_START|STOP(name) to compile and link -// even without functions with ATTRIBUTE_SECTION(name). -// DEFINE_ATTRIBUTE_SECTION should be in the exactly one file; it's -// a no-op on ELF but not on Mach-O. -// -#ifndef DECLARE_ATTRIBUTE_SECTION_VARS -#define DECLARE_ATTRIBUTE_SECTION_VARS(name) \ - extern char __start_##name[] ATTRIBUTE_WEAK; \ - extern char __stop_##name[] ATTRIBUTE_WEAK -#endif -#ifndef DEFINE_ATTRIBUTE_SECTION_VARS -#define INIT_ATTRIBUTE_SECTION_VARS(name) -#define DEFINE_ATTRIBUTE_SECTION_VARS(name) -#endif - -// -// Return void* pointers to start/end of a section of code with -// functions having ATTRIBUTE_SECTION(name). -// Returns 0 if no such functions exits. -// One must DECLARE_ATTRIBUTE_SECTION_VARS(name) for this to compile and link. -// -#define ATTRIBUTE_SECTION_START(name) (reinterpret_cast<void*>(__start_##name)) -#define ATTRIBUTE_SECTION_STOP(name) (reinterpret_cast<void*>(__stop_##name)) - -#endif // HAVE_ATTRIBUTE_SECTION - // // The legacy prod71 libc does not provide the stack alignment required for use // of SSE intrinsics. In order to properly use the intrinsics you need to use @@ -551,6 +468,40 @@ inline void* memrchr(const void* bytes, int find_char, size_t len) { #define MUST_USE_RESULT #endif +// Annotate a virtual method indicating it must be overriding a virtual +// method in the parent class. +// Use like: +// virtual void foo() OVERRIDE; +#if defined(COMPILER_MSVC) +#define OVERRIDE override +#elif defined(__clang__) +#define OVERRIDE override +#elif defined(COMPILER_GCC) && __cplusplus >= 201103 && \ + (__GNUC__ * 10000 + __GNUC_MINOR__ * 100) >= 40700 +// GCC 4.7 supports explicit virtual overrides when C++11 support is enabled. +#define OVERRIDE override +#else +#define OVERRIDE +#endif + +// Annotate a virtual method indicating that subclasses must not override it, +// or annotate a class to indicate that it cannot be subclassed. +// Use like: +// virtual void foo() FINAL; +// class B FINAL : public A {}; +#if defined(COMPILER_MSVC) +// TODO(jered): Change this to "final" when chromium no longer uses MSVC 2010. +#define FINAL sealed +#elif defined(__clang__) +#define FINAL final +#elif defined(COMPILER_GCC) && __cplusplus >= 201103 && \ + (__GNUC__ * 10000 + __GNUC_MINOR__ * 100) >= 40700 +// GCC 4.7 supports explicit virtual overrides when C++11 support is enabled. +#define FINAL final +#else +#define FINAL +#endif + #if defined(__GNUC__) // Defined behavior on some of the uarchs: // PREFETCH_HINT_T0: @@ -570,7 +521,7 @@ enum PrefetchHint { #endif extern inline void prefetch(const char *x, int hint) { -#if defined(__llvm__) || defined(__INTEL_COMPILER) +#if defined(__llvm__) // In the gcc version of prefetch(), hint is only a constant _after_ inlining // (assumed to have been successful). llvm views things differently, and // checks constant-ness _before_ inlining. This leads to compilation errors @@ -714,7 +665,6 @@ inline void aligned_free(void *aligned_memory) { #define ATTRIBUTE_INITIAL_EXEC #define ATTRIBUTE_NONNULL(arg_index) #define ATTRIBUTE_NORETURN -#define HAVE_ATTRIBUTE_SECTION 0 #define ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC #define REQUIRE_STACK_ALIGN_TRAMPOLINE (0) #define MUST_USE_RESULT @@ -798,18 +748,6 @@ struct AlignType { typedef char result[Size]; }; #define ALIGNED_CHAR_ARRAY ALIGNED_CHAR_ARRAY_is_not_available_without_Cplusplus #endif // __cplusplus -#if !HAVE_ATTRIBUTE_SECTION // provide dummy definitions - -#define ATTRIBUTE_SECTION(name) -#define INIT_ATTRIBUTE_SECTION_VARS(name) -#define DEFINE_ATTRIBUTE_SECTION_VARS(name) -#define DECLARE_ATTRIBUTE_SECTION_VARS(name) -#define ATTRIBUTE_SECTION_START(name) (reinterpret_cast<void*>(0)) -#define ATTRIBUTE_SECTION_STOP(name) (reinterpret_cast<void*>(0)) - -#endif // !HAVE_ATTRIBUTE_SECTION - - #ifdef _MSC_VER /* if Visual C++ */ // This compiler flag can be easily overlooked on MSVC. @@ -998,7 +936,7 @@ inline int isinf(double x) { return 0; } -// #include "conflict-signal.h" +// #include "kudu/conflict-signal.h" typedef void (*sig_t)(int); // These actually belong in errno.h but there's a name confilict in errno @@ -1042,7 +980,7 @@ typedef short int16_t; #endif // _MSC_VER #ifdef STL_MSVC // not always the same as _MSC_VER -#include "base/port_hash.h" +#include "kudu/base/port_hash.h" #else struct PortableHashBase { }; #endif http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/02f3e3fc/be/src/gutil/proto/types.pb.cc ---------------------------------------------------------------------- diff --git a/be/src/gutil/proto/types.pb.cc b/be/src/gutil/proto/types.pb.cc deleted file mode 100644 index b3ebe01..0000000 --- a/be/src/gutil/proto/types.pb.cc +++ /dev/null @@ -1,107 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! - -#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION -#include "gutil/proto/types.pb.h" - -#include <algorithm> - -#include <google/protobuf/stubs/once.h> -#include <google/protobuf/io/coded_stream.h> -#include <google/protobuf/wire_format_lite_inl.h> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/reflection_ops.h> -#include <google/protobuf/wire_format.h> -// @@protoc_insertion_point(includes) - -namespace common { - -namespace { - -const ::google::protobuf::EnumDescriptor* DataType_descriptor_ = NULL; - -} // namespace - - -void protobuf_AssignDesc_gutil_2fproto_2ftypes_2eproto() { - protobuf_AddDesc_gutil_2fproto_2ftypes_2eproto(); - const ::google::protobuf::FileDescriptor* file = - ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName( - "gutil/proto/types.proto"); - GOOGLE_CHECK(file != NULL); - DataType_descriptor_ = file->enum_type(0); -} - -namespace { - -GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_); -inline void protobuf_AssignDescriptorsOnce() { - ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_, - &protobuf_AssignDesc_gutil_2fproto_2ftypes_2eproto); -} - -void protobuf_RegisterTypes(const ::std::string&) { - protobuf_AssignDescriptorsOnce(); -} - -} // namespace - -void protobuf_ShutdownFile_gutil_2fproto_2ftypes_2eproto() { -} - -void protobuf_AddDesc_gutil_2fproto_2ftypes_2eproto() { - static bool already_here = false; - if (already_here) return; - already_here = true; - GOOGLE_PROTOBUF_VERIFY_VERSION; - - ::google::protobuf::DescriptorPool::InternalAddGeneratedFile( - "\n\027gutil/proto/types.proto\022\006common*\247\001\n\010Da" - "taType\022\t\n\005INT32\020\001\022\t\n\005INT64\020\002\022\n\n\006UINT32\020\010" - "\022\n\n\006UINT64\020\003\022\t\n\005FLOAT\020\t\022\n\n\006DOUBLE\020\005\022\010\n\004B" - "OOL\020\006\022\010\n\004DATE\020\n\022\014\n\010DATETIME\020\004\022\n\n\006STRING\020" - "\000\022\n\n\006BINARY\020\007\022\r\n\tDATA_TYPE\020\013\022\r\n\tNULL_TYP" - "E\020\014B4\n%com.google.datawarehouse.common.p" - "rotoB\013CommonEnums", 257); - ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( - "gutil/proto/types.proto", &protobuf_RegisterTypes); - ::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_gutil_2fproto_2ftypes_2eproto); -} - -// Force AddDescriptors() to be called at static initialization time. -struct StaticDescriptorInitializer_gutil_2fproto_2ftypes_2eproto { - StaticDescriptorInitializer_gutil_2fproto_2ftypes_2eproto() { - protobuf_AddDesc_gutil_2fproto_2ftypes_2eproto(); - } -} static_descriptor_initializer_gutil_2fproto_2ftypes_2eproto_; - -const ::google::protobuf::EnumDescriptor* DataType_descriptor() { - protobuf_AssignDescriptorsOnce(); - return DataType_descriptor_; -} -bool DataType_IsValid(int value) { - switch(value) { - case 0: - case 1: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - case 9: - case 10: - case 11: - case 12: - return true; - default: - return false; - } -} - - -// @@protoc_insertion_point(namespace_scope) - -} // namespace common - -// @@protoc_insertion_point(global_scope) http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/02f3e3fc/be/src/gutil/proto/types.pb.h ---------------------------------------------------------------------- diff --git a/be/src/gutil/proto/types.pb.h b/be/src/gutil/proto/types.pb.h deleted file mode 100644 index 88f6551..0000000 --- a/be/src/gutil/proto/types.pb.h +++ /dev/null @@ -1,94 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: gutil/proto/types.proto - -#ifndef PROTOBUF_gutil_2fproto_2ftypes_2eproto__INCLUDED -#define PROTOBUF_gutil_2fproto_2ftypes_2eproto__INCLUDED - -#include <string> - -#include <google/protobuf/stubs/common.h> - -#if GOOGLE_PROTOBUF_VERSION < 2004000 -#error This file was generated by a newer version of protoc which is -#error incompatible with your Protocol Buffer headers. Please update -#error your headers. -#endif -#if 2004001 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION -#error This file was generated by an older version of protoc which is -#error incompatible with your Protocol Buffer headers. Please -#error regenerate this file with a newer version of protoc. -#endif - -#include <google/protobuf/generated_message_util.h> -#include <google/protobuf/repeated_field.h> -#include <google/protobuf/extension_set.h> -#include <google/protobuf/generated_message_reflection.h> -// @@protoc_insertion_point(includes) - -namespace common { - -// Internal implementation detail -- do not call these. -void protobuf_AddDesc_gutil_2fproto_2ftypes_2eproto(); -void protobuf_AssignDesc_gutil_2fproto_2ftypes_2eproto(); -void protobuf_ShutdownFile_gutil_2fproto_2ftypes_2eproto(); - - -enum DataType { - INT32 = 1, - INT64 = 2, - UINT32 = 8, - UINT64 = 3, - FLOAT = 9, - DOUBLE = 5, - BOOL = 6, - DATE = 10, - DATETIME = 4, - STRING = 0, - BINARY = 7, - DATA_TYPE = 11, - NULL_TYPE = 12 -}; -bool DataType_IsValid(int value); -const DataType DataType_MIN = STRING; -const DataType DataType_MAX = NULL_TYPE; -const int DataType_ARRAYSIZE = DataType_MAX + 1; - -const ::google::protobuf::EnumDescriptor* DataType_descriptor(); -inline const ::std::string& DataType_Name(DataType value) { - return ::google::protobuf::internal::NameOfEnum( - DataType_descriptor(), value); -} -inline bool DataType_Parse( - const ::std::string& name, DataType* value) { - return ::google::protobuf::internal::ParseNamedEnum<DataType>( - DataType_descriptor(), name, value); -} -// =================================================================== - - -// =================================================================== - - -// =================================================================== - - -// @@protoc_insertion_point(namespace_scope) - -} // namespace common - -#ifndef SWIG -namespace google { -namespace protobuf { - -template <> -inline const EnumDescriptor* GetEnumDescriptor< common::DataType>() { - return common::DataType_descriptor(); -} - -} // namespace google -} // namespace protobuf -#endif // SWIG - -// @@protoc_insertion_point(global_scope) - -#endif // PROTOBUF_gutil_2fproto_2ftypes_2eproto__INCLUDED http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/02f3e3fc/be/src/gutil/proto/types.proto ---------------------------------------------------------------------- diff --git a/be/src/gutil/proto/types.proto b/be/src/gutil/proto/types.proto deleted file mode 100644 index aae0557..0000000 --- a/be/src/gutil/proto/types.proto +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2010 Google Inc. All Rights Reserved. - -option java_package = "com.google.datawarehouse.common.proto"; -option java_outer_classname = "CommonEnums"; - -package common; - -// Supported types. -enum DataType { - INT32 = 1; - INT64 = 2; - UINT32 = 8; - UINT64 = 3; - FLOAT = 9; - DOUBLE = 5; - BOOL = 6; - DATE = 10; // Fixed-precision, daily granularity. - DATETIME = 4; // Fixed-precision, microsecond granularity. - - STRING = 0; - BINARY = 7; - - DATA_TYPE = 11; // For representing the DataType enum itself. - NULL_TYPE = 12; // Untyped NULL literal. - - // Note: next available: 13 -} - http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/02f3e3fc/be/src/gutil/raw_scoped_refptr_mismatch_checker.h ---------------------------------------------------------------------- diff --git a/be/src/gutil/raw_scoped_refptr_mismatch_checker.h b/be/src/gutil/raw_scoped_refptr_mismatch_checker.h new file mode 100644 index 0000000..63e4e71 --- /dev/null +++ b/be/src/gutil/raw_scoped_refptr_mismatch_checker.h @@ -0,0 +1,63 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef KUDU_GUTIL_RAW_SCOPED_REFPTR_MISMATCH_CHECKER_H_ +#define KUDU_GUTIL_RAW_SCOPED_REFPTR_MISMATCH_CHECKER_H_ + +#include <type_traits> + +#include "kudu/gutil/ref_counted.h" + +// It is dangerous to post a task with a T* argument where T is a subtype of +// RefCounted(Base|ThreadSafeBase), since by the time the parameter is used, the +// object may already have been deleted since it was not held with a +// scoped_refptr. Example: http://crbug.com/27191 +// The following set of traits are designed to generate a compile error +// whenever this antipattern is attempted. + +namespace kudu { + +// This is a base internal implementation file used by task.h and callback.h. +// Not for public consumption, so we wrap it in namespace internal. +namespace internal { + +template <typename T> +struct NeedsScopedRefptrButGetsRawPtr { +#if defined(OS_WIN) + enum { + value = base::false_type::value + }; +#else + enum { + // Human readable translation: you needed to be a scoped_refptr if you are a + // raw pointer type and are convertible to a RefCounted(Base|ThreadSafeBase) + // type. + value = (std::is_pointer<T>::value && + (std::is_convertible<T, subtle::RefCountedBase*>::value || + std::is_convertible<T, subtle::RefCountedThreadSafeBase*>::value)) + }; +#endif +}; + +template <typename Params> +struct ParamsUseScopedRefptrCorrectly { + enum { value = 0 }; +}; + +template <> +struct ParamsUseScopedRefptrCorrectly<std::tuple<>> { + enum { value = 1 }; +}; + +template <typename Head, typename... Tail> +struct ParamsUseScopedRefptrCorrectly<std::tuple<Head, Tail...>> { + enum { value = !NeedsScopedRefptrButGetsRawPtr<Head>::value && + ParamsUseScopedRefptrCorrectly<std::tuple<Tail...>>::value }; +}; + +} // namespace internal + +} // namespace kudu + +#endif // KUDU_GUTIL_RAW_SCOPED_REFPTR_MISMATCH_CHECKER_H_ http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/02f3e3fc/be/src/gutil/ref_counted.cc ---------------------------------------------------------------------- diff --git a/be/src/gutil/ref_counted.cc b/be/src/gutil/ref_counted.cc new file mode 100644 index 0000000..a15a1e2 --- /dev/null +++ b/be/src/gutil/ref_counted.cc @@ -0,0 +1,95 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "kudu/gutil/ref_counted.h" + +#include <glog/logging.h> +#include "kudu/gutil/threading/thread_collision_warner.h" + +namespace kudu { + +namespace subtle { + +RefCountedBase::RefCountedBase() + : ref_count_(0) +#ifndef NDEBUG + , in_dtor_(false) +#endif + { +} + +RefCountedBase::~RefCountedBase() { +#ifndef NDEBUG + DCHECK(in_dtor_) << "RefCounted object deleted without calling Release()"; +#endif +} + +void RefCountedBase::AddRef() const { + // TODO(maruel): Add back once it doesn't assert 500 times/sec. + // Current thread books the critical section "AddRelease" without release it. + // DFAKE_SCOPED_LOCK_THREAD_LOCKED(add_release_); +#ifndef NDEBUG + DCHECK(!in_dtor_); +#endif + ++ref_count_; +} + +bool RefCountedBase::Release() const { + // TODO(maruel): Add back once it doesn't assert 500 times/sec. + // Current thread books the critical section "AddRelease" without release it. + // DFAKE_SCOPED_LOCK_THREAD_LOCKED(add_release_); +#ifndef NDEBUG + DCHECK(!in_dtor_); +#endif + if (--ref_count_ == 0) { +#ifndef NDEBUG + in_dtor_ = true; +#endif + return true; + } + return false; +} + +bool RefCountedThreadSafeBase::HasOneRef() const { + return base::RefCountIsOne( + &const_cast<RefCountedThreadSafeBase*>(this)->ref_count_); +} + +RefCountedThreadSafeBase::RefCountedThreadSafeBase() : ref_count_(0) { +#ifndef NDEBUG + in_dtor_ = false; +#endif +} + +RefCountedThreadSafeBase::~RefCountedThreadSafeBase() { +#ifndef NDEBUG + DCHECK(in_dtor_) << "RefCountedThreadSafe object deleted without " + "calling Release()"; +#endif +} + +void RefCountedThreadSafeBase::AddRef() const { +#ifndef NDEBUG + DCHECK(!in_dtor_); +#endif + base::RefCountInc(&ref_count_); +} + +bool RefCountedThreadSafeBase::Release() const { +#ifndef NDEBUG + DCHECK(!in_dtor_); + DCHECK(!base::RefCountIsZero(&ref_count_)); +#endif + if (!base::RefCountDec(&ref_count_)) { +#ifndef NDEBUG + in_dtor_ = true; +#endif + return true; + } + return false; +} + +} // namespace subtle + +} // namespace kudu http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/02f3e3fc/be/src/gutil/ref_counted.h ---------------------------------------------------------------------- diff --git a/be/src/gutil/ref_counted.h b/be/src/gutil/ref_counted.h new file mode 100644 index 0000000..8b6a553 --- /dev/null +++ b/be/src/gutil/ref_counted.h @@ -0,0 +1,354 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_MEMORY_REF_COUNTED_H_ +#define BASE_MEMORY_REF_COUNTED_H_ + +#include <cassert> + +#include "kudu/gutil/atomic_refcount.h" +#include "kudu/gutil/port.h" +#include "kudu/gutil/threading/thread_collision_warner.h" + +namespace kudu { +namespace subtle { + +typedef Atomic32 AtomicRefCount; + +class RefCountedBase { + public: + bool HasOneRef() const { return ref_count_ == 1; } + + protected: + RefCountedBase(); + ~RefCountedBase(); + + void AddRef() const; + + // Returns true if the object should self-delete. + bool Release() const; + + private: + mutable int ref_count_; +#ifndef NDEBUG + mutable bool in_dtor_; +#endif + + DFAKE_MUTEX(add_release_); + + DISALLOW_COPY_AND_ASSIGN(RefCountedBase); +}; + +class RefCountedThreadSafeBase { + public: + bool HasOneRef() const; + + protected: + RefCountedThreadSafeBase(); + ~RefCountedThreadSafeBase(); + + void AddRef() const; + + // Returns true if the object should self-delete. + bool Release() const; + + private: + mutable AtomicRefCount ref_count_; +#ifndef NDEBUG + mutable bool in_dtor_; +#endif + + DISALLOW_COPY_AND_ASSIGN(RefCountedThreadSafeBase); +}; + +} // namespace subtle + +// +// A base class for reference counted classes. Otherwise, known as a cheap +// knock-off of WebKit's RefCounted<T> class. To use this guy just extend your +// class from it like so: +// +// class MyFoo : public RefCounted<MyFoo> { +// ... +// private: +// friend class RefCounted<MyFoo>; +// ~MyFoo(); +// }; +// +// You should always make your destructor private, to avoid any code deleting +// the object accidently while there are references to it. +template <class T> +class RefCounted : public subtle::RefCountedBase { + public: + RefCounted() {} + + void AddRef() const { + subtle::RefCountedBase::AddRef(); + } + + void Release() const { + if (subtle::RefCountedBase::Release()) { + delete static_cast<const T*>(this); + } + } + + protected: + ~RefCounted() {} + + private: + DISALLOW_COPY_AND_ASSIGN(RefCounted<T>); +}; + +// Forward declaration. +template <class T, typename Traits> class RefCountedThreadSafe; + +// Default traits for RefCountedThreadSafe<T>. Deletes the object when its ref +// count reaches 0. Overload to delete it on a different thread etc. +template<typename T> +struct DefaultRefCountedThreadSafeTraits { + static void Destruct(const T* x) { + // Delete through RefCountedThreadSafe to make child classes only need to be + // friend with RefCountedThreadSafe instead of this struct, which is an + // implementation detail. + RefCountedThreadSafe<T, + DefaultRefCountedThreadSafeTraits>::DeleteInternal(x); + } +}; + +// +// A thread-safe variant of RefCounted<T> +// +// class MyFoo : public RefCountedThreadSafe<MyFoo> { +// ... +// }; +// +// If you're using the default trait, then you should add compile time +// asserts that no one else is deleting your object. i.e. +// private: +// friend class RefCountedThreadSafe<MyFoo>; +// ~MyFoo(); +template <class T, typename Traits = DefaultRefCountedThreadSafeTraits<T> > +class RefCountedThreadSafe : public subtle::RefCountedThreadSafeBase { + public: + RefCountedThreadSafe() {} + + void AddRef() const { + subtle::RefCountedThreadSafeBase::AddRef(); + } + + void Release() const { + if (subtle::RefCountedThreadSafeBase::Release()) { + Traits::Destruct(static_cast<const T*>(this)); + } + } + + protected: + ~RefCountedThreadSafe() {} + + private: + friend struct DefaultRefCountedThreadSafeTraits<T>; + static void DeleteInternal(const T* x) { delete x; } + + DISALLOW_COPY_AND_ASSIGN(RefCountedThreadSafe); +}; + +// +// A thread-safe wrapper for some piece of data so we can place other +// things in scoped_refptrs<>. +// +template<typename T> +class RefCountedData + : public kudu::RefCountedThreadSafe< kudu::RefCountedData<T> > { + public: + RefCountedData() : data() {} + RefCountedData(const T& in_value) : data(in_value) {} + + T data; + + private: + friend class kudu::RefCountedThreadSafe<kudu::RefCountedData<T> >; + ~RefCountedData() {} +}; + +} // namespace kudu + +// +// A smart pointer class for reference counted objects. Use this class instead +// of calling AddRef and Release manually on a reference counted object to +// avoid common memory leaks caused by forgetting to Release an object +// reference. Sample usage: +// +// class MyFoo : public RefCounted<MyFoo> { +// ... +// }; +// +// void some_function() { +// scoped_refptr<MyFoo> foo = new MyFoo(); +// foo->Method(param); +// // |foo| is released when this function returns +// } +// +// void some_other_function() { +// scoped_refptr<MyFoo> foo = new MyFoo(); +// ... +// foo = NULL; // explicitly releases |foo| +// ... +// if (foo) +// foo->Method(param); +// } +// +// The above examples show how scoped_refptr<T> acts like a pointer to T. +// Given two scoped_refptr<T> classes, it is also possible to exchange +// references between the two objects, like so: +// +// { +// scoped_refptr<MyFoo> a = new MyFoo(); +// scoped_refptr<MyFoo> b; +// +// b.swap(a); +// // now, |b| references the MyFoo object, and |a| references NULL. +// } +// +// To make both |a| and |b| in the above example reference the same MyFoo +// object, simply use the assignment operator: +// +// { +// scoped_refptr<MyFoo> a = new MyFoo(); +// scoped_refptr<MyFoo> b; +// +// b = a; +// // now, |a| and |b| each own a reference to the same MyFoo object. +// } +// +template <class T> +class scoped_refptr { + public: + typedef T element_type; + + scoped_refptr() : ptr_(NULL) { + } + + scoped_refptr(T* p) : ptr_(p) { + if (ptr_) + ptr_->AddRef(); + } + + scoped_refptr(const scoped_refptr<T>& r) : ptr_(r.ptr_) { + if (ptr_) + ptr_->AddRef(); + } + + template <typename U> + scoped_refptr(const scoped_refptr<U>& r) : ptr_(r.get()) { + if (ptr_) + ptr_->AddRef(); + } + + template <typename U> + scoped_refptr(scoped_refptr<U>&& r) : ptr_(r.get()) { + r.ptr_ = nullptr; + } + + ~scoped_refptr() { + if (ptr_) + ptr_->Release(); + } + + T* get() const { return ptr_; } + +// The following is disabled in Cloudera's version of this file since it's +// relatively dangerous. Chromium is planning on doing the same in their +// tree, but hasn't done so yet. See http://code.google.com/p/chromium/issues/detail?id=110610 +#if SCOPED_REFPTR_ALLOW_IMPLICIT_CONVERSION_TO_PTR + // Allow scoped_refptr<C> to be used in boolean expression + // and comparison operations. + operator T*() const { return ptr_; } +#else + typedef T* scoped_refptr::*Testable; + operator Testable() const { return ptr_ ? &scoped_refptr::ptr_ : NULL; } +#endif + + T* operator->() const { + assert(ptr_ != NULL); + return ptr_; + } + + scoped_refptr<T>& operator=(T* p) { + // AddRef first so that self assignment should work + if (p) + p->AddRef(); + T* old_ptr = ptr_; + ptr_ = p; + if (old_ptr) + old_ptr->Release(); + return *this; + } + + scoped_refptr<T>& operator=(const scoped_refptr<T>& r) { + return *this = r.ptr_; + } + + template <typename U> + scoped_refptr<T>& operator=(const scoped_refptr<U>& r) { + return *this = r.get(); + } + + scoped_refptr<T>& operator=(scoped_refptr<T>&& r) { + scoped_refptr<T>(r).swap(*this); + return *this; + } + + template <typename U> + scoped_refptr<T>& operator=(scoped_refptr<U>&& r) { + scoped_refptr<T>(r).swap(*this); + return *this; + } + + void swap(T** pp) { + T* p = ptr_; + ptr_ = *pp; + *pp = p; + } + + void swap(scoped_refptr<T>& r) { + swap(&r.ptr_); + } + + // Like gscoped_ptr::reset(), drops a reference on the currently held object + // (if any), and adds a reference to the passed-in object (if not NULL). + void reset(T* p = NULL) { + *this = p; + } + + protected: + T* ptr_; + + private: + template <typename U> friend class scoped_refptr; +}; + +// Handy utility for creating a scoped_refptr<T> out of a T* explicitly without +// having to retype all the template arguments +template <typename T> +scoped_refptr<T> make_scoped_refptr(T* t) { + return scoped_refptr<T>(t); +} + +// equal_to and hash implementations for templated scoped_refptrs suitable for +// use with STL unordered_* containers. +template <class T> +struct ScopedRefPtrEqualToFunctor { + bool operator()(const scoped_refptr<T>& x, const scoped_refptr<T>& y) const { + return x.get() == y.get(); + } +}; + +template <class T> +struct ScopedRefPtrHashFunctor { + size_t operator()(const scoped_refptr<T>& p) const { + return reinterpret_cast<size_t>(p.get()); + } +}; + +#endif // BASE_MEMORY_REF_COUNTED_H_ http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/02f3e3fc/be/src/gutil/ref_counted_memory.cc ---------------------------------------------------------------------- diff --git a/be/src/gutil/ref_counted_memory.cc b/be/src/gutil/ref_counted_memory.cc new file mode 100644 index 0000000..1d695d9 --- /dev/null +++ b/be/src/gutil/ref_counted_memory.cc @@ -0,0 +1,99 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "kudu/gutil/ref_counted_memory.h" + +#include <stdlib.h> + +#include <glog/logging.h> + +namespace kudu { + +bool RefCountedMemory::Equals( + const scoped_refptr<RefCountedMemory>& other) const { + return other.get() && + size() == other->size() && + (memcmp(front(), other->front(), size()) == 0); +} + +RefCountedMemory::RefCountedMemory() {} + +RefCountedMemory::~RefCountedMemory() {} + +const unsigned char* RefCountedStaticMemory::front() const { + return data_; +} + +size_t RefCountedStaticMemory::size() const { + return length_; +} + +RefCountedStaticMemory::~RefCountedStaticMemory() {} + +RefCountedBytes::RefCountedBytes() {} + +RefCountedBytes::RefCountedBytes(std::vector<unsigned char> initializer) + : data_(std::move(initializer)) {} + +RefCountedBytes::RefCountedBytes(const unsigned char* p, size_t size) + : data_(p, p + size) {} + +RefCountedBytes* RefCountedBytes::TakeVector( + std::vector<unsigned char>* to_destroy) { + auto bytes = new RefCountedBytes; + bytes->data_.swap(*to_destroy); + return bytes; +} + +const unsigned char* RefCountedBytes::front() const { + // STL will assert if we do front() on an empty vector, but calling code + // expects a NULL. + return size() ? &data_.front() : nullptr; +} + +size_t RefCountedBytes::size() const { + return data_.size(); +} + +RefCountedBytes::~RefCountedBytes() {} + +RefCountedString::RefCountedString() {} + +RefCountedString::~RefCountedString() {} + +// static +RefCountedString* RefCountedString::TakeString(std::string* to_destroy) { + auto self = new RefCountedString; + to_destroy->swap(self->data_); + return self; +} + +const unsigned char* RefCountedString::front() const { + return data_.empty() ? nullptr : + reinterpret_cast<const unsigned char*>(data_.data()); +} + +size_t RefCountedString::size() const { + return data_.size(); +} + +RefCountedMallocedMemory::RefCountedMallocedMemory( + void* data, size_t length) + : data_(reinterpret_cast<unsigned char*>(data)), length_(length) { + DCHECK(data || length == 0); +} + +const unsigned char* RefCountedMallocedMemory::front() const { + return length_ ? data_ : nullptr; +} + +size_t RefCountedMallocedMemory::size() const { + return length_; +} + +RefCountedMallocedMemory::~RefCountedMallocedMemory() { + free(data_); +} + +} // namespace kudu http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/02f3e3fc/be/src/gutil/ref_counted_memory.h ---------------------------------------------------------------------- diff --git a/be/src/gutil/ref_counted_memory.h b/be/src/gutil/ref_counted_memory.h new file mode 100644 index 0000000..550a142 --- /dev/null +++ b/be/src/gutil/ref_counted_memory.h @@ -0,0 +1,150 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef KUDU_GUTIL_REF_COUNTED_MEMORY_H_ +#define KUDU_GUTIL_REF_COUNTED_MEMORY_H_ + +#include <string> +#include <vector> + +#include "kudu/gutil/macros.h" +#include "kudu/gutil/ref_counted.h" +#include "kudu/gutil/port.h" + +#ifndef BASE_EXPORT +#define BASE_EXPORT +#endif + +namespace kudu { + +// A generic interface to memory. This object is reference counted because one +// of its two subclasses own the data they carry, and we need to have +// heterogeneous containers of these two types of memory. +class BASE_EXPORT RefCountedMemory + : public RefCountedThreadSafe<RefCountedMemory> { + public: + // Retrieves a pointer to the beginning of the data we point to. If the data + // is empty, this will return NULL. + virtual const unsigned char* front() const = 0; + + // Size of the memory pointed to. + virtual size_t size() const = 0; + + // Returns true if |other| is byte for byte equal. + bool Equals(const scoped_refptr<RefCountedMemory>& other) const; + + // Handy method to simplify calling front() with a reinterpret_cast. + template<typename T> const T* front_as() const { + return reinterpret_cast<const T*>(front()); + } + + protected: + friend class RefCountedThreadSafe<RefCountedMemory>; + RefCountedMemory(); + virtual ~RefCountedMemory(); +}; + +// An implementation of RefCountedMemory, where the ref counting does not +// matter. +class BASE_EXPORT RefCountedStaticMemory : public RefCountedMemory { + public: + RefCountedStaticMemory() + : data_(NULL), length_(0) {} + RefCountedStaticMemory(const void* data, size_t length) + : data_(static_cast<const unsigned char*>(length ? data : NULL)), + length_(length) {} + + // Overridden from RefCountedMemory: + virtual const unsigned char* front() const OVERRIDE; + virtual size_t size() const OVERRIDE; + + private: + virtual ~RefCountedStaticMemory(); + + const unsigned char* data_; + size_t length_; + + DISALLOW_COPY_AND_ASSIGN(RefCountedStaticMemory); +}; + +// An implementation of RefCountedMemory, where we own the data in a vector. +class BASE_EXPORT RefCountedBytes : public RefCountedMemory { + public: + RefCountedBytes(); + + // Constructs a RefCountedBytes object by _copying_ from |initializer|. + explicit RefCountedBytes(std::vector<unsigned char> initializer); + + // Constructs a RefCountedBytes object by copying |size| bytes from |p|. + RefCountedBytes(const unsigned char* p, size_t size); + + // Constructs a RefCountedBytes object by performing a swap. (To non + // destructively build a RefCountedBytes, use the constructor that takes a + // vector.) + static RefCountedBytes* TakeVector(std::vector<unsigned char>* to_destroy); + + // Overridden from RefCountedMemory: + virtual const unsigned char* front() const OVERRIDE; + virtual size_t size() const OVERRIDE; + + const std::vector<unsigned char>& data() const { return data_; } + std::vector<unsigned char>& data() { return data_; } + + private: + virtual ~RefCountedBytes(); + + std::vector<unsigned char> data_; + + DISALLOW_COPY_AND_ASSIGN(RefCountedBytes); +}; + +// An implementation of RefCountedMemory, where the bytes are stored in an STL +// string. Use this if your data naturally arrives in that format. +class BASE_EXPORT RefCountedString : public RefCountedMemory { + public: + RefCountedString(); + + // Constructs a RefCountedString object by performing a swap. (To non + // destructively build a RefCountedString, use the default constructor and + // copy into object->data()). + static RefCountedString* TakeString(std::string* to_destroy); + + // Overridden from RefCountedMemory: + virtual const unsigned char* front() const OVERRIDE; + virtual size_t size() const OVERRIDE; + + const std::string& data() const { return data_; } + std::string& data() { return data_; } + + private: + virtual ~RefCountedString(); + + std::string data_; + + DISALLOW_COPY_AND_ASSIGN(RefCountedString); +}; + +// An implementation of RefCountedMemory that holds a chunk of memory +// previously allocated with malloc or calloc, and that therefore must be freed +// using free(). +class BASE_EXPORT RefCountedMallocedMemory : public RefCountedMemory { + public: + RefCountedMallocedMemory(void* data, size_t length); + + // Overridden from RefCountedMemory: + virtual const unsigned char* front() const OVERRIDE; + virtual size_t size() const OVERRIDE; + + private: + virtual ~RefCountedMallocedMemory(); + + unsigned char* data_; + size_t length_; + + DISALLOW_COPY_AND_ASSIGN(RefCountedMallocedMemory); +}; + +} // namespace kudu + +#endif // KUDU_GUTIL_REF_COUNTED_MEMORY_H_ http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/02f3e3fc/be/src/gutil/singleton.h ---------------------------------------------------------------------- diff --git a/be/src/gutil/singleton.h b/be/src/gutil/singleton.h index d1e1667..61e5ea5 100644 --- a/be/src/gutil/singleton.h +++ b/be/src/gutil/singleton.h @@ -60,8 +60,9 @@ #include <stddef.h> #include <glog/logging.h> -#include "gutil/logging-inl.h" -#include "gutil/once.h" + +#include "kudu/gutil/logging-inl.h" +#include "kudu/gutil/once.h" namespace util { namespace gtl {
