blob: 1f8da58d3e7a863924497931337e9c4d68e45318 [file] [log] [blame]
<!DOCTYPE html>
<!--
Copyright (c) 2013 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.
-->
<link rel="import" href="/tracing/base/guid.html">
<link rel="import" href="/tracing/base/math/range.html">
<link rel="import" href="/tracing/model/counter.html">
<link rel="import" href="/tracing/model/event_container.html">
<link rel="import" href="/tracing/model/object_collection.html">
<link rel="import" href="/tracing/model/thread.html">
<script>
'use strict';
/**
* @fileoverview Provides the ProcessBase class.
*/
tr.exportTo('tr.model', function() {
var Thread = tr.model.Thread;
var Counter = tr.model.Counter;
/**
* The ProcessBase is a partial base class, upon which Kernel
* and Process are built.
*
* @constructor
* @extends {tr.model.EventContainer}
*/
function ProcessBase(model) {
if (!model)
throw new Error('Must provide a model');
tr.model.EventContainer.call(this);
this.model = model;
this.threads = {};
this.counters = {};
this.objects = new tr.model.ObjectCollection(this);
this.sortIndex = 0;
}
ProcessBase.compare = function(x, y) {
return x.sortIndex - y.sortIndex;
};
ProcessBase.prototype = {
__proto__: tr.model.EventContainer.prototype,
get stableId() {
throw new Error('Not implemented');
},
childEventContainers: function* () {
yield* tr.b.dictionaryValues(this.threads);
yield* tr.b.dictionaryValues(this.counters);
yield this.objects;
},
iterateAllPersistableObjects: function(cb) {
cb(this);
for (var tid in this.threads)
this.threads[tid].iterateAllPersistableObjects(cb);
},
/**
* Gets the number of threads in this process.
*/
get numThreads() {
var n = 0;
for (var p in this.threads) {
n++;
}
return n;
},
/**
* Shifts all the timestamps inside this process forward by the amount
* specified.
*/
shiftTimestampsForward: function(amount) {
for (var child of this.childEventContainers())
child.shiftTimestampsForward(amount);
},
/**
* Closes any open slices.
*/
autoCloseOpenSlices: function() {
for (var tid in this.threads) {
var thread = this.threads[tid];
thread.autoCloseOpenSlices();
}
},
autoDeleteObjects: function(maxTimestamp) {
this.objects.autoDeleteObjects(maxTimestamp);
},
/**
* Called by the model after finalizing imports,
* but before joining refs.
*/
preInitializeObjects: function() {
this.objects.preInitializeAllObjects();
},
/**
* Called by the model after joining refs.
*/
initializeObjects: function() {
this.objects.initializeAllObjects();
},
/**
* Merge slices from the kernel with those from userland for each thread.
*/
mergeKernelWithUserland: function() {
for (var tid in this.threads) {
var thread = this.threads[tid];
thread.mergeKernelWithUserland();
}
},
updateBounds: function() {
this.bounds.reset();
for (var tid in this.threads) {
this.threads[tid].updateBounds();
this.bounds.addRange(this.threads[tid].bounds);
}
for (var id in this.counters) {
this.counters[id].updateBounds();
this.bounds.addRange(this.counters[id].bounds);
}
this.objects.updateBounds();
this.bounds.addRange(this.objects.bounds);
},
addCategoriesToDict: function(categoriesDict) {
for (var tid in this.threads)
this.threads[tid].addCategoriesToDict(categoriesDict);
for (var id in this.counters)
categoriesDict[this.counters[id].category] = true;
this.objects.addCategoriesToDict(categoriesDict);
},
findAllThreadsMatching: function(predicate, opt_this) {
var threads = [];
for (var tid in this.threads) {
var thread = this.threads[tid];
if (predicate.call(opt_this, thread))
threads.push(thread);
}
return threads;
},
/**
* @param {String} The name of the thread to find.
* @return {Array} An array of all the matched threads.
*/
findAllThreadsNamed: function(name) {
var threads = this.findAllThreadsMatching(function(thread) {
if (!thread.name)
return false;
return thread.name === name;
});
return threads;
},
findAtMostOneThreadNamed: function(name) {
var threads = this.findAllThreadsNamed(name);
if (threads.length === 0)
return undefined;
if (threads.length > 1)
throw new Error('Expected no more than one ' + name);
return threads[0];
},
/**
* Removes threads from the process that are fully empty.
*/
pruneEmptyContainers: function() {
var threadsToKeep = {};
for (var tid in this.threads) {
var thread = this.threads[tid];
if (!thread.isEmpty)
threadsToKeep[tid] = thread;
}
this.threads = threadsToKeep;
},
/**
* @return {TimelineThread} The thread identified by tid on this process,
* or undefined if it doesn't exist.
*/
getThread: function(tid) {
return this.threads[tid];
},
/**
* @return {TimelineThread} The thread identified by tid on this process,
* creating it if it doesn't exist.
*/
getOrCreateThread: function(tid) {
if (!this.threads[tid])
this.threads[tid] = new Thread(this, tid);
return this.threads[tid];
},
/**
* @return {Counter} The counter on this process with the given
* category/name combination, creating it if it doesn't exist.
*/
getOrCreateCounter: function(cat, name) {
var id = cat + '.' + name;
if (!this.counters[id])
this.counters[id] = new Counter(this, id, cat, name);
return this.counters[id];
},
getSettingsKey: function() {
throw new Error('Not implemented');
},
createSubSlices: function() {
for (var tid in this.threads)
this.threads[tid].createSubSlices();
}
};
return {
ProcessBase,
};
});
</script>