| 603 | |
| 604 | template <typename T> |
| 605 | struct ZRef { |
| 606 | private: |
| 607 | struct RefCounted { |
| 608 | internals::refcount_t rc; |
| 609 | #if __cplusplus >= 201100 |
| 610 | alignas(T) |
| 611 | #endif |
| 612 | char data[sizeof(T)]; |
| 613 | RefCounted() : rc(1) { |
| 614 | } |
| 615 | }; |
| 616 | internals::vaddr_t vaddr; |
| 617 | internals::refcount_t &refcount() { |
| 618 | return ((RefCounted *) (internals::vmem.to_ptr(vaddr)))->rc; |
| 619 | } |
| 620 | void *to_ptr() { |
| 621 | return &(((RefCounted *) (internals::vmem.to_ptr(vaddr)))->data); |
| 622 | } |
| 623 | |
| 624 | public: |
| 625 | ZRef() : vaddr(internals::VADDR_NULL) { |
| 626 | } |
| 627 | ZRef(internals::vaddr_t vaddr) : vaddr(vaddr) { |
| 628 | } |
| 629 | operator bool() { |
| 630 | return vaddr != internals::VADDR_NULL; |
| 631 | } |
| 632 | bool is_null() { |
| 633 | return vaddr == internals::VADDR_NULL; |
| 634 | } |
| 635 | ZRef(void *ptr) { |
| 636 | vaddr = internals::allocated_ptr_to_vaddr(ptr); |
| 637 | } |
| 638 | T *as_ptr() const { |
| 639 | return (T *) to_ptr(); |
| 640 | } |
| 641 | T &as_ref() const { |
| 642 | return *(T *) to_ptr(); |
| 643 | } |
| 644 | T &operator*() const { |
| 645 | return *(T *) to_ptr(); |
| 646 | } |
| 647 | T *operator->() { |
| 648 | return (T *) to_ptr(); |
| 649 | } |
| 650 | ZRef<T> &operator=(ZRef<T> other) { |
| 651 | vaddr = other.vaddr; |
| 652 | } |
| 653 | template <typename U> |
| 654 | ZRef<U> cast() const { |
| 655 | return ZRef<U>(vaddr); |
| 656 | } |
| 657 | void retain() { |
| 658 | refcount().inc(vaddr); |
| 659 | } |
| 660 | void release() { |
| 661 | if (refcount().dec(vaddr) == 0) { |
| 662 | as_ref().~T(); |