mirror of https://github.com/xzeldon/htop.git
ProcessList: introduce displayList
Separate `processes` (the vector owning the processes, sorted in whatever order is needed right now internally) and `displayList` (a vector referencing the processes in the same order they're to be displayed).
This commit is contained in:
parent
2477a5a018
commit
58b42e4cac
|
@ -22,7 +22,7 @@ in the source distribution for its full text.
|
||||||
|
|
||||||
ProcessList* ProcessList_init(ProcessList* this, const ObjectClass* klass, UsersTable* usersTable, Hashtable* dynamicMeters, Hashtable* dynamicColumns, Hashtable* pidMatchList, uid_t userId) {
|
ProcessList* ProcessList_init(ProcessList* this, const ObjectClass* klass, UsersTable* usersTable, Hashtable* dynamicMeters, Hashtable* dynamicColumns, Hashtable* pidMatchList, uid_t userId) {
|
||||||
this->processes = Vector_new(klass, true, DEFAULT_SIZE);
|
this->processes = Vector_new(klass, true, DEFAULT_SIZE);
|
||||||
this->processes2 = Vector_new(klass, true, DEFAULT_SIZE); // tree-view auxiliary buffer
|
this->displayList = Vector_new(klass, false, DEFAULT_SIZE);
|
||||||
|
|
||||||
this->processTable = Hashtable_new(200, false);
|
this->processTable = Hashtable_new(200, false);
|
||||||
this->displayTreeSet = Hashtable_new(200, false);
|
this->displayTreeSet = Hashtable_new(200, false);
|
||||||
|
@ -78,7 +78,7 @@ void ProcessList_done(ProcessList* this) {
|
||||||
Hashtable_delete(this->displayTreeSet);
|
Hashtable_delete(this->displayTreeSet);
|
||||||
Hashtable_delete(this->processTable);
|
Hashtable_delete(this->processTable);
|
||||||
|
|
||||||
Vector_delete(this->processes2);
|
Vector_delete(this->displayList);
|
||||||
Vector_delete(this->processes);
|
Vector_delete(this->processes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,7 +224,7 @@ static void ProcessList_updateTreeSetLayer(ProcessList* this, unsigned int leftB
|
||||||
if (layerSize == 0)
|
if (layerSize == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Vector* layer = Vector_new(Vector_type(this->processes), false, layerSize);
|
Vector* layer = Vector_new(Vector_type(this->displayList), false, layerSize);
|
||||||
|
|
||||||
// Find all processes on the same layer (process with the same `deep` value
|
// Find all processes on the same layer (process with the same `deep` value
|
||||||
// and included in a range from `leftBound` to `rightBound`).
|
// and included in a range from `leftBound` to `rightBound`).
|
||||||
|
@ -317,7 +317,7 @@ static void ProcessList_updateTreeSet(ProcessList* this) {
|
||||||
unsigned int index = 0;
|
unsigned int index = 0;
|
||||||
unsigned int tree_index = 1;
|
unsigned int tree_index = 1;
|
||||||
|
|
||||||
const int vsize = Vector_size(this->processes);
|
const int vsize = Vector_size(this->displayList);
|
||||||
|
|
||||||
assert(Hashtable_count(this->draftingTreeSet) == 0);
|
assert(Hashtable_count(this->draftingTreeSet) == 0);
|
||||||
assert((int)Hashtable_count(this->displayTreeSet) == vsize);
|
assert((int)Hashtable_count(this->displayTreeSet) == vsize);
|
||||||
|
@ -344,7 +344,6 @@ static void ProcessList_buildTreeBranch(ProcessList* this, pid_t pid, int level,
|
||||||
for (int i = Vector_size(this->processes) - 1; i >= 0; i--) {
|
for (int i = Vector_size(this->processes) - 1; i >= 0; i--) {
|
||||||
Process* process = (Process*)Vector_get(this->processes, i);
|
Process* process = (Process*)Vector_get(this->processes, i);
|
||||||
if (Process_isChildOf(process, pid)) {
|
if (Process_isChildOf(process, pid)) {
|
||||||
process = (Process*)Vector_take(this->processes, i);
|
|
||||||
if (process->show)
|
if (process->show)
|
||||||
lastShown = Vector_size(children);
|
lastShown = Vector_size(children);
|
||||||
Vector_add(children, process);
|
Vector_add(children, process);
|
||||||
|
@ -362,14 +361,14 @@ static void ProcessList_buildTreeBranch(ProcessList* this, pid_t pid, int level,
|
||||||
process->show = false;
|
process->show = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int s = Vector_size(this->processes2);
|
int s = Vector_size(this->displayList);
|
||||||
if (direction == 1) {
|
if (direction == 1) {
|
||||||
Vector_add(this->processes2, process);
|
Vector_add(this->displayList, process);
|
||||||
} else {
|
} else {
|
||||||
Vector_insert(this->processes2, 0, process);
|
Vector_insert(this->displayList, 0, process);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(Vector_size(this->processes2) == s + 1); (void)s;
|
assert(Vector_size(this->displayList) == s + 1); (void)s;
|
||||||
|
|
||||||
int nextIndent = indent | (1 << level);
|
int nextIndent = indent | (1 << level);
|
||||||
ProcessList_buildTreeBranch(this, process->pid, level + 1, (i < lastShown) ? nextIndent : indent, direction, process->show && process->showChildren, node_counter, node_index);
|
ProcessList_buildTreeBranch(this, process->pid, level + 1, (i < lastShown) ? nextIndent : indent, direction, process->show && process->showChildren, node_counter, node_index);
|
||||||
|
@ -406,6 +405,8 @@ static int ProcessList_treeProcessCompareByPID(const void* v1, const void* v2) {
|
||||||
|
|
||||||
// Builds a sorted tree from scratch, without relying on previously gathered information
|
// Builds a sorted tree from scratch, without relying on previously gathered information
|
||||||
static void ProcessList_buildTree(ProcessList* this) {
|
static void ProcessList_buildTree(ProcessList* this) {
|
||||||
|
Vector_prune(this->displayList);
|
||||||
|
|
||||||
int node_counter = 1;
|
int node_counter = 1;
|
||||||
int node_index = 0;
|
int node_index = 0;
|
||||||
int direction = ScreenSettings_getActiveDirection(this->settings->ss);
|
int direction = ScreenSettings_getActiveDirection(this->settings->ss);
|
||||||
|
@ -415,10 +416,8 @@ static void ProcessList_buildTree(ProcessList* this) {
|
||||||
int vsize = Vector_size(this->processes);
|
int vsize = Vector_size(this->processes);
|
||||||
|
|
||||||
// Find all processes whose parent is not visible
|
// Find all processes whose parent is not visible
|
||||||
int size;
|
int size = Vector_size(this->processes);
|
||||||
while ((size = Vector_size(this->processes))) {
|
for (int i = 0; i < size; i++) {
|
||||||
int i;
|
|
||||||
for (i = 0; i < size; i++) {
|
|
||||||
Process* process = (Process*)Vector_get(this->processes, i);
|
Process* process = (Process*)Vector_get(this->processes, i);
|
||||||
|
|
||||||
pid_t ppid = Process_getParentPid(process);
|
pid_t ppid = Process_getParentPid(process);
|
||||||
|
@ -440,39 +439,34 @@ static void ProcessList_buildTree(ProcessList* this) {
|
||||||
|
|
||||||
// If parent not found, then construct the tree with this node as root
|
// If parent not found, then construct the tree with this node as root
|
||||||
if (isRoot) {
|
if (isRoot) {
|
||||||
process = (Process*)Vector_take(this->processes, i);
|
process = (Process*)Vector_get(this->processes, i);
|
||||||
process->indent = 0;
|
process->indent = 0;
|
||||||
process->tree_depth = 0;
|
process->tree_depth = 0;
|
||||||
process->tree_left = node_counter++;
|
process->tree_left = node_counter++;
|
||||||
process->tree_index = node_index++;
|
process->tree_index = node_index++;
|
||||||
Vector_add(this->processes2, process);
|
Vector_add(this->displayList, process);
|
||||||
Hashtable_put(this->displayTreeSet, process->tree_index, process);
|
Hashtable_put(this->displayTreeSet, process->tree_index, process);
|
||||||
ProcessList_buildTreeBranch(this, process->pid, 0, 0, direction, process->showChildren, &node_counter, &node_index);
|
ProcessList_buildTreeBranch(this, process->pid, 0, 0, direction, process->showChildren, &node_counter, &node_index);
|
||||||
process->tree_right = node_counter++;
|
process->tree_right = node_counter++;
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// There should be no loop in the process tree
|
|
||||||
assert(i < size);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Swap listings around
|
|
||||||
Vector* t = this->processes;
|
|
||||||
this->processes = this->processes2;
|
|
||||||
this->processes2 = t;
|
|
||||||
|
|
||||||
// Check consistency of the built structures
|
// Check consistency of the built structures
|
||||||
assert(Vector_size(this->processes) == vsize); (void)vsize;
|
assert(Vector_size(this->displayList) == vsize); (void)vsize;
|
||||||
assert(Vector_size(this->processes2) == 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProcessList_sort(ProcessList* this) {
|
void ProcessList_updateDisplayList(ProcessList* this) {
|
||||||
if (this->settings->ss->treeView) {
|
if (this->settings->ss->treeView) {
|
||||||
ProcessList_updateTreeSet(this);
|
ProcessList_updateTreeSet(this);
|
||||||
Vector_quickSortCustomCompare(this->processes, ProcessList_treeProcessCompare);
|
Vector_quickSortCustomCompare(this->displayList, ProcessList_treeProcessCompare);
|
||||||
} else {
|
} else {
|
||||||
|
if (this->needsSort)
|
||||||
Vector_insertionSort(this->processes);
|
Vector_insertionSort(this->processes);
|
||||||
|
Vector_prune(this->displayList);
|
||||||
|
int size = Vector_size(this->processes);
|
||||||
|
for (int i = 0; i < size; i++)
|
||||||
|
Vector_add(this->displayList, Vector_get(this->processes, i));
|
||||||
}
|
}
|
||||||
this->needsSort = false;
|
this->needsSort = false;
|
||||||
}
|
}
|
||||||
|
@ -510,8 +504,7 @@ void ProcessList_collapseAllBranches(ProcessList* this) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProcessList_rebuildPanel(ProcessList* this) {
|
void ProcessList_rebuildPanel(ProcessList* this) {
|
||||||
if (this->needsSort)
|
ProcessList_updateDisplayList(this);
|
||||||
ProcessList_sort(this);
|
|
||||||
|
|
||||||
const char* incFilter = this->incFilter;
|
const char* incFilter = this->incFilter;
|
||||||
|
|
||||||
|
@ -530,12 +523,12 @@ void ProcessList_rebuildPanel(ProcessList* this) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const int processCount = Vector_size(this->processes);
|
const int processCount = Vector_size(this->displayList);
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
bool foundFollowed = false;
|
bool foundFollowed = false;
|
||||||
|
|
||||||
for (int i = 0; i < processCount; i++) {
|
for (int i = 0; i < processCount; i++) {
|
||||||
Process* p = (Process*) Vector_get(this->processes, i);
|
Process* p = (Process*) Vector_get(this->displayList, i);
|
||||||
|
|
||||||
if ( (!p->show)
|
if ( (!p->show)
|
||||||
|| (this->userId != (uid_t) -1 && (p->st_uid != this->userId))
|
|| (this->userId != (uid_t) -1 && (p->st_uid != this->userId))
|
||||||
|
|
|
@ -43,9 +43,9 @@ typedef unsigned long long int memory_t;
|
||||||
typedef struct ProcessList_ {
|
typedef struct ProcessList_ {
|
||||||
const Settings* settings;
|
const Settings* settings;
|
||||||
|
|
||||||
Vector* processes;
|
Vector* processes; /* all known processes; sort order can vary and differ from display order */
|
||||||
Vector* processes2;
|
Vector* displayList; /* process tree flattened in display order (borrowed) */
|
||||||
Hashtable* processTable;
|
Hashtable* processTable; /* fast known process lookup by PID */
|
||||||
UsersTable* usersTable;
|
UsersTable* usersTable;
|
||||||
|
|
||||||
Hashtable* displayTreeSet;
|
Hashtable* displayTreeSet;
|
||||||
|
@ -109,7 +109,7 @@ void ProcessList_add(ProcessList* this, Process* p);
|
||||||
|
|
||||||
void ProcessList_remove(ProcessList* this, const Process* p);
|
void ProcessList_remove(ProcessList* this, const Process* p);
|
||||||
|
|
||||||
void ProcessList_sort(ProcessList* this);
|
void ProcessList_updateDisplayList(ProcessList* this);
|
||||||
|
|
||||||
ProcessField ProcessList_keyAt(const ProcessList* this, int at);
|
ProcessField ProcessList_keyAt(const ProcessList* this, int at);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue