writefile: simplify outliner treestore workaround
Instead of keeping a list of allocations, write to unique addresses based on the BLI_mempool address since we know this is unique.
This commit is contained in:
@@ -2911,43 +2911,41 @@ static void write_uilist(WriteData *wd, uiList *ui_list)
|
||||
}
|
||||
}
|
||||
|
||||
static void write_soops(WriteData *wd, SpaceOops *so, LinkNode **tmp_mem_list)
|
||||
static void write_soops(WriteData *wd, SpaceOops *so)
|
||||
{
|
||||
BLI_mempool *ts = so->treestore;
|
||||
|
||||
if (ts) {
|
||||
SpaceOops so_flat = *so;
|
||||
|
||||
int elems = BLI_mempool_count(ts);
|
||||
/* linearize mempool to array */
|
||||
TreeStoreElem *data = elems ? BLI_mempool_as_arrayN(ts, "TreeStoreElem") : NULL;
|
||||
|
||||
if (data) {
|
||||
TreeStore *ts_flat = MEM_callocN(sizeof(TreeStore), "TreeStore");
|
||||
/* In this block we use the memory location of the treestore
|
||||
* but _not_ its data, the addresses in this case are UUID's,
|
||||
* since we can't rely on malloc giving us different values each time.
|
||||
*/
|
||||
TreeStore ts_flat = {0};
|
||||
|
||||
ts_flat->usedelem = elems;
|
||||
ts_flat->totelem = elems;
|
||||
ts_flat->data = data;
|
||||
/* we know the treestore is at least as big as a pointer,
|
||||
* so offsetting works to give us a UUID. */
|
||||
void *data_addr = (void *)POINTER_OFFSET(ts, sizeof(void *));
|
||||
|
||||
ts_flat.usedelem = elems;
|
||||
ts_flat.totelem = elems;
|
||||
ts_flat.data = data_addr;
|
||||
|
||||
/* temporarily replace mempool-treestore by flat-treestore */
|
||||
so->treestore = (BLI_mempool *)ts_flat;
|
||||
writestruct(wd, DATA, SpaceOops, 1, so);
|
||||
|
||||
writestruct(wd, DATA, TreeStore, 1, ts_flat);
|
||||
writestruct(wd, DATA, TreeStoreElem, elems, data);
|
||||
|
||||
/* we do not free the pointers immediately, because if we have multiple
|
||||
* outliners in a screen we might get the same address on the next
|
||||
* malloc, which makes the address no longer unique and so invalid for
|
||||
* lookups on file read, causing crashes or double frees */
|
||||
BLI_linklist_prepend(tmp_mem_list, ts_flat);
|
||||
BLI_linklist_prepend(tmp_mem_list, data);
|
||||
writestruct_at_address(wd, DATA, TreeStore, 1, ts, &ts_flat);
|
||||
writestruct_at_address(wd, DATA, TreeStoreElem, elems, data_addr, data);
|
||||
}
|
||||
else {
|
||||
so->treestore = NULL;
|
||||
writestruct(wd, DATA, SpaceOops, 1, so);
|
||||
so_flat.treestore = NULL;
|
||||
writestruct_at_address(wd, DATA, SpaceOops, 1, so, &so_flat);
|
||||
}
|
||||
|
||||
/* restore old treestore */
|
||||
so->treestore = ts;
|
||||
}
|
||||
else {
|
||||
writestruct(wd, DATA, SpaceOops, 1, so);
|
||||
@@ -2960,7 +2958,6 @@ static void write_screens(WriteData *wd, ListBase *scrbase)
|
||||
ScrArea *sa;
|
||||
ScrVert *sv;
|
||||
ScrEdge *se;
|
||||
LinkNode *tmp_mem_list = NULL;
|
||||
|
||||
sc = scrbase->first;
|
||||
while (sc) {
|
||||
@@ -3064,7 +3061,7 @@ static void write_screens(WriteData *wd, ListBase *scrbase)
|
||||
}
|
||||
else if (sl->spacetype == SPACE_OUTLINER) {
|
||||
SpaceOops *so = (SpaceOops *)sl;
|
||||
write_soops(wd, so, &tmp_mem_list);
|
||||
write_soops(wd, so);
|
||||
}
|
||||
else if (sl->spacetype == SPACE_IMAGE) {
|
||||
writestruct(wd, DATA, SpaceImage, 1, sl);
|
||||
@@ -3132,8 +3129,6 @@ static void write_screens(WriteData *wd, ListBase *scrbase)
|
||||
sc = sc->id.next;
|
||||
}
|
||||
|
||||
BLI_linklist_freeN(tmp_mem_list);
|
||||
|
||||
/* flush helps the compression for undo-save */
|
||||
mywrite(wd, MYWRITE_FLUSH, 0);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user