[Swift] strong, weak, unowned์ ๋น๋ฐ
๋ํผ๋ฐ์ค ์นด์ดํธ
์๋ ํ์ธ์! ์ค๋์ swift์์ ๋ํผ๋ฐ์ค ์นด์ดํธ๋ฅผ ์ด๋ป๊ฒ ๊ตฌํํ๊ณ ์๋์ง ์์๋ณด๋ ค๊ณ ํฉ๋๋ค. ๋ง์ ๋ธ๋ก๊ทธ์์ weak๊ณผ unowned์ ์ฐจ์ด๋ฅผ Optional์ ๊ฐ๋ฅ ์ฌ๋ถ๋ผ๊ณ ๋งํ๊ณ ์๋๋ฐ, ์ฌ์ค ํ๋ฆฐ ํํ์ด์์. Swift 5.0๋ถํฐ๋ Unowned Optional์ด ์ถ๊ฐ๋์ด์ unowned๋ ์ต์ ๋์ ๊ฐ์ง ์ ์์ต๋๋ค.
๊ทธ๋์ ๋ ๋ก์ฐ ๋ ๋ฒจ๋ก ๊ฐ๋ฉด ๋ํผ๋ฐ์ค ์นด์ดํ ๊ณผ ๋ฉ๋ชจ๋ฆฌ ํด์ ์ ์์ด์ ๋ถ๋ช ๋ค๋ฅธ ๋ถ๋ถ์ด ์์ ๊ฒ์ด๋ผ๊ณ ์๊ฐํ๊ณ ,
Swift ๊ณต์ ๋ ํฌ์ RefCount.h ์ ๋ํผ๋ฐ์ค ์นด์ดํ ์ ๋ํ ์ค๋ช ์ด ์์ธํ๊ฒ ์ฃผ์์ผ๋ก ๋ฌ๋ ค์์ด์ ์ด ๋ถ๋ถ์ ๋ฒ์ญํ๋ฉด์ ๊ณต๋ถํด๋ณด๋ ค๊ณ ํฉ๋๋ค. ๊ทธ๋ผ ์์ํ๊ฒ ์ต๋๋ค!
์ธํธ๋ก
๐ An object conceptually has three refcounts. These refcounts are stored either "inline" in the field following the isa or in a "side table entry" pointed to by the field following the isa.
๊ฐ์ฒด๋ ๊ฐ๋ ์ ์ผ๋ก ์ธ ์ข ๋ฅ์ ๋ํผ๋ฐ์ค ์นด์ดํธ๋ฅผ ๊ฐ์ง๊ณ ์์ด์. ๊ทธ๋ฆฌ๊ณ ์ด ์นด์ดํธ๋ isa ์์ ์๋ "inline"์ ์ ์ฅ๋๊ฑฐ๋ isa๊ฐ ํฌ์ธํฐ๋ฅผ ๊ฐ์ง๊ณ ์๋ "side table entry"์ ์ ์ฅ๋ฉ๋๋ค.
ํ ๋ฌด์จ ์๋ฆฐ์ง ๋ชจ๋ฅด๊ฒ ๋ค์.. isa, inline, side table์ ํตํด๋๊ณ ๊ณ์ ์ฝ์ด๋ณด์๊ตฌ์.
๊ฐํ ์ฐธ์กฐ ์นด์ดํธ(Strong Reference Count)
๐ The strong RC counts strong references to the object. When the strong RC reaches zero the object is deinited, unowned reference reads become errors, and weak reference reads become nil. The strong RC is stored as an extra count: when the physical field is 0 the logical value is 1.
๊ฐํ ์ฐธ์กฐ(Strong Reference Count) ์นด์ดํธ๋ ๊ฐ์ฒด๋ฅผ ๊ฐํ๊ฒ ์ฐธ์กฐํ๋ ๊ฐ์๋ฅผ ๊ธฐ๋กํด์. ๋ง์ฝ ๊ฐํ ์ฐธ์กฐ๊ฐ 0์ด ๋๋ฉด ๊ฐ์ฒด๋ deinit ๋๊ณ ์ด ๊ฐ์ฒด๋ฅผ ๋ฏธ์์ ์ฐธ์กฐ(unowned reference) ์ฝ์ผ๋ ค๊ณ ํ๋ค๋ฉด ์๋ฌ, ์ฝํ ์ฐธ์กฐ(weak refrence)๋ก ์ฝ์ผ๋ ค๊ณ ํ๋ค๋ฉด nil์ด ๋์ฃ . ์ฌ๊ธฐ๊น์ง๋ ์ฐ๋ฆฌ๊ฐ ๋ค ์๋ ์ด์ผ๊ธฐ์ด๋ค์ใ ใ
๊ทธ๋ฆฌ๊ณ ๊ฐํ ์ฐธ์กฐ ์นด์ดํธ๋ ์์คํธ๋ผ ์นด์ดํธ๋ก ์ ์ฅ๋๋ค๊ณ ํ๋๋ฐ์, ํ๋์ ์ค์ ๊ฐ์ด 0์ด๋ผ๋ฉด, ๋ ผ๋ฆฌ์ ์ผ๋ก๋ 1๋ก ์ทจ๊ธ๋๋ค๊ณ ํฉ๋๋ค.
์์ง๊น์ง๋ ํ์ดํฉ๋๋ค. ๊ณ์ ์ฝ์ด๋ณผ๊น์?
๋ฏธ์์ ์ฐธ์กฐ ์นด์ดํธ(Unowned Reference Count)
๐The unowned RC counts unowned references to the object. The unowned RC also has an extra +1 on behalf of the strong references; this +1 is decremented after deinit completes. When the unowned RC reaches zero the object's allocation is freed.
๋ฏธ์์ ์ฐธ์กฐ ์นด์ดํธ(Unowned Reference Count)๋ ๋ฏธ์์ ์ฐธ์กฐ๋ก ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ๋ ๊ฐ์๋ฅผ ์นด์ดํ ํฉ๋๋ค. ๋ฏธ์์ ์ฐธ์กฐ์ ์นด์ดํธ๋ ๊ฐํ ์ฐธ์กฐ์ ๋ํด 1์ ์ถ๊ฐ์ ์ธ ์นด์ดํธ๋ฅผ ๊ฐ์ง๋๋ฐ์, ์ด ์ถ๊ฐ์ ์ธ ์นด์ดํธ๋ deinit์ด ์๋ฃ๋๋ฉด ์ค์ด๋ ๋ค๊ณ ํฉ๋๋ค.
๋ง์ฝ ๋ฏธ์์ ์ฐธ๊ณ ์นด์ดํธ๊ฐ 0์ด ๋๋ฉด ๊ฐ์ฒด์ ํ ๋น์ด ํด์ (freed)๋ฉ๋๋ค.
๊ฐํ ์ฐธ์กฐ์ ๋ญ๊ฐ ๋ค๋ฅด๋ค๋ ๊ฒ์ ๋์น์ฑ์ จ๋์? ๊ฐํ ์ฐธ์กฐ์์๋ ์นด์ดํธ๊ฐ 0์ด๋๋ฉด deinit์ ํ๋ค๊ณ ํํํ๊ณ ์๋๋ฐ, ๋ฏธ์์ ์ฐธ์กฐ์ ์นด์ดํธ๊ฐ 0์ด ๋๋ฉด free ๋๋ค๊ณ ํํํ๊ณ ์์ด์.
deinit๊ณผ free์๋ ์ฐจ์ด๊ฐ ์๋๋ฐ์, deinit์ ์ธ์คํด์ค๊ฐ ์๋ฉธ๋๋ ๊ฒ์ด์ง ์์ง ๋ฉ๋ชจ๋ฆฌ์์ ํด์ ๋ ์ํ๊ฐ ์๋๋๋ค. ์ฆ, deinit๋ free์ ์ฌ์ ๋์์ผ ๋ฟ์ธ ๊ฒ์ด์ฃ . ์ด ๋ถ๋ถ์ ๋ฌธ์์์ ๋ช ํํ๊ฒ ๋ํ๋ด๊ณ ์์ง๋ ์์ง๋ง ์ค์ํํธ์ ๊ณต์๋ฌธ์๋ฅผ ์ดํด๋ณด๋ฉด,
์ด๋ ๊ฒ deinitialization๊ณผ deallocation์ ๊ตฌ๋ถํด์ ๋ถ๋ฅด๊ณ ์๋ ๊ฒ์ ์ ์ ์์ด์.
๊ทธ๋ผ ๋ค์ ๋์์์ ์ ๋ฆฌํด๋ณด๋ฉด ๋ฏธ์์ ์ฐธ์กฐ ์นด์ดํธ๋ ๊ฐํ ์ฐธ์กฐ ์นด์ดํธ์ ๋ํด 1์ ์ถ๊ฐ์ ์ธ ์นด์ดํธ๋ฅผ ๊ฐ์ง๊ณ , deinit์ด ์๋ฃ๋๋ฉด ์ด ์นด์ดํธ๊ฐ ์ค์ด๋ ๋ค๋ ๊ฒ, ๊ทธ๋ฆฌ๊ณ ๋ฏธ์์ ์ฐธ์กฐ ์นด์ดํธ๊ฐ 0์ด ๋๋ฉด ์ธ์คํด์ค๊ฐ ๋ฉ๋ชจ๋ฆฌ์์ ํด์ ๋๋ค๋ ๊ฒ์ ์ ์ ์์์ต๋๋ค.
๊ณ์ ์ฝ์ด๋ด ์๋ค.
์ฝํ ์ฐธ์กฐ ์นด์ดํธ(Weak Reference Count)
๐ The weak RC counts weak references to the object. The weak RC also has an extra +1 on behalf of the unowned references; this +1 is decremented after the object's allocation is freed. When the weak RC reaches zero the object's side table entry is freed.
์ฝํ ์ฐธ์กฐ ์นด์ดํธ(Weak Reference Count)๋ ๊ฐ์ฒด์ ๋ํ ์ฝํ ์ฐธ์กฐ์ ๊ฐ์๋ฅผ ์ ์ฅํฉ๋๋ค. ์ฝํ ์ฐธ์กฐ๋ ๋ฏธ์์ ์ฐธ์กฐ ์นด์ดํธ์ ๋ํด 1์ ์ถ๊ฐ์ ์ธ ์นด์ดํธ๋ฅผ ๊ฐ์ง๋๋ฐ์, ์ด ์นด์ดํธ๋ ๊ฐ์ฒด๊ฐ ๋ฉ๋ชจ๋ฆฌ์์ ํด์ ๋๋ฉด ์ค์ด๋ค๊ฒ ๋ฉ๋๋ค.
๊ทธ๋ฆฌ๊ณ ์ฝํ ์ฐธ์กฐ๊ฐ 0์ด ๋๋ฉด ๊ฐ์ฒด์ side table entry๊ฐ ํด์ ๋ฉ๋๋ค.
์ด๋ฒ์๋ ๋ค๋ฅธ ๋ถ๋ถ์ด ์๊ฒผ์ฃ ? ์ฝํ ์ฐธ์กฐ ์นด์ดํธ๊ฐ 0์ด๋๋ฉด ์ฌ์ด๋ ํ ์ด๋ธ ์ํธ๋ฆฌ๋ผ๋ ๊ฒ์ด ๋ฉ๋ชจ๋ฆฌ์์ ํด์ ๋๋ค๊ณ ํฉ๋๋ค.
์ด์ ๋ค์ด์ด์ ์ฌ์ด๋ ํ ์ด๋ธ์ ๋ํ ์ค๋ช ์ด ๋์ค๋๊น ๊ณ์ ์ฝ์ด๋ณด๊ฒ ์ต๋๋ค.
์ฌ์ด๋ ํ ์ด๋ธ(Side Table Entry)
๐ Objects initially start with no side table. They can gain a side table when:
* a weak reference is formed and pending future implementation:
* strong RC or unowned RC overflows (inline RCs will be small on 32-bit)
* associated object storage is needed on an object
* etc
Gaining a side table entry is a one-way operation; an object with a side table entry never loses it. This prevents some thread races.
๊ฐ์ฒด๊ฐ ์ฒ์ ์์ฑ๋์์ ๋๋ ์ฌ์ด๋ ํ ์ด๋ธ์ด ์๋ค๊ณ ํฉ๋๋ค. ๊ฐ์ฒด์ ๋ํด ์ฌ์ด๋ ํ ์ด๋ธ์ด ์์ฑ๋๋ ๊ฒฝ์ฐ๋ ๋ช ๊ฐ์ง๊ฐ ์๋๋ฐ์,
1. ๊ฐ์ฒด์ ๋ํ ์ฝํ ์ฐธ์กฐ๊ฐ ๋ฐ์ํ์ ๋
2. ๊ฐํ ์ฐธ์กฐ๋ ๋ฏธ์์ ์ฐธ์กฐ์ ์นด์ดํธ๊ฐ ๋ฒ์๋ฅผ ์ด๊ณผํ์ ๋
3. ๊ฐ์ฒด์ ๋ํ ์ถ๊ฐ์ ์ธ ๊ณต๊ฐ์ด ํ์ํ ๋
4. ๋ฑ๋ฑ(???)
์์งํ ๊ณต์ ์์ค์ฝ๋์ธ๋ฐ etc๋ ๋๋ฌดํ๊ฒ ์๋์ง... ์ผ๋จ ๊ฐ์ฒด์ ์ถ๊ฐ์ ์ธ ๊ณต๊ฐ์ด ํ์ํ๊ฑฐ๋ ๋ฒ์ overflow๋ ์ฝ๊ฒ ์ผ์ด๋์ง ์๋ ์ผ์ธ ๊ฒ ๊ฐ๊ณ , ์ฝํ ์ฐธ์กฐ๊ฐ ๋ฐ์ํ์ ๋๊ฐ ๊ฐ์ฅ ์ค์ํด ๋ณด์ด๋ค์.
๋ง์ง๋ง ๋ฌธ์ฅ์์๋ ์ฌ์ด๋ ํ ์ด๋ธ์ด ์์ฑ๋๋ ๊ฒ์ด one-way operation์ด๋ผ๊ณ ์ค๋ช ํ๊ณ ์์ด์. ๊ฐ์ฒด๊ฐ ํ๋ฒ ์ฌ์ด๋ ํ ์ด๋ธ์ ๊ฐ์ง๊ฒ ๋๋ฉด ์ ๋ ์์ด๋ฒ๋ฆฌ์ง ์์ฃ . ์ค๋ ๋ ๊ฐ์ ๋ ์ด์ค ์ปจ๋์ ์ ๋ง๊ธฐ ์ํด์๋ผ๊ณ ํ๋ค์.
๐ Strong and unowned variables point at the object.
Weak variables point at the object's side table.
์ค์ํ ๋ฌธ์ฅ์ ์จ๋์๋๋ฐ์, ๊ฐํ ์ฐธ์กฐ ๋ณ์์ ๋ฏธ์์ ์ฐธ์กฐ ๋ณ์๋ ๊ฐ์ฒด๋ฅผ ์ง์ ์ฐธ์กฐํ๊ณ , ์ฝํ ์ฐธ์กฐ ๋ณ์๋ ๊ฐ์ฒด์ ์ฌ์ด๋ ํ ์ด๋ธ์ ์ฐธ์กฐํ๋ค๊ณ ํฉ๋๋ค.
๊ฐ์ฒด์ ์ฌ์ด๋ ํ ์ด๋ธ์ ๊ตฌํ์ ์๋์ ๊ฐ์ต๋๋ค.
HeapObject {
isa
InlineRefCounts {
atomic<InlineRefCountBits> {
strong RC + unowned RC + flags
OR
HeapObjectSideTableEntry*
}
}
}
HeapObjectSideTableEntry {
SideTableRefCounts {
object pointer
atomic<SideTableRefCountBits> {
strong RC + unowned RC + weak RC + flags
}
}
}
๊ฐ์ฅ ์ฒ์์ ์ฝ์๋ isa, side table entry, inline์ด ์ฌ๊ธฐ์ ๋ค ํด๊ฒฐ์ด ๋๋ค์! ๋จผ์ HeapObject๋ (isa๊ฐ ๋ฌด์จ ๋ฌธ๋ฒ์ธ์ง ๋ชจ๋ฅด๊ฒ ์ง๋ง) InlineRefCounts๋ฅผ ๊ฐ์ง๊ณ ์์ด์. ๊ทธ๋ฆฌ๊ณ ์ด ๋ด๋ถ์์๋ ๊ฐํ ์ฐธ์กฐ, ๋ฏธ์์ ์ฐธ์กฐ, ํ๋๊ทธ์ ํฉ์ด๋ HeapObjectSideTableEntry์ ๋ํ ํฌ์ธํฐ๋ฅผ ๊ฐ์ง๊ณ ์์ฃ .
์ฝํ ์ฐธ์กฐ๊ฐ ๋ฐ์ํ๋ฉด ๋ฌด์กฐ๊ฑด ์ฌ์ด๋ ํ ์ด๋ธ์ด ์์ฑ๋๋ ์ฝํ ์ฐธ์กฐ์ ๋ํ ์นด์ดํธ๋ ๊ณ ๋ คํ๊ณ ์์ง ์๋ ๊ฒ์ ์ ์ ์๋ค์.
์ฌ์ด๋ ํ ์ด๋ธ์ ๊ตฌํ์์๋ ์์ ์ ๊ฐ๋ฆฌํค๊ณ ์๋ ๊ฐ์ฒด์ ๋ํ ํฌ์ธํฐ์ ๊ฐํ ์ฐธ์กฐ, ๋ฏธ์์ ์ฐธ์กฐ, ์ฝํ ์ฐธ์กฐ, ๊ทธ๋ฆฌ๊ณ ํ๋๊ทธ์ ํฉ์ ๊ฐ์ง๊ณ ์์ต๋๋ค.
๊ฐ์ฒด์ ๋ผ์ดํ ์ฌ์ดํด
๐ LIVE without side table
The object is alive.
Object's refcounts are initialized as 1 strong, 1 unowned, 1 weak.
No side table.
No weak RC storage.
Strong variable operations work normally.
Unowned variable operations work normally.
Weak variable load can't happen.
Weak variable store adds the side table, becoming LIVE with side table.
When the strong RC reaches zero deinit() is called and the object becomes DEINITING.
๋จผ์ ์ฌ์ด๋ ํ ์ด๋ธ ์์ด ๊ฐ์ฒด๊ฐ ์กด์ฌํ๋ ๊ฒฝ์ฐ์ ๋๋ค. ๊ฐ์ฒด๋ ๊ฐํ ์ฐธ์กฐ 1, ๋ฏธ์์ ์ฐธ์กฐ 1, ์ฝํ ์ฐธ์กฐ 1์ ๊ฐ์ง๊ณ ์์ํฉ๋๋ค.
์ด๊ฑด ์๊น ์์์ ์ ๋ฆฌํ๋ ๋๋ก์ธ๋ฐ์, ๊ฐ์ฒด๋ฅผ ์์ฑํ ๋ initializer์ ์ํด ๊ฐํ ์ฐธ์กฐ๊ฐ 1 ์ฆ๊ฐํ๊ณ , ๋ฏธ์์ ์ฐธ์กฐ ์นด์ดํธ๋ ๊ฐํ ์ฐธ์กฐ ์นด์ดํธ์ ๋ํด 1์ ์ถ๊ฐ์ ์ผ๋ก ๊ฐ์ง๋๊น 0 -> 1 ์ด ๋๊ณ , weak์ unowned์ ๋ํด 1์ ์ถ๊ฐ์ ์ผ๋ก ๊ฐ์ง๊ธฐ ๋๋ฌธ์ 0 -> 1์ด ๋ฉ๋๋ค. ๊ฒฐ๊ณผ์ ์ผ๋ก ์ฒ์ ์์๋๋ฉด ๋ชจ๋ ์ฐธ์กฐ ์นด์ดํธ๊ฐ 1์ด ๋๋ ๊ฒ์ด์ฃ .
์ฌ์ด๋ ํ ์ด๋ธ์ ์กด์ฌํ์ง ์๊ณ , ์ฌ์ด๋ ํ ์ด๋ธ์ด ์์ผ๋๊น ์ฝํ ์ฐธ์กฐ๋ฅผ ์ํ ์ ์ฅ๊ณต๊ฐ๋ ์๊ฒ ์ฃ . ๋ง์ฝ ์ฝํ ์ฐธ์กฐ๊ฐ ๋ฐ์ํ๋ฉด ์ด ๊ฐ์ฒด์ ์ํ๋ LIVE with side table๋ก ๋ณ๊ฒฝ๋ฉ๋๋ค.
๊ทธ๋ฆฌ๊ณ ๊ฐํ ์ฐธ์กฐ ์นด์ดํธ๊ฐ 0์ด ๋๋ฉด, deinit์ด ํธ์ถ๋๊ณ ๊ฐ์ฒด์ ์ํ๋ DEINITIING์ด ๋ฉ๋๋ค.
๐ LIVE with side table
Weak variable operations work normally.
Everything else is the same as LIVE.
์ฌ์ด๋ ํ ์ด๋ธ์ ๊ฐ์ง๊ณ LIVE ์ํ์ผ ๋๋ weak ๋ณ์์ ๋ํ ์ฒ๋ฆฌ๊ฐ ๋ฐ์ํ๋ค๋ ๊ฒ ์ธ์๋ ๋ชจ๋ ์ฌ์ด๋ ํ ์ด๋ธ์ด ์์ ๋์ ๋์ผํ์ฃ .
๐ DEINITING without side table
deinit() is in progress on the object.
Strong variable operations have no effect.
Unowned variable load halts in swift_abortRetainUnowned().
Unowned variable store works normally.
Weak variable load can't happen.
Weak variable store stores nil.
When deinit() completes, the generated code calls swift_deallocObject.
swift_deallocObject calls canBeFreedNow() checking for the fast path of no weak or unowned references.
If canBeFreedNow() the object is freed and it becomes DEAD.
Otherwise, it decrements the unowned RC and the object becomes DEINITED.
์๊น ๊ฐํ ์ฐธ์กฐ ์นด์ดํธ๊ฐ 0์ด๋๋ฉด DEINITING ์ํ๋ก ๋ฐ๋๋ค๊ณ ์ ๋ฆฌํ์๋๋ฐ์, ์ด๋ ์ผ์ด๋๋ ์ผ๋ค์ ์ ๋ฆฌํด๋ด ์๋ค.
๋จผ์ deinit์ด ํธ์ถ๋์ด์ ๊ฐ์ฒด์ ๋ํ ์๋ฉธ์ด ์์๋๊ฒ ์ฃ . ์ด๋, ๊ฐํ ์ฐธ์กฐ๋ฅผ ํ๊ณ ์๋ ๋ณ์๋ ์๋ฌด ์ํฅ์ ๋ฐ์ง ์์ต๋๋ค.
๋ฏธ์์ ์ฐธ์กฐ๋ฅผ ํ๊ณ ์๋ ๋ณ์๋ ๋ฐ์ดํฐ๋ฅผ ์ฝ์ ๋ swift_abortRetainUnowned()์ ์ํด ๋๋ ์ด(์ด ํจ์์ ๋ชฉ์ ์ด ์ ์ดํด๋ ์๋๋ค์ใ )๋๊ณ , ์ ์ฅํ ๋๋ ์ํฅ์ ๋ฐ์ง ์์ต๋๋ค.
์ฌ์ด๋ ํ ์ด๋ธ์ด ์๊ธฐ ๋๋ฌธ์ ์ฝํ ์ฐธ์กฐ๊ฐ ์๋ ๊ฒฝ์ฐ๋ ๋ฐ์ํ์ง ์๊ณ , ์ฝํ ์ฐธ์กฐ ๋ณ์์ ๊ฐ์ฒด๋ฅผ ์ ์ฅํ๋ฉด nil์ด ์ ์ฅ๋ฉ๋๋ค.
deinit์ด ์๋ฃ๋๋ฉด swift_deallocObject๊ฐ ํธ์ถ๋๋ฉด์ ์ฝํ ์ฐธ์กฐ๋ ๋ฏธ์์ ์ฐธ์กฐ๊ฐ ์กด์ฌํ๋์ง ํ์ธํฉ๋๋ค. ์ด๋ฅผ ์ํด ํธ์ถํ๋ ํจ์๊ฐ canBeFreedNow()์ด๊ณ , ๋ค๋ฅธ ์ฐธ์กฐ๊ฐ ์กด์ฌํ์ง ์๋๋ค๋ฉด ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๋น์ฐ๊ณ ๊ฐ์ฒด์ ์ํ๋ DEAD๊ฐ ๋ฉ๋๋ค.
๋ง์ฝ ๋ค๋ฅธ ์ฐธ์กฐ๊ฐ ์กด์ฌํ๋ค๋ฉด ๋ฏธ์์ ์ฐธ์กฐ ์นด์ดํธ๋ฅผ ํ๋ ์ค์ด๊ณ DEINITED ์ํ๋ก ๋ฐ๋๊ฒ ๋์ฃ . ๋ฏธ์์ ์ฐธ์กฐ ์นด์ดํธ๊ฐ ์ค์ด๋๋ ์ด์ ๋ ์์์ ๋์์์ฃ ? deinit์ด ์๋ฃ๋์๊ธฐ ๋๋ฌธ์ ๋ฏธ์์ ์ฐธ์กฐ์ ์นด์ดํธ๊ฐ ํ๋ ์ค์ด๋ค๊ฒ ๋์์ต๋๋ค.
๐ DEINITING with side table
Weak variable load returns nil.
Weak variable store stores nil.
canBeFreedNow() is always false, so it never transitions directly to DEAD.
Everything else is the same as DEINITING.
์ฌ์ด๋ ํ ์ด๋ธ์ด ์กด์ฌํ๋ ๊ฒฝ์ฐ์๋ ์ฝํ ์ฐธ์กฐ๋ฅผ ํ๋ ๋ณ์์ ๊ฐ์ฒด๋ฅผ ์ ์ฅํ๊ฑฐ๋, ๋ถ๋ฌ์ฌ ๋ ๋ชจ๋ nil์ ๋ฐ๊ฒ ๋ฉ๋๋ค. ์ฌ์ด๋ ํ ์ด๋ธ์ด ์๋ค๋ ๊ฒ์ ํญ์ ์ถ๊ฐ์ ์ธ weak ์นด์ดํธ๊ฐ ์๋ค๋ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ canBeFreedNow()์์๋ ํญ์ false๊ฐ ๋ฐํ๋๊ณ DEINITING์ผ๋ก ์ํ๊ฐ ๋ฐ๋๊ฒ ๋ฉ๋๋ค.
๐ DEINITED without side table
deinit() has completed but there are unowned references outstanding.
Strong variable operations can't happen.
Unowned variable store can't happen.
Unowned variable load halts in swift_abortRetainUnowned().
Weak variable operations can't happen.
When the unowned RC reaches zero, the object is freed and it becomes DEAD.
์ฌ์ด๋ ํ ์ด๋ธ์ด ์๋ DENITED ์ํ์ ๋ํ ๋์์ ๋๋ค.
deinit์ ์๋ฃ๋์์ง๋ง unowned refence๋ ์์ง ์กด์ฌํ๋ ์ํ์ ๋๋ค. ์๋ํ๋ฉด ๋ฏธ์์ ์ฐธ์กฐ๊ฐ ์์๋ค๋ฉด ๊ณง๋ฐ๋ก DEAD ์ํ๊ฐ ๋์์ ๊ฒ์ด๊ณ , ์ฝํ ์ฐธ์กฐ๊ฐ ์๋ค๋ฉด ์ฌ์ด๋ ํ ์ด๋ธ์ด ์กด์ฌํ์ ํ ๋๊น์.
์ด๋ฏธ ๊ฐํ ์ฐธ์กฐ์ ์นด์ดํธ๋ 0์ด๊ธฐ ๋๋ฌธ์ ๊ฐํ ์ฐธ์กฐ์ ๋ํ ์ฐ์ฐ์ ๋ฐ์ํ์ง ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ๋ฏธ์์ ์ฐธ์กฐ ์นด์ดํธ๊ฐ 0์ด ๋๋ฉด ๊ฐ์ฒด๊ฐ ์์ ํ ํด์ ๋๊ณ ์ํ๊ฐ DEAD๋ก ๋ณ๊ฒฝ๋ฉ๋๋ค.
๐ FREED without side table
This state never happens.
์ฌ์ด๋ ํ ์ด๋ธ์ด ์์ผ๋ฉด์ FREED ์ํ๋ ์กด์ฌํ์ง ์์ ๊ฑฐ์์. ์ฝํ ์ฐธ์กฐ๊ฐ ์์ผ๋ฉด ๊ณง๋ฐ๋ก DEAD๊ฐ ๋๋๊น์.
๐ FREED with side table
The object is freed but there are weak refs to the side table outstanding.
Strong variable operations can't happen.
Unowned variable operations can't happen. Weak variable load returns nil.
Weak variable store can't happen.
When the weak RC reaches zero, the side table entry is freed and the object becomes DEAD.
FREED ์ํ๋ ๊ฐ์ฒด๋ ํด์ ๋์๋๋ฐ, ์ฌ์ ํ ์ฌ์ด๋ ํ ์ด๋ธ์ ์ฝํ ์ฐธ์กฐ ์นด์ดํธ๊ฐ ๋จ์์๋ ๊ฒฝ์ฐ์ ๋๋ค. ์ด๋ ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ๊ฒ ๋๋ฉด nil์ ๋ฐํ๋ฐ๊ฒ ๋์ฃ .
์ฝํ ์ฐธ์กฐ์ ์นด์ดํธ๊ฐ 0์ด ๋๋ฉด ์ด๋๋ ๋ชจ๋ ์ฐธ์กฐ ์นด์ดํธ๊ฐ 0์ด ๋๊ฒ ์ฃ ? ์ด ์์ ์ ์ฌ์ด๋ ํ ์ด๋ธ ์ํธ๋ฆฌ๊ฐ ๋ฉ๋ชจ๋ฆฌ์์ ํด์ ๋๊ณ ๊ฐ์ฒด๋ DEAD์ํ๊ฐ ๋ฉ๋๋ค.
์ฌ์ดํด ์ ๋ฆฌ
ํน์ ๋ชฐ๋ผ์ ์ฐพ์๋ดค๋๋ฐ ๋ฏธ๋์์ ๋ค๋ฅธ ๋ถ์ด ๋ง๋ค์ด๋์ ์ํ ๋จธ์ ๊ทธ๋ฆผ์ด ์๋๋ผ๊ตฌ์. ์ด๊ฑธ ๋ณด๋๊น ํจ์ฌ ์ฝ๊ฒ ์ดํด๋๋ ๊ฒ ๊ฐ์ต๋๋ค!
์ ๋ฆฌ, ๋ง๋ฌด๋ฆฌ
weak, unowned, strong์ ๋จ์ํ ๋ํผ๋ฐ์ค ์นด์ดํธ๋ฅผ ์ฌ๋ฆฐ๋ค ์ ์ฌ๋ฆฐ๋ค, ์ต์ ๋์ด๋ค ์๋๋ค์ ์ฐจ์ด๊ฐ ์๋์์ด์. ์ฌ์ค ๋ด๋ถ์ ์ผ๋ก๋ ๋ชจ๋ ์ข ๋ฅ์ ๋ํ ์นด์ดํธ๋ฅผ ๋ค ์ธ์ด์ฃผ๊ณ ์์์ฃ .
๊ฐํ ์ฐธ์กฐ๊ฐ 0์ด ๋๋ฉด ๊ฐ์ฒด๋ deinit ๋์ง๋ง ์ฌ์ ํ ๋ฉ๋ชจ๋ฆฌ์ ๋จ์์์๊ณ , ์ด๋ ๋ฏธ์์ ์ฐธ์กฐ๋ ์ฝํ ์ฐธ์กฐ ์ฌ๋ถ์ ๋ฐ๋ผ ์ํ๊ฐ ๊ฒฐ์ ์ด ๋ฉ๋๋ค. ๋ฏธ์์ ์ฐธ์กฐ๊ฐ ๋จ์์๋ค๋ฉด DEINITED ์ํ๊ฐ ๋์ด์ ๋ฉ๋ชจ๋ฆฌ์์ ํด์ ๋์ง ์๊ณ , ๋ฏธ์์ ์ฐธ์กฐ ์นด์ดํธ๊ฐ 0์ด ๋์ด๋ ์ฝํ ์ฐธ์กฐ ์นด์ดํธ๊ฐ ๋จ์์๋ค๋ฉด FREED ์ํ๊ฐ ๋์ด์ ์์ง ์ฌ์ด๋ ํ ์ด๋ธ์ด ๋ฉ๋ชจ๋ฆฌ์ ๋จ์์๊ฒ ๋์ฃ .
์ด์ ๋๊ตฐ๊ฐ weak์ด๋ unowned๊ฐ ๋ฌด์จ ์ฐจ์ด๋๊ณ ๋ฌผ์ด๋ณด๋ฉด ๋ฉ์ง๊ฒ ์ฌ์ด๋ ํ ์ด๋ธ๊ณผ ๋ํผ๋ฐ์ค ์นด์ดํธ ์ด์ผ๊ธฐ๋ฅผ ํด์ฃผ๋ ๊ฒ์ ์ด๋จ๊น์?
์ค๋๋ ์ฝ์ด์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค~!
'๐ ์์ด-์ค-์์ค > ๐ค ์ค์ํํธ' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Swift-WWDC21] ARC in Swift: Basics and beyond (0) | 2022.01.06 |
---|---|
[Swift] Method Dispatch ๋ฐํ์๋ฃ (2) | 2021.12.28 |
[Swift] Method Dispatch (3): Dynamic Dispatch๋ฅผ ์ค์ฌ๋ณด์ (0) | 2021.12.26 |
[Swift] Method Dispatch (2): ๋ ๋ณต์กํ ์ํฉ์ Method Dispatch (0) | 2021.12.26 |
[Swift] Method Dispatch (1): Static Dispatch vs. Dynamic Dispatch (1) | 2021.12.26 |
๋๊ธ
์ด ๊ธ ๊ณต์ ํ๊ธฐ
-
๊ตฌ๋
ํ๊ธฐ
๊ตฌ๋ ํ๊ธฐ
-
์นด์นด์คํก
์นด์นด์คํก
-
๋ผ์ธ
๋ผ์ธ
-
ํธ์ํฐ
ํธ์ํฐ
-
Facebook
Facebook
-
์นด์นด์ค์คํ ๋ฆฌ
์นด์นด์ค์คํ ๋ฆฌ
-
๋ฐด๋
๋ฐด๋
-
๋ค์ด๋ฒ ๋ธ๋ก๊ทธ
๋ค์ด๋ฒ ๋ธ๋ก๊ทธ
-
Pocket
Pocket
-
Evernote
Evernote