# Some tokenization primitives. == code # instruction effective address register displacement immediate # . op subop mod rm32 base index scale r32 # . 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes # extract the next run of characters that are different from a given 'delimiter' (skipping multiple delimiters if necessary) # on reaching end of file, return an empty interval next-token-from-slice: # start: (addr byte), end: (addr byte), delimiter: byte, out: (addr slice) # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp # . save registers 50/push-eax 51/push-ecx 52/push-edx 57/push-edi # ecx = end 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 0xc/disp8 . # copy *(ebp+12) to ecx # edx = delimiter 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 2/r32/edx 0x10/disp8 . # copy *(ebp+16) to edx # edi = out 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 7/r32/edi 0x14/disp8 . # copy *(ebp+20) to edi # eax = skip-chars-matching-in-slice(start, end, delimiter) # . . push args 52/push-edx 51/push-ecx ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) # . . call e8/call skip-chars-matching-in-slice/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp # out->start = eax 89/copy 0/mod/indirect 7/rm32/edi . . . 0/r32/eax . . # copy eax to *edi # eax = skip-chars-not-matching-in-slice(eax, end, delimiter) # . . push args 52/push-edx 51/push-ecx 50/push-eax # . . call e8/call skip-chars-not-matching-in-slice/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp # out->end = eax 89/copy 1/mod/*+disp8 7/rm32/edi . . . 0/r32/eax 4/disp8 . # copy eax to *(edi+4) # . restore registers 5f/pop-to-edi 5a/pop-to-edx 59/pop-to-ecx 58/pop-to-eax # . epilogue 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 5d/pop-to-ebp c3/return test-next-token-from-slice: # . prologue 55/push-ebp 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp # (eax..ecx) = " ab" b8/copy-to-eax " ab"/imm32 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx 05/add-to-eax 4/imm32 # var out/edi: slice 68/push 0/imm32/end 68/push 0/imm32/start 89/copy 3/mod/direct 7/rm32/edi . . . 4/r32/esp . . # copy esp to edi # next-token-from-slice(eax, ecx, 0x20/space, out) # . . push args 57/push-edi 68/push 0x20/imm32 51/push-ecx 50/push-eax # . . call e8/call next-token-from-slice/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp # out->start should be at the 'a' # . check-ints-equal(out->start - in->start, 2, msg) # . . push args 68/push "F - test-next-token-from-slice: start"/imm32 68/push 2/imm32 # . . push out->start - in->start 8b/copy 0/mod/indirect 7/rm32/edi . . . 1/r32/ecx . . # copy *edi to ecx 2b/subtract 3/mod/direct 0/rm32/eax . . . 1/r32/ecx . . # subtract eax from ecx 51/push-ecx # . . call e8/call check-ints-equal/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp # out->end should be after the 'b' # check-ints-equal(out->end - in->start, 4, msg) # . . push args 68/push "F - test-next-t
discard """
output: '''obj2 @[]
obj @[]
obj3 @[]
3
obj2 @[]
obj @[]
obj3 @[]'''
cmd: "nim c -r --threads:on $file"
"""
# bug #4776
import tables
type
Base* = ref object of RootObj
someSeq: seq[int]
baseData: array[400000, byte]
Derived* = ref object of Base
data: array[400000, byte]
type
ThreadPool = ref object
threads: seq[ptr Thread[ThreadArg]]
channels: seq[ThreadArg]
TableChannel = Channel[TableRef[string, Base]]
ThreadArg = ptr TableChannel
var globalTable {.threadvar.}: TableRef[string, Base]
globalTable = newTable[string, Base]()
let d = new(Derived)
globalTable.add("obj", d)
globalTable.add("obj2", d)
globalTable.add("obj3", d)
proc testThread(channel: ptr TableChannel) {.thread.} =
globalTable = channel[].recv()
for k, v in pairs globaltable:
echo k, " ", v.someSeq
var myObj: Base
deepCopy(myObj, globalTable["obj"])
myObj.someSeq = newSeq[int](100)
let table = channel[].recv() # same table
echo table.len
for k, v in mpairs table:
echo k, " ", v.someSeq
assert(table.contains("obj")) # fails!
assert(table.contains("obj2")) # fails!
assert(table.contains("obj3")) # fails!
var channel: TableChannel
proc newThreadPool(threadCount: int) = #: ThreadPool =
#new(result)
#result.threads = newSeq[ptr Thread[ThreadArg]](threadCount)
#var channel = cast[ptr TableChannel](allocShared0(sizeof(TableChannel)))
channel.open()
channel.send(globalTable)
channel.send(globalTable)
#createThread(threadPtr[], testThread, addr channel)
testThread(addr channel)
#result.threads[i] = threadPtr
proc stop(p: ThreadPool) =
for t in p.threads:
joinThread(t[])
dealloc(t)
newThreadPool(1)#.stop()