+
+void bluesky_mmap_unref(BlueSkyMmap *mmap)
+{
+ if (mmap == NULL)
+ return;
+
+ if (g_atomic_int_dec_and_test(&mmap->refcount)) {
+ /* There is a potential race condition here: the BlueSkyLog contains a
+ * hash table of currently-existing BlueSkyMmap objects, which does not
+ * hold a reference. Some other thread might grab a new reference to
+ * this object after reading it from the hash table. So, before
+ * destruction we need to grab the lock for the hash table, then check
+ * the reference count again. If it is still zero, we can proceed with
+ * object destruction. */
+ BlueSkyLog *log = mmap->log;
+ g_mutex_lock(log->mmap_lock);
+ if (g_atomic_int_get(&mmap->refcount) > 0) {
+ g_mutex_unlock(log->mmap_lock);
+ return;
+ }
+
+ g_hash_table_remove(log->mmap_cache, GINT_TO_POINTER(mmap->log_seq));
+ munmap((void *)mmap->addr, mmap->len);
+ g_free(mmap);
+ g_mutex_unlock(log->mmap_lock);
+ }
+}
+