gctest.nim 4.9 KB

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