gctest.nim 4.9 KB

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