gctest.nim 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. discard """
  2. outputsub: "finished"
  3. """
  4. # Test the garbage collector.
  5. import
  6. strutils
  7. type
  8. PNode = ref TNode
  9. TNode {.final.} = object
  10. le, ri: PNode
  11. data: string
  12. TTable {.final.} = object
  13. counter, max: int
  14. data: seq[string]
  15. TBNode {.final.} = object
  16. other: PNode # a completely different tree
  17. data: string
  18. sons: seq[TBNode] # directly embedded!
  19. t: TTable
  20. TCaseKind = enum nkStr, nkWhole, nkList
  21. PCaseNode = ref TCaseNode
  22. TCaseNode {.final.} = object
  23. case kind: TCaseKind
  24. of nkStr: data: string
  25. of nkList: sons: seq[PCaseNode]
  26. else: unused: seq[string]
  27. TIdObj* = object of TObject
  28. id*: int # unique id; use this for comparisons and not the pointers
  29. PIdObj* = ref TIdObj
  30. PIdent* = ref TIdent
  31. TIdent*{.acyclic.} = object of TIdObj
  32. s*: string
  33. next*: PIdent # for hash-table chaining
  34. h*: int # hash value of s
  35. var
  36. flip: int
  37. proc newCaseNode(data: string): PCaseNode =
  38. new(result)
  39. if flip == 0:
  40. result.kind = nkStr
  41. result.data = data
  42. else:
  43. result.kind = nkWhole
  44. result.unused = @["", "abc", "abdc"]
  45. flip = 1 - flip
  46. proc newCaseNode(a, b: PCaseNode): PCaseNode =
  47. new(result)
  48. result.kind = nkList
  49. result.sons = @[a, b]
  50. proc caseTree(lvl: int = 0): PCaseNode =
  51. if lvl == 3: result = newCaseNode("data item")
  52. else: result = newCaseNode(caseTree(lvl+1), caseTree(lvl+1))
  53. proc finalizeNode(n: PNode) =
  54. assert(n != nil)
  55. write(stdout, "finalizing: ")
  56. if isNil(n.data): writeLine(stdout, "nil!")
  57. else: writeLine(stdout, "not nil")
  58. var
  59. id: int = 1
  60. proc buildTree(depth = 1): PNode =
  61. if depth == 7: return nil
  62. new(result, finalizeNode)
  63. result.le = buildTree(depth+1)
  64. result.ri = buildTree(depth+1)
  65. result.data = $id
  66. inc(id)
  67. proc returnTree(): PNode =
  68. writeLine(stdout, "creating id: " & $id)
  69. new(result, finalizeNode)
  70. result.data = $id
  71. new(result.le, finalizeNode)
  72. result.le.data = $id & ".1"
  73. new(result.ri, finalizeNode)
  74. result.ri.data = $id & ".2"
  75. inc(id)
  76. # now create a cycle:
  77. writeLine(stdout, "creating id (cyclic): " & $id)
  78. var cycle: PNode
  79. new(cycle, finalizeNode)
  80. cycle.data = $id
  81. cycle.le = cycle
  82. cycle.ri = cycle
  83. inc(id)
  84. #writeLine(stdout, "refcount: " & $refcount(cycle))
  85. #writeLine(stdout, "refcount le: " & $refcount(cycle.le))
  86. #writeLine(stdout, "refcount ri: " & $refcount(cycle.ri))
  87. proc printTree(t: PNode) =
  88. if t == nil: return
  89. writeLine(stdout, "printing")
  90. writeLine(stdout, t.data)
  91. printTree(t.le)
  92. printTree(t.ri)
  93. proc unsureNew(result: var PNode) =
  94. writeLine(stdout, "creating unsure id: " & $id)
  95. new(result, finalizeNode)
  96. result.data = $id
  97. new(result.le, finalizeNode)
  98. result.le.data = $id & ".a"
  99. new(result.ri, finalizeNode)
  100. result.ri.data = $id & ".b"
  101. inc(id)
  102. proc setSons(n: var TBNode) =
  103. n.sons = @[] # free memory of the sons
  104. n.t.data = @[]
  105. var
  106. m: seq[string]
  107. m = @[]
  108. setLen(m, len(n.t.data) * 2)
  109. for i in 0..high(m):
  110. m[i] = "..."
  111. n.t.data = m
  112. proc buildBTree(father: var TBNode) =
  113. father.data = "father"
  114. father.other = nil
  115. father.sons = @[]
  116. for i in 1..10:
  117. write(stdout, "next iteration!\n")
  118. var n: TBNode
  119. n.other = returnTree()
  120. n.data = "B node: " & $i
  121. if i mod 2 == 0: n.sons = @[] # nil and [] need to be handled correctly!
  122. add father.sons, n
  123. father.t.counter = 0
  124. father.t.max = 3
  125. father.t.data = @["ha", "lets", "stress", "it"]
  126. setSons(father)
  127. proc getIdent(identifier: cstring, length: int, h: int): PIdent =
  128. new(result)
  129. result.h = h
  130. result.s = newString(length)
  131. proc main() =
  132. discard getIdent("addr", 4, 0)
  133. discard getIdent("hall", 4, 0)
  134. discard getIdent("echo", 4, 0)
  135. discard getIdent("huch", 4, 0)
  136. var
  137. father: TBNode
  138. for i in 1..1_00:
  139. buildBTree(father)
  140. for i in 1..1_00:
  141. var t = returnTree()
  142. var t2: PNode
  143. unsureNew(t2)
  144. write(stdout, "now building bigger trees: ")
  145. var t2: PNode
  146. for i in 1..100:
  147. t2 = buildTree()
  148. printTree(t2)
  149. write(stdout, "now test sequences of strings:")
  150. var s: seq[string] = @[]
  151. for i in 1..100:
  152. add s, "hohoho" # test reallocation
  153. writeLine(stdout, s[89])
  154. write(stdout, "done!\n")
  155. var
  156. father: TBNode
  157. s: string
  158. s = ""
  159. s = ""
  160. writeLine(stdout, repr(caseTree()))
  161. father.t.data = @["ha", "lets", "stress", "it"]
  162. father.t.data = @["ha", "lets", "stress", "it"]
  163. var t = buildTree()
  164. write(stdout, repr(t[]))
  165. buildBTree(father)
  166. write(stdout, repr(father))
  167. write(stdout, "starting main...\n")
  168. main()
  169. GC_fullCollect()
  170. # the M&S GC fails with this call and it's unclear why. Definitely something
  171. # we need to fix!
  172. GC_fullCollect()
  173. writeLine(stdout, GC_getStatistics())
  174. write(stdout, "finished\n")