blob: d39d68046efc64dcaacd9a8425250d80298eb17f [file] [log] [blame]
// Copyright 2018 The Fuchsia 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 LIB_ESCHER_UTIL_HASHABLE_H_
#define LIB_ESCHER_UTIL_HASHABLE_H_
#include <stdlib.h>
#include "lib/escher/util/hash.h"
#include "lib/fxl/logging.h"
namespace escher {
// A simple base class for self-hashing objects. Copying and moving is allowed;
// it's up to subclasses to disallow, if they want.
//
// Not thread-safe.
class Hashable {
public:
// Return the cached hash, generating it if necessary.
Hash hash() const {
if (!hash_.IsValid()) {
hash_ = GenerateHash();
FXL_DCHECK(hash_.IsValid()) << "GenerateHash() must return a valid Hash.";
}
return hash_;
}
// Allows any Hashable object to be used as a HashMap key.
struct HashMapHasher {
size_t operator()(const Hashable& key) const { return key.hash().val; }
};
bool operator==(const Hashable& other) const = delete;
bool operator!=(const Hashable& other) const = delete;
protected:
// Subclasses must call whenever the object's state changes such that
// GenerateHash() would return a different result.
void InvalidateHash() const { hash_ = {0}; }
// Returns true if there is a cached hash value, i.e. if there has been no
// call to InvalidateHash() since the last call of GenerateHash(). Mostly for
// testing.
bool HasCachedHash() const { return hash_.IsValid(); }
private:
// Subclasses must implement to generate a hash value based on the hashable
// object's internal data. The generated value must be non-zero.
virtual Hash GenerateHash() const = 0;
// Valid hashes are always non-zero. Zero means invalid.
mutable Hash hash_ = {0};
};
} // namespace escher
#endif // LIB_ESCHER_UTIL_HASHABLE_H_