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:
Denis Lisov 2021-12-16 19:09:03 +03:00 committed by BenBE
parent 2477a5a018
commit 58b42e4cac
2 changed files with 54 additions and 61 deletions

View File

@ -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,64 +416,57 @@ 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; Process* process = (Process*)Vector_get(this->processes, i);
for (i = 0; i < size; i++) {
Process* process = (Process*)Vector_get(this->processes, i);
pid_t ppid = Process_getParentPid(process); pid_t ppid = Process_getParentPid(process);
bool isRoot = false; bool isRoot = false;
// If PID corresponds with PPID (e.g. "kernel_task" (PID:0, PPID:0) // If PID corresponds with PPID (e.g. "kernel_task" (PID:0, PPID:0)
// on Mac OS X 10.11.6) regard this process as root. // on Mac OS X 10.11.6) regard this process as root.
if (process->pid == ppid) if (process->pid == ppid)
isRoot = true; isRoot = true;
// On Linux both the init process (pid 1) and the root UMH kernel thread (pid 2) // On Linux both the init process (pid 1) and the root UMH kernel thread (pid 2)
// use a ppid of 0. As that PID can't exist, we can skip searching for it. // use a ppid of 0. As that PID can't exist, we can skip searching for it.
if (!ppid) if (!ppid)
isRoot = true; isRoot = true;
// Lookup the parent via the processTable hashtable not modified in buildTree // Lookup the parent via the processTable hashtable not modified in buildTree
if (ProcessList_findProcess(this, ppid) == NULL) if (ProcessList_findProcess(this, ppid) == NULL)
isRoot = true; isRoot = true;
// 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 {
Vector_insertionSort(this->processes); if (this->needsSort)
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))

View File

@ -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);