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:
2016-07-06 21:58:47 +10:00
parent 95ff9e9904
commit b98b331d04

View File

@@ -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);
}