diff --git a/sketching/september_2025/dll_rc/dll_rc.dm b/sketching/september_2025/dll_rc/dll_rc.dm new file mode 100644 index 0000000..7bff613 --- /dev/null +++ b/sketching/september_2025/dll_rc/dll_rc.dm @@ -0,0 +1,81 @@ +pub class Rc : Drop, Copy + + class Inner(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 count is 1 + let game = ChessGame(board) // Rc copied, count is 2 + let player = ChessPlayer(board) // Rc copied, count is 3 + (game, player) // initial Rc dropped before fn return, count now 2 +end + +fn playChess() + let (game, player) = getGameAndPlayer() + // Rc 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 \ No newline at end of file