
메모리 관리
메모리 관리에서는 타입 이름에 @ref를 붙이면 구조체가 힙에 초기화된다. vector 바인딩의 타입은 mut ref Vector3이며, MutRef<Vector3>로도 쓸 수 있다. 이런 참조는 포인터 연산을 지원하지 않는 포인터와 본질적으로 같다.
let vector @owner = Vector3@ref 1 3 8
@owner 속성은 바인딩의 범위가 끝나기 전에 메모리를 해제한다. @[owner function]은 바인딩을 포함하는 함수가 반환되기 전에 메모리를 해제한다.
객체
객체에는 기본적으로 자동 참조 카운팅(reference counting)이 적용된다.
type App =
val name : String
let app = App "Editor"
@mrc 한정자를 사용하면 객체가 수동 참조 카운팅으로 전환된다. 참조 카운트는 kd/retain과 kd/release 함수로 관리한다.
let app = App@mrc "Editor"
kd/retain app
kd/release app
@ref를 붙이면 app은 힙에 있는 객체를 참조한다. 이 객체는 kd/free 함수로 직접 해제해야 한다.
let app = App@ref "Editor"
kd/free app
app 바인딩의 타입이 mem App이면 객체의 메모리를 담는다. app에 접근하면 App 타입의 참조를 반환한다. 복사하려면 @copy 한정자를 붙여야 한다.
let app = App@mem "Editor"
let app_ref = app
let app_copy = app@copy
create 함수가 mem App을 반환하더라도, app 바인딩은 힙에 할당된 참조 카운팅 방식의 App 객체를 가리킨다.
def create = App@mem "Editor"
let app = create@arc
@mem을 기본 옵션으로 지정하면 App에서 참조 카운팅을 사용할 수 없다. 다만 @ref는 계속 사용할 수 있다.
type App @mem =
val name : String
let app = App@ref "Editor"
복사·이동 의미론을 위한 통합 코드
복사·이동 의미론을 위한 통합 코드에서는 List<mem T>를 다음과 같이 정의한다.
type List<mem T> =
var size : u32 = 0
let mut array = Array<mem T> 0
fun get (i : u32) = array[i]
def index_of (x : T) =
for i = 0 until size do
if array[i] == x then return i
fail "no such item"
def add (x : mem T) =
if size == array.size then
set_array_size (if size == 0 then 4 else size * 2)
kd/retain x
array[size] = x@move
size += 1
def remove_at (index : u32) =
kd/clear array[index]
if size > 1 then
for i = index to size - 2 do
array[i] = array[i + 1]@move
size -= 1
def remove (x : T) =
let index = index_of x
remove_at index
mem T는 참조 타입에서 객체의 메모리를 나타낸다. 값 타입에서는 타입 자체와 같아 mem T == T가 되며, 이때 @copy와 @move 연산은 아무 작업도 하지 않는다.
kd/clear 함수는 mem 타입을 파괴하고 참조 카운팅 객체의 참조 카운트를 줄인다.
댓글 (0)
로그인하면 이 기사에 내 생각을 남길 수 있어요