package mem type Mem struct { cells []cell free []Ptr } func New() Mem { cells := make([]cell, 1) // Reserve NullPtr cells[NullPtr].kind = CellKindForbidden return Mem{ cells: cells, free: make([]Ptr, 0), } } func (m *Mem) Allocate(kind CellKind) (Ptr, error) { if len(m.free) > 0 { idx := m.free[len(m.free)-1] m.free = m.free[:len(m.free)-1] if m.cells[idx].kind != CellKindEmpty { return NullPtr, ErrFatalNonFreeCell } m.cells[idx].kind = kind return Ptr(idx), nil } else { if len(m.cells) > 10000 { return NullPtr, ErrMemOverflow } idx := len(m.cells) m.cells = append(m.cells, cell{kind: kind, refs: 1}) return Ptr(idx), nil } } func (m *Mem) Set(ptr Ptr, v CellData) error { if err := m.validPtr(ptr); err != nil { return err } m.cells[ptr].data = v return nil } func (m *Mem) Get(ptr Ptr) (CellData, error) { if err := m.validPtr(ptr); err != nil { return nil, err } return m.cells[ptr].data, nil } func (m *Mem) Is(ptr Ptr, kind CellKind) bool { if ptr >= Ptr(len(m.cells)) { return false } return m.cells[ptr].kind == kind } func (m *Mem) Kind(ptr Ptr) CellKind { if ptr >= Ptr(len(m.cells)) { return CellKindForbidden } return m.cells[ptr].kind } func (m *Mem) Retain(ptr Ptr) error { if err := m.validPtr(ptr); err != nil { return err } m.cells[ptr].refs++ return nil } func (m *Mem) Release(ptr Ptr) error { if err := m.validPtr(ptr); err != nil { return err } m.cells[ptr].refs-- if m.cells[ptr].refs == 0 { c := m.cells[ptr].data c.DropCell(m) m.cells[ptr] = cell{} m.free = append(m.free, ptr) } return nil } func (m *Mem) validPtr(ptr Ptr) error { if ptr >= Ptr(len(m.cells)) { return ErrInvalidMemAccess{ptr} } kind := m.cells[ptr].kind if kind == CellKindForbidden || kind == CellKindEmpty { return ErrInvalidMemAccess{ptr} } return nil }