#6428 closed defect (fixed)
[MM] Add Dangerous.listAppendDestroy to the MetaModelica
Reported by: | Adrian Pop | Owned by: | Martin Sjölund |
---|---|---|---|
Priority: | high | Milestone: | 1.17.1 |
Component: | MetaModelica | Version: | 1.16.2 |
Keywords: | Cc: | Karim Adbdelhak |
Description
Change History (12)
comment:1 by , 4 years ago
Cc: | added |
---|
comment:2 by , 4 years ago
Resolution: | → fixed |
---|---|
Status: | new → closed |
comment:3 by , 4 years ago
I basically have something like the following example (extremely simplified). Will this work? And if not, is there a way to make it work? The lists contain ComponentRef in my current implementation but that could also be smth else.
function test input ComponentRef i1; input ComponentRef i2; input UnorderedMap<Integer, list<...>> map; protected list<...> list1, list2; algorithm // if both are in the map merge them if UnorderedMap.contains(i1, map) and UnorderedMap.contains(i2, map) then list1 := UnorderedMap.get(i1, map); list2 := UnorderedMap.get(i2, map); Dangerous.listAppendDestroy(list1,list2); UnorderedMap.add(i1, list2); UnorderedMap.add(i2, list2); // is this needed? else // smth else end if; end if;
follow-up: 7 comment:4 by , 4 years ago
it should be: list1 := Dangerous.listAppendDestroy(list1,list2);
as when list1 is empty I return list2.
comment:5 by , 4 years ago
It depends on how the lists in the UnorderedMap are created, if they are created via cons then is fine.
comment:6 by , 4 years ago
They cannot be empty, they will always have at least one entry. And they are created step by step either by appending one element at a time or merged like we see here.
comment:7 by , 4 years ago
Replying to adrpo:
it should be:
list1 := Dangerous.listAppendDestroy(list1,list2);
as when list1 is empty I return list2.
Good to know! So list1
will be the list i have to use and whatever i put in i cannot use anymore right?
comment:8 by , 4 years ago
list1 will be destroyed if not empty, if is empty then list2 will be returned and list1 stays empty.
comment:9 by , 4 years ago
This is the C code for it, maybe is easier to understand how it works:
modelica_metatype listAppendDestroy(modelica_metatype lstFirstDestroyed, modelica_metatype listSecondKept) { modelica_metatype lst = lstFirstDestroyed; if (MMC_NILTEST(lstFirstDestroyed)) { return listSecondKept; } while (!MMC_NILTEST(lst)) { /* reached the end, set the element */ if (MMC_NILTEST(MMC_CDR(lst))) { MMC_CDR(lst) = listSecondKept; break; } lst = MMC_CDR(lst); } return lstFirstDestroyed; }
comment:10 by , 4 years ago
Since we are talking about performance here, does this save one if-statement?
modelica_metatype listAppendDestroy(modelica_metatype lstFirstDestroyed, modelica_metatype listSecondKept) { modelica_metatype lst = lstFirstDestroyed; if (MMC_NILTEST(lstFirstDestroyed)) { return listSecondKept; } while (!MMC_NILTEST(MMC_CDR(lst))) { lst = MMC_CDR(lst); } /* reached the end, set the element */ MMC_CDR(lst) = listSecondKept; return lstFirstDestroyed; }
PR: https://github.com/OpenModelica/OpenModelica/pull/7303
Note that if you do:
Dangerous.listAppendDestroy(constantList, anyList) you will get a segfault as you cannot write the end of a constant list to point to the second list.