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 | 
