1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-22 12:22:45 +03:00

Improve ilist.h's support for deletion of slist elements during iteration.

Previously one had to use slist_delete(), implying an additional scan of
the list, making this infrastructure considerably less efficient than
traditional Lists when deletion of element(s) in a long list is needed.
Modify the slist_foreach_modify() macro to support deleting the current
element in O(1) time, by keeping a "prev" pointer in addition to "cur"
and "next".  Although this makes iteration with this macro a bit slower,
no real harm is done, since in any scenario where you're not going to
delete the current list element you might as well just use slist_foreach
instead.  Improve the comments about when to use each macro.

Back-patch to 9.3 so that we'll have consistent semantics in all branches
that provide ilist.h.  Note this is an ABI break for callers of
slist_foreach_modify().

Andres Freund and Tom Lane
This commit is contained in:
Tom Lane
2013-07-24 17:41:55 -04:00
parent 910d3a458c
commit fa2fad3c06
6 changed files with 71 additions and 19 deletions

View File

@@ -267,15 +267,20 @@ BackgroundWorkerStateChange(void)
/*
* Forget about a background worker that's no longer needed.
*
* At present, this only happens when a background worker marked
* BGW_NEVER_RESTART exits. This function should only be invoked in
* the postmaster.
* The worker must be identified by passing an slist_mutable_iter that
* points to it. This convention allows deletion of workers during
* searches of the worker list, and saves having to search the list again.
*
* This function must be invoked only in the postmaster.
*/
void
ForgetBackgroundWorker(RegisteredBgWorker *rw)
ForgetBackgroundWorker(slist_mutable_iter *cur)
{
RegisteredBgWorker *rw;
BackgroundWorkerSlot *slot;
rw = slist_container(RegisteredBgWorker, rw_lnode, cur->cur);
Assert(rw->rw_shmem_slot < max_worker_processes);
slot = &BackgroundWorkerData->slot[rw->rw_shmem_slot];
slot->in_use = false;
@@ -284,7 +289,7 @@ ForgetBackgroundWorker(RegisteredBgWorker *rw)
(errmsg("unregistering background worker: %s",
rw->rw_worker.bgw_name)));
slist_delete(&BackgroundWorkerList, &rw->rw_lnode);
slist_delete_current(cur);
free(rw);
}