Make main library safe(er) for the threaded usage

Added a lock to the Main which is getting acquired and released
when modifying it's lists.

Should not be any functional changes now, it just means Main is
now considered safe without worrying about locks in the callee.
This commit is contained in:
Sergey Sharybin 2014-06-24 20:43:08 +06:00
parent fc1040cc47
commit 04648767fa
Notes: blender-bot 2023-02-14 11:21:43 +01:00
Referenced by issue #41964, 2.72 Freestyle renders two times longer on Linux
Referenced by issue #40525, Blender Crash/Freeze On Animation Plays
6 changed files with 19 additions and 8 deletions

View File

@ -77,7 +77,7 @@ int set_listbasepointers(struct Main *main, struct ListBase **lb);
void BKE_libblock_free(struct Main *bmain, void *idv);
void BKE_libblock_free_ex(struct Main *bmain, void *idv, bool do_id_user);
void BKE_libblock_free_us(struct Main *bmain, void *idv);
void BKE_libblock_free_data(struct ID *id);
void BKE_libblock_free_data(struct Main *bmain, struct ID *id);
/* Main API */

View File

@ -41,6 +41,7 @@
*
*/
#include "DNA_listBase.h"
#include "BLI_threads.h"
#ifdef __cplusplus
extern "C" {
@ -96,6 +97,8 @@ typedef struct Main {
/* Evaluation context used by viewport */
struct EvaluationContext *eval_ctx;
SpinLock lock;
} Main;
#define MAIN_VERSION_ATLEAST(main, ver, subver) \

View File

@ -747,12 +747,14 @@ void *BKE_libblock_alloc(Main *bmain, short type, const char *name)
id = alloc_libblock_notest(type);
if (id) {
BLI_spin_lock(&bmain->lock);
BLI_addtail(lb, id);
id->us = 1;
id->icon_id = 0;
*( (short *)id->name) = type;
new_id(lb, id, name);
/* alphabetic insertion: is in new_id */
BLI_spin_unlock(&bmain->lock);
}
DAG_id_type_tag(bmain, type);
return id;
@ -881,10 +883,8 @@ static void animdata_dtar_clear_cb(ID *UNUSED(id), AnimData *adt, void *userdata
}
}
void BKE_libblock_free_data(ID *id)
void BKE_libblock_free_data(Main *bmain, ID *id)
{
Main *bmain = G.main; /* should eventually be an arg */
if (id->properties) {
IDP_FreeProperty(id->properties);
MEM_freeN(id->properties);
@ -1008,12 +1008,15 @@ void BKE_libblock_free_ex(Main *bmain, void *idv, bool do_id_user)
}
/* avoid notifying on removed data */
BLI_spin_lock(&bmain->lock);
if (free_notifier_reference_cb)
free_notifier_reference_cb(id);
BLI_remlink(lb, id);
BKE_libblock_free_data(id);
BKE_libblock_free_data(bmain, id);
BLI_spin_unlock(&bmain->lock);
MEM_freeN(id);
}
@ -1043,7 +1046,9 @@ void BKE_libblock_free_us(Main *bmain, void *idv) /* test users */
Main *BKE_main_new(void)
{
Main *bmain = MEM_callocN(sizeof(Main), "new main");
bmain->eval_ctx = MEM_callocN(sizeof(EvaluationContext), "EvaluationContext");
bmain->eval_ctx = MEM_callocN(sizeof(EvaluationContext),
"EvaluationContext");
BLI_spin_init(&bmain->lock);
return bmain;
}
@ -1106,6 +1111,7 @@ void BKE_main_free(Main *mainvar)
}
}
BLI_spin_end(&mainvar->lock);
MEM_freeN(mainvar->eval_ctx);
MEM_freeN(mainvar);
}

View File

@ -780,11 +780,13 @@ void test_object_materials(Main *bmain, ID *id)
return;
}
BLI_spin_lock(&bmain->lock);
for (ob = bmain->object.first; ob; ob = ob->id.next) {
if (ob->data == id) {
BKE_material_resize_object(ob, *totcol, false);
}
}
BLI_spin_unlock(&bmain->lock);
}
void assign_material_id(ID *id, Material *ma, short act)

View File

@ -2148,7 +2148,7 @@ Mesh *BKE_mesh_new_from_object(
* if it didn't the curve did not have any segments or otherwise
* would have generated an empty mesh */
if (tmpobj->type != OB_MESH) {
BKE_libblock_free_us(G.main, tmpobj);
BKE_libblock_free_us(bmain, tmpobj);
return NULL;
}

View File

@ -1777,7 +1777,7 @@ void ntreeFreeTree_ex(bNodeTree *ntree, const bool do_id_user)
if (tntree == ntree)
break;
if (tntree == NULL) {
BKE_libblock_free_data(&ntree->id);
BKE_libblock_free_data(G.main, &ntree->id);
}
}
/* same as ntreeFreeTree_ex but always manage users */