blob: c73c4d8b7b95c00e9ab33c71b78b65fcb75b781d [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="/base/guid.html">
<link rel="import" href="/base/range.html">
<link rel="import" href="/model/counter.html">
<link rel="import" href="/model/event_container.html">
<link rel="import" href="/model/object_collection.html">
<link rel="import" href="/model/thread.html">
<link rel="import" href="/model/model_settings.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.guid_ = tr.b.GUID.allocate();
this.model = model;
this.threads = {};
this.counters = {};
this.objects = new tr.model.ObjectCollection(this);
this.bounds = new tr.b.Range();
this.sortIndex = 0;
};
ProcessBase.compare = function(x, y) {
return x.sortIndex - y.sortIndex;
};
ProcessBase.prototype = {
__proto__: tr.model.EventContainer.prototype,
get guid() {
return this.guid_;
},
get stableId() {
throw new Error('Not implemented');
},
iterateAllChildEventContainers: function(callback, opt_this) {
for (var tid in this.threads)
callback.call(opt_this, this.threads[tid]);
for (var id in this.counters)
callback.call(opt_this, this.counters[id]);
callback.call(opt_this, this.objects);
},
iterateAllEventsInThisContainer: function(eventTypePredicate,
callback, opt_this) {
},
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 tid in this.threads)
this.threads[tid].shiftTimestampsForward(amount);
for (var id in this.counters)
this.counters[id].shiftTimestampsForward(amount);
this.objects.shiftTimestampsForward(amount);
},
/**
* Closes any open slices.
*/
autoCloseOpenSlices: function(opt_maxTimestamp) {
for (var tid in this.threads) {
var thread = this.threads[tid];
thread.autoCloseOpenSlices(opt_maxTimestamp);
}
},
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 {TimelineCounter} The counter on this process named 'name',
* 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: ProcessBase
};
});
</script>