diff options
author | Allison Lortie <desrt@desrt.ca> | 2016-08-12 11:13:18 +0200 |
---|---|---|
committer | Allison Lortie <desrt@desrt.ca> | 2016-10-14 10:03:07 +0200 |
commit | 4f0688a7009eb2fd8f7ad5e701cd62b4bb2b4b28 (patch) | |
tree | 2b23c6074b8dd865238e5d0e4ef6cc112dd82765 | |
parent | 9385c9a8c383486e083c4b019df31b10aabbffbd (diff) | |
download | dconf-4f0688a7009eb2fd8f7ad5e701cd62b4bb2b4b28.tar.gz |
engine: optimise the no-locks case
Add a fast path for avoiding writability checks for the very common case
where there are no databases installed that have locks (ie: the default
configuration).
This allows us to avoid iterating a changeset to check for writability
before sending it off to the service, for example.
-rw-r--r-- | engine/dconf-engine-source.h | 2 | ||||
-rw-r--r-- | engine/dconf-engine.c | 40 |
2 files changed, 36 insertions, 6 deletions
diff --git a/engine/dconf-engine-source.h b/engine/dconf-engine-source.h index 802f09d..71e03a6 100644 --- a/engine/dconf-engine-source.h +++ b/engine/dconf-engine-source.h @@ -44,7 +44,7 @@ struct _DConfEngineSource GvdbTable *values; GvdbTable *locks; GBusType bus_type; - gboolean writable; + gboolean writable; /* this is not allowed to change */ gboolean did_warn; gchar *bus_name; gchar *object_path; diff --git a/engine/dconf-engine.c b/engine/dconf-engine.c index bc36e52..aca2dd3 100644 --- a/engine/dconf-engine.c +++ b/engine/dconf-engine.c @@ -14,7 +14,7 @@ * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see <http://www.gnu.org/licenses/>. * - * Author: Ryan Lortie <desrt@desrt.ca> + * Author: Allison Lortie <desrt@desrt.ca> */ #include "config.h" @@ -162,6 +162,7 @@ struct _DConfEngine guint64 state; /* Counter that changes every time a source is refreshed. */ DConfEngineSource **sources; /* Array never changes, but each source changes internally. */ gint n_sources; + gboolean has_locks; /* Must be updated when refreshing the source list. */ GMutex queue_lock; /* This lock is for pending, in_flight, queue_cond */ GCond queue_cond; /* Signalled when the queues empty */ @@ -195,13 +196,32 @@ struct _DConfEngine static void dconf_engine_acquire_sources (DConfEngine *engine) { + gboolean changed = FALSE; gint i; g_mutex_lock (&engine->sources_lock); for (i = 0; i < engine->n_sources; i++) - if (dconf_engine_source_refresh (engine->sources[i])) + changed |= dconf_engine_source_refresh (engine->sources[i]); + + if (changed) + { + gboolean has_locks; + + /* If we have no sources, or if the first source is non-writable, the + * effect is as-if everything is locked. + * + * Note: nothing in this line can change as a result of a refresh. + */ + has_locks = engine->n_sources == 0 || !engine->sources[0]->writable; + + /* Now we check if the refresh had any effect. */ + for (i = 1; !has_locks && i < engine->n_sources; i++) + has_locks |= engine->sources[i]->locks != NULL; + + engine->has_locks = has_locks; engine->state++; + } } static void @@ -234,6 +254,12 @@ dconf_engine_new (const gchar *profile, engine->free_func = free_func; engine->ref_count = 1; + /* The engine starts with zero sources, which means that every key is + * effectively locked. If the engine has more than zero sources, this + * will be updated when the first refresh is done. + */ + engine->has_locks = TRUE; + g_mutex_init (&engine->sources_lock); g_mutex_init (&engine->queue_lock); g_cond_init (&engine->queue_cond); @@ -354,10 +380,13 @@ gboolean dconf_engine_is_writable (DConfEngine *engine, const gchar *key) { - gboolean writable; + gboolean writable = TRUE; dconf_engine_acquire_sources (engine); - writable = dconf_engine_is_writable_internal (engine, key); + + if (engine->has_locks) + writable = dconf_engine_is_writable_internal (engine, key); + dconf_engine_release_sources (engine); return writable; @@ -1115,7 +1144,8 @@ dconf_engine_changeset_changes_only_writable_keys (DConfEngine *engine, dconf_engine_acquire_sources (engine); - if (!dconf_changeset_all (changeset, dconf_engine_is_writable_changeset_predicate, engine)) + if (engine->has_locks && + !dconf_changeset_all (changeset, dconf_engine_is_writable_changeset_predicate, engine)) { g_set_error_literal (error, DCONF_ERROR, DCONF_ERROR_NOT_WRITABLE, "The operation attempted to modify one or more non-writable keys"); |