[Bf-blender-cvs] [23941b425ed] id_copy_refactor: Add same new ID freeing API as copying one.

Bastien Montagne noreply at git.blender.org
Fri Jun 16 10:51:25 CEST 2017


Commit: 23941b425ed9a7243a7b91b8c9a216de9f636bca
Author: Bastien Montagne
Date:   Thu Jun 15 16:18:48 2017 +0200
Branches: id_copy_refactor
https://developer.blender.org/rB23941b425ed9a7243a7b91b8c9a216de9f636bca

Add same new ID freeing API as copying one.

Idea is the same, looks like it will be a tad simpler than with copy
though, since we should not need to change each ID type freeing func, as
ID usercount handling is done in main BKE_library code (would like to do
that for copy as well, but it's not that simple).

===================================================================

M	source/blender/blenkernel/BKE_library.h
M	source/blender/blenkernel/intern/library.c
M	source/blender/blenkernel/intern/library_remap.c
M	source/blender/blenloader/intern/writefile.c
M	source/blender/makesdna/DNA_ID.h

===================================================================

diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h
index 4273aafd7d8..6a67188b640 100644
--- a/source/blender/blenkernel/BKE_library.h
+++ b/source/blender/blenkernel/BKE_library.h
@@ -62,10 +62,14 @@ enum {
 	/* *** Generic options (should be handled by all ID types copying). *** */
 	/* Create copy outside of any main database - similar to 'localize' functions of materials etc. */
 	LIB_ID_COPY_NO_MAIN            = 1 << 0,
-	LIB_ID_COPY_NO_USER_REFCOUNT   = 1 << 1,  /* Do not affect user refcount of datablocks used by copied one. */
-	LIB_ID_COPY_NO_DEG_TAG         = 1 << 2,  /* Do not tag duplicated ID for update in depsgraph. */
-	/* Assume given 'newid' already points to allocated memory for whole datablock (ID + data) - USE WITH CAUTION! */
-	LIB_ID_COPY_NO_ALLOCATE        = 1 << 3,
+	/* Do not affect user refcount of datablocks used by copied one.
+	 * Implies LIB_ID_COPY_NO_MAIN. */
+	LIB_ID_COPY_NO_USER_REFCOUNT   = 1 << 1,
+	/* Assume given 'newid' already points to allocated memory for whole datablock (ID + data) - USE WITH CAUTION!
+	 * Implies LIB_ID_COPY_NO_MAIN. */
+	LIB_ID_COPY_NO_ALLOCATE        = 1 << 2,
+
+	LIB_ID_COPY_NO_DEG_TAG         = 1 << 8,  /* Do not tag duplicated ID for update in depsgraph. */
 
 	/* Specific options to some ID types or usages, may be ignored by unrelated ID copying functions. */
 	LIB_ID_COPY_NO_PROXY_CLEAR     = 1 << 16,  /* Object only, needed by make_local code. */
@@ -77,7 +81,9 @@ enum {
 
 void BKE_libblock_copy_ex(struct Main *bmain, const struct ID *id, struct ID **r_newid, const int flag);
 void *BKE_libblock_copy(struct Main *bmain, const struct ID *id) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+/* "Deprecated" old API. */
 void *BKE_libblock_copy_nolib(const struct ID *id, const bool do_action) ATTR_NONNULL();
+
 void  BKE_libblock_copy_data(struct ID *id, const struct ID *id_from, const bool do_action);
 
 void  BKE_libblock_rename(struct Main *bmain, struct ID *id, const char *name) ATTR_NONNULL();
@@ -87,13 +93,39 @@ struct ID *BKE_libblock_find_name_ex(struct Main *bmain, const short type, const
 struct ID *BKE_libblock_find_name(const short type, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
 
 /* library_remap.c (keep here since they're general functions) */
-void  BKE_libblock_free(struct Main *bmain, void *idv) ATTR_NONNULL();
-void  BKE_libblock_free_datablock(struct ID *id) ATTR_NONNULL();
+/**
+ * New freeing logic options.
+ */
+enum {
+	/* *** Generic options (should be handled by all ID types freeing). *** */
+	/* Do not try to remove freed ID from given Main (passed Main may be NULL). */
+	LIB_ID_FREE_NO_MAIN            = 1 << 0,
+	/* Do not affect user refcount of datablocks used by freed one.
+	 * Implies LIB_ID_FREE_NO_MAIN. */
+	LIB_ID_FREE_NO_USER_REFCOUNT   = 1 << 1,
+	/* Assume freed ID datablock memory is managed elsewhere, do not free it
+	 * (still calls relevant ID type's freeing function though) - USE WITH CAUTION!
+	 * Implies LIB_ID_FREE_NO_MAIN. */
+	LIB_ID_FREE_NOT_ALLOCATED      = 1 << 2,
+
+	LIB_ID_FREE_NO_DEG_TAG         = 1 << 8,  /* Do not tag freed ID for update in depsgraph. */
+	LIB_ID_FREE_NO_UI_USER         = 1 << 9,  /* Do not attempt to remove freed ID from UI data/notifiers/... */
+};
+
+void BKE_id_free_ex(struct Main *bmain, void *idv, int flag, const bool use_flag_from_idtag);
+void BKE_id_free(struct Main *bmain, void *idv);
+/* Those three naming are bad actually, should be BKE_id_free... (since it goes beyond mere datablock). */
+/* "Deprecated" old API */
 void  BKE_libblock_free_ex(struct Main *bmain, void *idv, const bool do_id_user, const bool do_ui_user) ATTR_NONNULL();
+void  BKE_libblock_free(struct Main *bmain, void *idv) ATTR_NONNULL();
 void  BKE_libblock_free_us(struct Main *bmain, void *idv) ATTR_NONNULL();
-void  BKE_libblock_free_data(struct ID *id, const bool do_id_user) ATTR_NONNULL();
+
+/* TODO should be named "BKE_id_delete()". */
 void  BKE_libblock_delete(struct Main *bmain, void *idv) ATTR_NONNULL();
 
+void  BKE_libblock_free_datablock(struct ID *id, const int flag) ATTR_NONNULL();
+void  BKE_libblock_free_data(struct ID *id, const bool do_id_user) ATTR_NONNULL();
+
 void BKE_id_lib_local_paths(struct Main *bmain, struct Library *lib, struct ID *id);
 void id_lib_extern(struct ID *id);
 void BKE_library_filepath_set(struct Library *lib, const char *filepath);
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index a1d0f12bed3..a0c1bc93f6b 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -1127,7 +1127,8 @@ void BKE_libblock_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int fla
 	ID *idn = *r_newid;
 
 	BLI_assert((flag & LIB_ID_COPY_NO_MAIN) != 0 || bmain != NULL);
-	BLI_assert((flag & LIB_ID_COPY_NO_ALLOCATE) == 0 || (flag & LIB_ID_COPY_NO_MAIN) != 0);
+	BLI_assert((flag & LIB_ID_COPY_NO_MAIN) != 0 || (flag & LIB_ID_COPY_NO_ALLOCATE) == 0);
+	BLI_assert((flag & LIB_ID_COPY_NO_MAIN) != 0 || (flag & LIB_ID_COPY_NO_USER_REFCOUNT) == 0);
 
 	if ((flag & LIB_ID_COPY_NO_ALLOCATE) != 0) {
 		/* r_newid already contains pointer to allocated memory. */
@@ -1166,7 +1167,7 @@ void BKE_libblock_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int fla
 		idn->tag |= LIB_TAG_FREE_NO_USER_REFCOUNT;
 	}
 	if ((flag & LIB_ID_COPY_NO_ALLOCATE) != 0) {
-		idn->tag |= LIB_TAG_FREE_NO_ALLOCATED;
+		idn->tag |= LIB_TAG_FREE_NOT_ALLOCATED;
 	}
 
 	if ((flag & LIB_ID_COPY_NO_DEG_TAG) == 0 && (flag & LIB_ID_COPY_NO_MAIN) == 0) {
diff --git a/source/blender/blenkernel/intern/library_remap.c b/source/blender/blenkernel/intern/library_remap.c
index 01ad4fb86ce..c11d64843f4 100644
--- a/source/blender/blenkernel/intern/library_remap.c
+++ b/source/blender/blenkernel/intern/library_remap.c
@@ -729,9 +729,11 @@ void BKE_libblock_free_data(ID *id, const bool do_id_user)
 		IDP_FreeProperty_ex(id->properties, do_id_user);
 		MEM_freeN(id->properties);
 	}
+
+	/* XXX TODO remove animdata handling from each type's freeing func, and do it here, like for copy! */
 }
 
-void BKE_libblock_free_datablock(ID *id)
+void BKE_libblock_free_datablock(ID *id, const int UNUSED(flag))
 {
 	const short type = GS(id->name);
 	switch (type) {
@@ -841,6 +843,90 @@ void BKE_libblock_free_datablock(ID *id)
 	}
 }
 
+
+void BKE_id_free_ex(Main *bmain, void *idv, int flag, const bool use_flag_from_idtag)
+{
+	ID *id = idv;
+
+	if (use_flag_from_idtag) {
+		if ((id->tag & LIB_TAG_FREE_NO_MAIN) != 0) {
+			flag |= LIB_ID_FREE_NO_MAIN;
+		}
+		else {
+			flag &= ~LIB_ID_FREE_NO_MAIN;
+		}
+
+		if ((id->tag & LIB_TAG_FREE_NO_USER_REFCOUNT) != 0) {
+			flag |= LIB_ID_FREE_NO_USER_REFCOUNT;
+		}
+		else {
+			flag &= ~LIB_ID_FREE_NO_USER_REFCOUNT;
+		}
+
+		if ((id->tag & LIB_TAG_FREE_NOT_ALLOCATED) != 0) {
+			flag |= LIB_ID_FREE_NOT_ALLOCATED;
+		}
+		else {
+			flag &= ~LIB_ID_FREE_NOT_ALLOCATED;
+		}
+	}
+
+	BLI_assert((flag & LIB_ID_FREE_NO_MAIN) != 0 || bmain != NULL);
+	BLI_assert((flag & LIB_ID_FREE_NO_MAIN) != 0 || (flag & LIB_ID_FREE_NOT_ALLOCATED) == 0);
+	BLI_assert((flag & LIB_ID_FREE_NO_MAIN) != 0 || (flag & LIB_ID_FREE_NO_USER_REFCOUNT) == 0);
+
+	const short type = GS(id->name);
+
+	if (bmain && (flag & LIB_ID_FREE_NO_DEG_TAG) == 0) {
+		DAG_id_type_tag(bmain, type);
+	}
+
+#ifdef WITH_PYTHON
+	BPY_id_release(id);
+#endif
+
+	if ((flag & LIB_ID_FREE_NO_USER_REFCOUNT) == 0) {
+		BKE_libblock_relink_ex(bmain, id, NULL, NULL, true);
+	}
+
+	BKE_libblock_free_datablock(id, flag);
+
+	/* avoid notifying on removed data */
+	if (bmain) {
+		BKE_main_lock(bmain);
+	}
+
+	if ((flag & LIB_ID_FREE_NO_UI_USER) == 0) {
+		if (free_notifier_reference_cb) {
+			free_notifier_reference_cb(id);
+		}
+
+		if (remap_editor_id_reference_cb) {
+			remap_editor_id_reference_cb(id, NULL);
+		}
+	}
+
+	if ((flag & LIB_ID_FREE_NO_MAIN) == 0) {
+		ListBase *lb = which_libbase(bmain, type);
+		BLI_remlink(lb, id);
+	}
+
+	BKE_libblock_free_data(id, (flag & LIB_ID_FREE_NO_USER_REFCOUNT) == 0);
+
+	if (bmain) {
+		BKE_main_unlock(bmain);
+	}
+
+	if ((flag & LIB_ID_FREE_NOT_ALLOCATED) == 0) {
+		MEM_freeN(id);
+	}
+}
+
+void BKE_id_free(Main *bmain, void *idv)
+{
+	BKE_id_free_ex(bmain, idv, 0, true);
+}
+
 /**
  * used in headerbuttons.c image.c mesh.c screen.c sound.c and library.c
  *
@@ -865,7 +951,7 @@ void BKE_libblock_free_ex(Main *bmain, void *idv, const bool do_id_user, const b
 		BKE_libblock_relink_ex(bmain, id, NULL, NULL, true);
 	}
 
-	BKE_libblock_free_datablock(id);
+	BKE_libblock_free_datablock(id, 0);
 
 	/* avoid notifying on removed data */
 	BKE_main_lock(bmain);
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index 0336f28ed85..fbaaa91bc4d 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -3842,7 +3842,7 @@ static bool write_file_handle(
 
 		for (; id; id = id->next) {
 			/* We should never attempt to write non-regular IDs (i.e. all kind of temp/runtime ones). */
-			BLI_assert((id->tag & (LIB_TAG_FREE_NO_MAIN | LIB_TAG_FREE_NO_USER_REFCOUNT | LIB_TAG_FREE_NO_ALLOCATED)) == 0);
+			BLI_assert((id->tag & (LIB_TAG_FREE_NO_MAIN | LIB_TAG_FREE_NO_USER_REFCOUNT | LIB_TAG_FREE_NOT_ALLOCATED)) == 0);
 
 			switch ((ID_Type)GS(id->name)) {
 				case ID_WM:
diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h
index 857b7478481..b3690e7d179 100644
--- a/source/blender/makesdna/DNA_ID.h
+++ b/source/blender/makesdna/DNA_ID.h
@@ -355,7 +355,7 @@ enum {
 	LIB_TAG_FREE_NO_USER_REFCOUNT = 1 << 17,  /* Datablock does not refcount usages of other IDs. */
 	/* Datablock was not allocated by standard system (BKE_libblock_alloc), do not free its memory
 	 * (usual type-specific freeing is called though). */
-	LIB_TAG_FREE_NO_ALLOCATED     = 1 << 18,
+	LIB_TAG_FREE_NOT_ALLOCATED     = 1 << 18,
 };
 
 /* To filter ID types (filter_id) */




More information about the Bf-blender-cvs mailing list