/* could be non-null instead of raw pointer? */
typedef atomic_rc [t any] {
	count *usize;
	data *t;
}

/* macros must be 'called' with () */
pub define arc(t) { struct (atomic_rc[t]) };

pub dereference(a *arc) *#a.data
{
	return a.t;
}

pub init(mut a *arc, e #a.data)
{
	new(a.count, 0);
	a.data = e;
}

pub init(mut a *arc, b *arc<#a.data>)
{
	copy(a, b);
}

pub deinit(mut a *arc)
{
	if atomic_fetch_add(a.count, -1) == 1 {
		dealloc(a.data);
		dealloc(a.count);
	}

	a.count = null;
	a.data = null;
}

pub copy(mut a *arc, b *arc<#a.data>)
{
	deinit(a);
	a.count = b.count;
	a.data = b.data;
	atomic_fetch_add(b.count, 1);
}

pub move(mut a *arc, mut b *arc<#a.data>)
{
	deinit(a);
	a.count = b.count;
	a.data = b.data;
	/* reference count stays the same */
	b.count = null;
	a.count = null;
}
