๊ธ€ ์ž‘์„ฑ์ž: ๊ฐœ๋ฐœํ•˜๋Š” ํ›ˆ์ด

๋ž˜ํผ๋Ÿฐ์Šค ์นด์šดํŠธ

์•ˆ๋…•ํ•˜์„ธ์š”! ์˜ค๋Š˜์€ swift์—์„œ ๋ž˜ํผ๋Ÿฐ์Šค ์นด์šดํŠธ๋ฅผ ์–ด๋–ป๊ฒŒ ๊ตฌํ˜„ํ•˜๊ณ  ์žˆ๋Š”์ง€ ์•Œ์•„๋ณด๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ๋งŽ์€ ๋ธ”๋กœ๊ทธ์—์„œ weak๊ณผ unowned์˜ ์ฐจ์ด๋ฅผ Optional์˜ ๊ฐ€๋Šฅ ์—ฌ๋ถ€๋ผ๊ณ  ๋งํ•˜๊ณ  ์žˆ๋Š”๋ฐ, ์‚ฌ์‹ค ํ‹€๋ฆฐ ํ‘œํ˜„์ด์—์š”. Swift 5.0๋ถ€ํ„ฐ๋Š” Unowned Optional์ด ์ถ”๊ฐ€๋˜์–ด์„œ unowned๋„ ์˜ต์…”๋„์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

๊ทธ๋ž˜์„œ ๋” ๋กœ์šฐ ๋ ˆ๋ฒจ๋กœ ๊ฐ€๋ฉด ๋ž˜ํผ๋Ÿฐ์Šค ์นด์šดํŒ…๊ณผ ๋ฉ”๋ชจ๋ฆฌ ํ•ด์ œ์— ์žˆ์–ด์„œ ๋ถ„๋ช… ๋‹ค๋ฅธ ๋ถ€๋ถ„์ด ์žˆ์„ ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ–ˆ๊ณ , 

 

GitHub - apple/swift: The Swift Programming Language

The Swift Programming Language. Contribute to apple/swift development by creating an account on GitHub.

github.com

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์ƒํƒœ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.

 

์‚ฌ์ดํด ์ •๋ฆฌ

https://shubhamchawla00.medium.com/memory-management-on-ios-ad2244b49b20

ํ˜น์‹œ ๋ชฐ๋ผ์„œ ์ฐพ์•„๋ดค๋Š”๋ฐ ๋ฏธ๋””์—„์— ๋‹ค๋ฅธ ๋ถ„์ด ๋งŒ๋“ค์–ด๋‘์‹  ์ƒํƒœ ๋จธ์‹  ๊ทธ๋ฆผ์ด ์žˆ๋”๋ผ๊ตฌ์š”. ์ด๊ฑธ ๋ณด๋‹ˆ๊นŒ ํ›จ์”ฌ ์‰ฝ๊ฒŒ ์ดํ•ด๋˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค! 

 

์ •๋ฆฌ, ๋งˆ๋ฌด๋ฆฌ

weak, unowned, strong์€ ๋‹จ์ˆœํžˆ ๋ž˜ํผ๋Ÿฐ์Šค ์นด์šดํŠธ๋ฅผ ์˜ฌ๋ฆฐ๋‹ค ์•ˆ ์˜ฌ๋ฆฐ๋‹ค, ์˜ต์…”๋„์ด๋‹ค ์•„๋‹ˆ๋‹ค์˜ ์ฐจ์ด๊ฐ€ ์•„๋‹ˆ์—ˆ์–ด์š”. ์‚ฌ์‹ค ๋‚ด๋ถ€์ ์œผ๋กœ๋Š” ๋ชจ๋“  ์ข…๋ฅ˜์— ๋Œ€ํ•œ ์นด์šดํŠธ๋ฅผ ๋‹ค ์„ธ์–ด์ฃผ๊ณ  ์žˆ์—ˆ์ฃ . 

 

๊ฐ•ํ•œ ์ฐธ์กฐ๊ฐ€ 0์ด ๋˜๋ฉด ๊ฐ์ฒด๋Š” deinit ๋˜์ง€๋งŒ ์—ฌ์ „ํžˆ ๋ฉ”๋ชจ๋ฆฌ์— ๋‚จ์•„์žˆ์—ˆ๊ณ , ์ด๋•Œ ๋ฏธ์†Œ์œ  ์ฐธ์กฐ๋‚˜ ์•ฝํ•œ ์ฐธ์กฐ ์—ฌ๋ถ€์— ๋”ฐ๋ผ ์ƒํƒœ๊ฐ€ ๊ฒฐ์ •์ด ๋ฉ๋‹ˆ๋‹ค. ๋ฏธ์†Œ์œ  ์ฐธ์กฐ๊ฐ€ ๋‚จ์•„์žˆ๋‹ค๋ฉด DEINITED ์ƒํƒœ๊ฐ€ ๋˜์–ด์„œ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ํ•ด์ œ๋˜์ง€ ์•Š๊ณ , ๋ฏธ์†Œ์œ  ์ฐธ์กฐ ์นด์šดํŠธ๊ฐ€ 0์ด ๋˜์–ด๋„ ์•ฝํ•œ ์ฐธ์กฐ ์นด์šดํŠธ๊ฐ€ ๋‚จ์•„์žˆ๋‹ค๋ฉด FREED ์ƒํƒœ๊ฐ€ ๋˜์–ด์„œ ์•„์ง ์‚ฌ์ด๋“œ ํ…Œ์ด๋ธ”์ด ๋ฉ”๋ชจ๋ฆฌ์— ๋‚จ์•„์žˆ๊ฒŒ ๋˜์ฃ .

 

์ด์ œ ๋ˆ„๊ตฐ๊ฐ€ weak์ด๋ž‘ unowned๊ฐ€ ๋ฌด์Šจ ์ฐจ์ด๋ƒ๊ณ  ๋ฌผ์–ด๋ณด๋ฉด ๋ฉ‹์ง€๊ฒŒ ์‚ฌ์ด๋“œ ํ…Œ์ด๋ธ”๊ณผ ๋ž˜ํผ๋Ÿฐ์Šค ์นด์šดํŠธ ์ด์•ผ๊ธฐ๋ฅผ ํ•ด์ฃผ๋Š” ๊ฒƒ์€ ์–ด๋–จ๊นŒ์š”?

 

์˜ค๋Š˜๋„ ์ฝ์–ด์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค~!