gctest.nim 4.9 KB

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