81 lines
		
	
	
		
			1.7 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			81 lines
		
	
	
		
			1.7 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
pub class Rc<T> : Drop, Copy
 | 
						|
 | 
						|
    class Inner<T>(t: T)
 | 
						|
        mut count = 1
 | 
						|
    end
 | 
						|
 | 
						|
    inner: &weak Inner = Null
 | 
						|
 | 
						|
    pub ctor(t: T)
 | 
						|
        inner = Inner(t)
 | 
						|
    end
 | 
						|
 | 
						|
    ctor(parent: &Self)
 | 
						|
        parent.inner++
 | 
						|
        inner = &weak parent.inner
 | 
						|
    end
 | 
						|
 | 
						|
    pub fn copy() -> Self
 | 
						|
        Self(self)
 | 
						|
    end
 | 
						|
 | 
						|
    impl fn drop(self)
 | 
						|
        if inner.upgrade() is Some(inner) then
 | 
						|
            inner.count--
 | 
						|
            if inner.count == 0 then
 | 
						|
                drop inner
 | 
						|
            end
 | 
						|
        else
 | 
						|
            throw Exception('rc.inner could not be converted from a weak reference')
 | 
						|
        end
 | 
						|
    end
 | 
						|
 | 
						|
end
 | 
						|
 | 
						|
class Game(player: Player) end
 | 
						|
 | 
						|
class Player
 | 
						|
    pub mut game: &weak Game = Null
 | 
						|
end
 | 
						|
 | 
						|
fn circular()
 | 
						|
    let player = Player()
 | 
						|
    let game = Game(player)
 | 
						|
 | 
						|
    expectThrows(EmptyWeakReferenceException) {
 | 
						|
        player.game.upgrade()
 | 
						|
    }
 | 
						|
 | 
						|
    player.game = &weak game
 | 
						|
 | 
						|
    expectDoesNotThrow {
 | 
						|
        player.game.upgrade()
 | 
						|
    }
 | 
						|
end
 | 
						|
 | 
						|
class Board
 | 
						|
    pub fn flip()
 | 
						|
        println 'Flipped!'
 | 
						|
    end
 | 
						|
end
 | 
						|
 | 
						|
class ChessGame(pub board: rc Board) end
 | 
						|
 | 
						|
class ChessPlayer(pub board: rc Board) end
 | 
						|
 | 
						|
fn getGameAndPlayer() -> (ChessGame, ChessPlayer)
 | 
						|
    let board = rc Board() // Rc<Board> count is 1
 | 
						|
    let game = ChessGame(board) // Rc<Board> copied, count is 2
 | 
						|
    let player = ChessPlayer(board) // Rc<Board> copied, count is 3
 | 
						|
    (game, player) // initial Rc<Board> dropped before fn return, count now 2
 | 
						|
end
 | 
						|
 | 
						|
fn playChess()
 | 
						|
    let (game, player) = getGameAndPlayer()
 | 
						|
    // Rc<Board> count is 2
 | 
						|
    let board = game.board // Copy, so count is now 3
 | 
						|
    board.flip()
 | 
						|
    drop board // count now 2
 | 
						|
    drop game // count now 1
 | 
						|
    drop player // count now 0, board memory finally dropped
 | 
						|
end |