blob: a411bcab8d960793843b57edea8717212d168a97 [file] [log] [blame]
// Copyright 2015 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 COMPONENTS_METRICS_LEAK_DETECTOR_CALL_STACK_MANAGER_H_
#define COMPONENTS_METRICS_LEAK_DETECTOR_CALL_STACK_MANAGER_H_
#include <stddef.h>
#include <stdint.h>
#include "base/containers/hash_tables.h"
#include "base/macros.h"
#include "components/metrics/leak_detector/custom_allocator.h"
#include "components/metrics/leak_detector/stl_allocator.h"
// Summary of structures:
//
// struct CallStack:
// Represents a unique call stack, defined by its raw call stack (array of
// pointers), and hash value. All CallStack objects are owned by class
// CallStackManager. Other classes may hold pointers to them but should not
// attempt to create or modify any CallStack objects.
//
// class CallStackManager:
// Creates CallStack objects to represent unique call stacks. Owns all
// CallStack objects that it creates, storing them internally.
//
// Returns the call stacks as const pointers because no caller should take
// ownership of them and modify or delete them. The lifetime of all CallStack
// objects is limited to that of the CallStackManager object that created
// them. When the CallStackManager is destroyed, the CallStack objects will be
// invalidated. Hence the caller should make sure that it does not use
// CallStack objects beyond the lifetime of the CallStackManager that created
// them.
namespace metrics {
namespace leak_detector {
// Struct to represent a call stack.
struct CallStack {
// Call stack as an array of pointers, |stack|. The array length is stored in
// |depth|. There is no null terminator.
const void** stack;
size_t depth;
// Hash of call stack. It is cached here so that it doesn not have to be
// recomputed each time.
size_t hash;
};
// Maintains and owns all unique call stack objects.
// Not thread-safe.
class CallStackManager {
public:
CallStackManager();
~CallStackManager();
// Returns a CallStack object for a given raw call stack. The first time a
// particular raw call stack is passed into this function, it will create a
// new CallStack object to hold the raw call stack data, and then return it.
// The CallStack object is stored internally.
//
// On subsequent calls with the same raw call stack, this function will return
// the previously created CallStack object.
const CallStack* GetCallStack(size_t depth, const void* const stack[]);
size_t size() const { return call_stacks_.size(); }
private:
// Allocator class for unique call stacks. Uses CustomAllocator to avoid
// recursive malloc hook invocation when analyzing allocs and frees.
using CallStackPointerAllocator = STLAllocator<CallStack*, CustomAllocator>;
// Hash operator for call stack object given as a pointer.
// Does not actually compute the hash. Instead, returns the already computed
// hash value stored in a CallStack object.
struct CallStackPointerStoredHash {
size_t operator()(const CallStack* call_stack) const {
return call_stack->hash;
}
};
// Equality comparator for call stack objects given as pointers. Compares
// their stack trace contents.
struct CallStackPointerEqual {
bool operator()(const CallStack* c1, const CallStack* c2) const;
};
// Holds all call stack objects. Each object is allocated elsewhere and stored
// as a pointer because the container may rearrange itself internally.
base::hash_set<CallStack*,
CallStackPointerStoredHash,
CallStackPointerEqual,
CallStackPointerAllocator> call_stacks_;
DISALLOW_COPY_AND_ASSIGN(CallStackManager);
};
} // namespace leak_detector
} // namespace metrics
#endif // COMPONENTS_METRICS_LEAK_DETECTOR_CALL_STACK_MANAGER_H_