remove some deprecated pre-1.0 stdlib modules (#20202)
* remove pre-1.0 stdlib deprecations notable exceptions: * ze, toU8 etc in system/arithmetics * potentially callsite * undo macros, ospaths, securehash, oswalkdir * add sets back * add back future, document deprecated versions * add to changelog [skip ci]
This commit is contained in:
parent
a895bbf714
commit
f4af9e955b
13 changed files with 18 additions and 980 deletions
|
|
@ -66,13 +66,16 @@
|
||||||
- Deprecated `std/sums`.
|
- Deprecated `std/sums`.
|
||||||
|
|
||||||
[//]: # "Removals:"
|
[//]: # "Removals:"
|
||||||
- Removed deprecated `std/sharedstrings`.
|
- Removed deprecated module `parseopt2`.
|
||||||
|
- Removed deprecated module `sharedstrings`.
|
||||||
|
- Removed deprecated module `dom_extensions`.
|
||||||
|
- Removed deprecated module `LockFreeHash`.
|
||||||
|
- Removed deprecated module `events`.
|
||||||
- Removed deprecated `oids.oidToString`.
|
- Removed deprecated `oids.oidToString`.
|
||||||
- Removed define `nimExperimentalAsyncjsThen` for `std/asyncjs.then` and `std/jsfetch`.
|
- Removed define `nimExperimentalAsyncjsThen` for `std/asyncjs.then` and `std/jsfetch`.
|
||||||
- Removed deprecated `jsre.test` and `jsre.toString`.
|
- Removed deprecated `jsre.test` and `jsre.toString`.
|
||||||
- Removed deprecated `math.c_frexp`.
|
- Removed deprecated `math.c_frexp`.
|
||||||
- Removed deprecated `` httpcore.`==` ``.
|
- Removed deprecated `` httpcore.`==` ``.
|
||||||
- Removed deprecated `std/dom_extensions`.
|
|
||||||
- Removed deprecated `std/posix.CMSG_SPACE` and `std/posix.CMSG_LEN` that takes wrong argument types.
|
- Removed deprecated `std/posix.CMSG_SPACE` and `std/posix.CMSG_LEN` that takes wrong argument types.
|
||||||
- Removed deprecated `osproc.poDemon`, symbol with typo.
|
- Removed deprecated `osproc.poDemon`, symbol with typo.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,611 +0,0 @@
|
||||||
#nim c -t:-march=i686 --cpu:amd64 --threads:on -d:release lockfreehash.nim
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
## Memory Utility Functions
|
|
||||||
|
|
||||||
{.deprecated.}
|
|
||||||
|
|
||||||
import math, hashes
|
|
||||||
|
|
||||||
proc newHeap*[T](): ptr T =
|
|
||||||
result = cast[ptr T](alloc0(sizeof(T)))
|
|
||||||
|
|
||||||
proc copyNew*[T](x: var T): ptr T =
|
|
||||||
var
|
|
||||||
size = sizeof(T)
|
|
||||||
mem = alloc(size)
|
|
||||||
copyMem(mem, x.addr, size)
|
|
||||||
return cast[ptr T](mem)
|
|
||||||
|
|
||||||
proc copyTo*[T](val: var T, dest: int) =
|
|
||||||
copyMem(pointer(dest), val.addr, sizeof(T))
|
|
||||||
|
|
||||||
proc allocType*[T](): pointer = alloc(sizeof(T))
|
|
||||||
|
|
||||||
proc newShared*[T](): ptr T =
|
|
||||||
result = cast[ptr T](allocShared0(sizeof(T)))
|
|
||||||
|
|
||||||
proc copyShared*[T](x: var T): ptr T =
|
|
||||||
var
|
|
||||||
size = sizeof(T)
|
|
||||||
mem = allocShared(size)
|
|
||||||
copyMem(mem, x.addr, size)
|
|
||||||
return cast[ptr T](mem)
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
## Pointer arithmetic
|
|
||||||
|
|
||||||
proc `+`*(p: pointer, i: int): pointer {.inline.} =
|
|
||||||
cast[pointer](cast[int](p) + i)
|
|
||||||
|
|
||||||
const
|
|
||||||
minTableSize = 8
|
|
||||||
reProbeLimit = 12
|
|
||||||
minCopyWork = 4096
|
|
||||||
intSize = sizeof(int)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
when sizeof(int) == 4: # 32bit
|
|
||||||
type
|
|
||||||
Raw = range[0..1073741823]
|
|
||||||
## The range of uint values that can be stored directly in a value slot
|
|
||||||
## when on a 32 bit platform
|
|
||||||
elif sizeof(int) == 8: # 64bit
|
|
||||||
type
|
|
||||||
Raw = range[0'i64..4611686018427387903'i64]
|
|
||||||
## The range of uint values that can be stored directly in a value slot
|
|
||||||
## when on a 64 bit platform
|
|
||||||
else:
|
|
||||||
{.error: "unsupported platform".}
|
|
||||||
|
|
||||||
type
|
|
||||||
Entry = tuple
|
|
||||||
key: int
|
|
||||||
value: int
|
|
||||||
|
|
||||||
EntryArr = ptr array[0..10_000_000, Entry]
|
|
||||||
|
|
||||||
PConcTable[K, V] = ptr object {.pure.}
|
|
||||||
len: int
|
|
||||||
used: int
|
|
||||||
active: int
|
|
||||||
copyIdx: int
|
|
||||||
copyDone: int
|
|
||||||
next: PConcTable[K, V]
|
|
||||||
data: EntryArr
|
|
||||||
|
|
||||||
proc setVal[K, V](table: var PConcTable[K, V], key: int, val: int,
|
|
||||||
expVal: int, match: bool): int
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
# Create a new table
|
|
||||||
proc newLFTable*[K, V](size: int = minTableSize): PConcTable[K, V] =
|
|
||||||
let
|
|
||||||
dataLen = max(nextPowerOfTwo(size), minTableSize)
|
|
||||||
dataSize = dataLen*sizeof(Entry)
|
|
||||||
dataMem = allocShared0(dataSize)
|
|
||||||
tableSize = 7 * intSize
|
|
||||||
tableMem = allocShared0(tableSize)
|
|
||||||
table = cast[PConcTable[K, V]](tableMem)
|
|
||||||
table.len = dataLen
|
|
||||||
table.used = 0
|
|
||||||
table.active = 0
|
|
||||||
table.copyIdx = 0
|
|
||||||
table.copyDone = 0
|
|
||||||
table.next = nil
|
|
||||||
table.data = cast[EntryArr](dataMem)
|
|
||||||
result = table
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
# Delete a table
|
|
||||||
proc deleteConcTable[K, V](tbl: PConcTable[K, V]) =
|
|
||||||
deallocShared(tbl.data)
|
|
||||||
deallocShared(tbl)
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
proc `[]`[K, V](table: var PConcTable[K, V], i: int): var Entry {.inline.} =
|
|
||||||
table.data[i]
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# State flags stored in ptr
|
|
||||||
|
|
||||||
|
|
||||||
proc pack[T](x: T): int {.inline.} =
|
|
||||||
result = (cast[int](x) shl 2)
|
|
||||||
#echo("packKey ",cast[int](x) , " -> ", result)
|
|
||||||
|
|
||||||
# Pop the flags off returning a 4 byte aligned ptr to our Key or Val
|
|
||||||
proc pop(x: int): int {.inline.} =
|
|
||||||
result = x and 0xFFFFFFFC'i32
|
|
||||||
|
|
||||||
# Pop the raw value off of our Key or Val
|
|
||||||
proc popRaw(x: int): int {.inline.} =
|
|
||||||
result = x shr 2
|
|
||||||
|
|
||||||
# Pop the flags off returning a 4 byte aligned ptr to our Key or Val
|
|
||||||
proc popPtr[V](x: int): ptr V {.inline.} =
|
|
||||||
result = cast[ptr V](pop(x))
|
|
||||||
#echo("popPtr " & $x & " -> " & $cast[int](result))
|
|
||||||
|
|
||||||
# Ghost (sentinel)
|
|
||||||
# K or V is no longer valid use new table
|
|
||||||
const Ghost = 0xFFFFFFFC
|
|
||||||
proc isGhost(x: int): bool {.inline.} =
|
|
||||||
result = x == 0xFFFFFFFC
|
|
||||||
|
|
||||||
# Tombstone
|
|
||||||
# applied to V = K is dead
|
|
||||||
proc isTomb(x: int): bool {.inline.} =
|
|
||||||
result = (x and 0x00000002) != 0
|
|
||||||
|
|
||||||
proc setTomb(x: int): int {.inline.} =
|
|
||||||
result = x or 0x00000002
|
|
||||||
|
|
||||||
# Prime
|
|
||||||
# K or V is in new table copied from old
|
|
||||||
proc isPrime(x: int): bool {.inline.} =
|
|
||||||
result = (x and 0x00000001) != 0
|
|
||||||
|
|
||||||
proc setPrime(x: int): int {.inline.} =
|
|
||||||
result = x or 0x00000001
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
##This is for i32 only need to override for i64
|
|
||||||
proc hashInt(x: int): int {.inline.} =
|
|
||||||
var h = uint32(x) #shr 2'u32
|
|
||||||
h = h xor (h shr 16'u32)
|
|
||||||
h *= 0x85ebca6b'u32
|
|
||||||
h = h xor (h shr 13'u32)
|
|
||||||
h *= 0xc2b2ae35'u32
|
|
||||||
h = h xor (h shr 16'u32)
|
|
||||||
result = int(h)
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
proc resize[K, V](self: PConcTable[K, V]): PConcTable[K, V] =
|
|
||||||
var next = atomic_load_n(self.next.addr, ATOMIC_RELAXED)
|
|
||||||
#echo("next = " & $cast[int](next))
|
|
||||||
if next != nil:
|
|
||||||
#echo("A new table already exists, copy in progress")
|
|
||||||
return next
|
|
||||||
var
|
|
||||||
oldLen = atomic_load_n(self.len.addr, ATOMIC_RELAXED)
|
|
||||||
newTable = newLFTable[K, V](oldLen*2)
|
|
||||||
success = atomic_compare_exchange_n(self.next.addr, next.addr, newTable,
|
|
||||||
false, ATOMIC_RELAXED, ATOMIC_RELAXED)
|
|
||||||
if not success:
|
|
||||||
echo("someone beat us to it! delete table we just created and return his " &
|
|
||||||
$cast[int](next))
|
|
||||||
deleteConcTable(newTable)
|
|
||||||
return next
|
|
||||||
else:
|
|
||||||
echo("Created New Table! " & $cast[int](newTable) & " Size = " & $newTable.len)
|
|
||||||
return newTable
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
#proc keyEQ[K](key1: ptr K, key2: ptr K): bool {.inline.} =
|
|
||||||
proc keyEQ[K](key1: int, key2: int): bool {.inline.} =
|
|
||||||
result = false
|
|
||||||
when K is Raw:
|
|
||||||
if key1 == key2:
|
|
||||||
result = true
|
|
||||||
else:
|
|
||||||
var
|
|
||||||
p1 = popPtr[K](key1)
|
|
||||||
p2 = popPtr[K](key2)
|
|
||||||
if p1 != nil and p2 != nil:
|
|
||||||
if cast[int](p1) == cast[int](p2):
|
|
||||||
return true
|
|
||||||
if p1[] == p2[]:
|
|
||||||
return true
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
#proc tableFull(self: var PConcTable[K,V]) : bool {.inline.} =
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
proc copySlot[K, V](idx: int, oldTbl: var PConcTable[K, V],
|
|
||||||
newTbl: var PConcTable[K, V]): bool =
|
|
||||||
#echo("Copy idx " & $idx)
|
|
||||||
var
|
|
||||||
oldVal = 0
|
|
||||||
oldkey = 0
|
|
||||||
ok = false
|
|
||||||
result = false
|
|
||||||
#Block the key so no other threads waste time here
|
|
||||||
while not ok:
|
|
||||||
ok = atomic_compare_exchange_n(oldTbl[idx].key.addr, oldKey.addr,
|
|
||||||
setTomb(oldKey), false, ATOMIC_RELAXED, ATOMIC_RELAXED)
|
|
||||||
#echo("oldKey was = " & $oldKey & " set it to tomb " & $setTomb(oldKey))
|
|
||||||
#Prevent new values from appearing in the old table by priming
|
|
||||||
oldVal = atomic_load_n(oldTbl[idx].value.addr, ATOMIC_RELAXED)
|
|
||||||
while not isPrime(oldVal):
|
|
||||||
var box = if oldVal == 0 or isTomb(oldVal): oldVal.setTomb.setPrime
|
|
||||||
else: oldVal.setPrime
|
|
||||||
if atomic_compare_exchange_n(oldTbl[idx].value.addr, oldVal.addr,
|
|
||||||
box, false, ATOMIC_RELAXED, ATOMIC_RELAXED):
|
|
||||||
if isPrime(box) and isTomb(box):
|
|
||||||
return true
|
|
||||||
oldVal = box
|
|
||||||
break
|
|
||||||
#echo("oldVal was = ", oldVal, " set it to prime ", box)
|
|
||||||
if isPrime(oldVal) and isTomb(oldVal):
|
|
||||||
#when not (K is Raw):
|
|
||||||
# deallocShared(popPtr[K](oldKey))
|
|
||||||
return false
|
|
||||||
if isTomb(oldVal):
|
|
||||||
echo("oldVal is Tomb!!!, should not happen")
|
|
||||||
if pop(oldVal) != 0:
|
|
||||||
result = setVal(newTbl, pop(oldKey), pop(oldVal), 0, true) == 0
|
|
||||||
#if result:
|
|
||||||
#echo("Copied a Slot! idx= " & $idx & " key= " & $oldKey & " val= " & $oldVal)
|
|
||||||
#else:
|
|
||||||
#echo("copy slot failed")
|
|
||||||
# Our copy is done so we disable the old slot
|
|
||||||
while not ok:
|
|
||||||
ok = atomic_compare_exchange_n(oldTbl[idx].value.addr, oldVal.addr,
|
|
||||||
oldVal.setTomb.setPrime, false, ATOMIC_RELAXED, ATOMIC_RELAXED)
|
|
||||||
#echo("disabled old slot")
|
|
||||||
#echo"---------------------"
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
proc promote[K, V](table: var PConcTable[K, V]) =
|
|
||||||
var
|
|
||||||
newData = atomic_load_n(table.next.data.addr, ATOMIC_RELAXED)
|
|
||||||
newLen = atomic_load_n(table.next.len.addr, ATOMIC_RELAXED)
|
|
||||||
newUsed = atomic_load_n(table.next.used.addr, ATOMIC_RELAXED)
|
|
||||||
|
|
||||||
deallocShared(table.data)
|
|
||||||
atomic_store_n(table.data.addr, newData, ATOMIC_RELAXED)
|
|
||||||
atomic_store_n(table.len.addr, newLen, ATOMIC_RELAXED)
|
|
||||||
atomic_store_n(table.used.addr, newUsed, ATOMIC_RELAXED)
|
|
||||||
atomic_store_n(table.copyIdx.addr, 0, ATOMIC_RELAXED)
|
|
||||||
atomic_store_n(table.copyDone.addr, 0, ATOMIC_RELAXED)
|
|
||||||
deallocShared(table.next)
|
|
||||||
atomic_store_n(table.next.addr, nil, ATOMIC_RELAXED)
|
|
||||||
echo("new table swapped!")
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
proc checkAndPromote[K, V](table: var PConcTable[K, V], workDone: int): bool =
|
|
||||||
var
|
|
||||||
oldLen = atomic_load_n(table.len.addr, ATOMIC_RELAXED)
|
|
||||||
copyDone = atomic_load_n(table.copyDone.addr, ATOMIC_RELAXED)
|
|
||||||
ok: bool
|
|
||||||
result = false
|
|
||||||
if workDone > 0:
|
|
||||||
#echo("len to copy =" & $oldLen)
|
|
||||||
#echo("copyDone + workDone = " & $copyDone & " + " & $workDone)
|
|
||||||
while not ok:
|
|
||||||
ok = atomic_compare_exchange_n(table.copyDone.addr, copyDone.addr,
|
|
||||||
copyDone + workDone, false, ATOMIC_RELAXED, ATOMIC_RELAXED)
|
|
||||||
#if ok: echo("set copyDone")
|
|
||||||
# If the copy is done we can promote this table
|
|
||||||
if copyDone + workDone >= oldLen:
|
|
||||||
# Swap new data
|
|
||||||
#echo("work is done!")
|
|
||||||
table.promote
|
|
||||||
result = true
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
proc copySlotAndCheck[K, V](table: var PConcTable[K, V], idx: int):
|
|
||||||
PConcTable[K, V] =
|
|
||||||
var
|
|
||||||
newTable = cast[PConcTable[K, V]](atomic_load_n(table.next.addr,
|
|
||||||
ATOMIC_RELAXED))
|
|
||||||
result = newTable
|
|
||||||
if newTable != nil and copySlot(idx, table, newTable):
|
|
||||||
#echo("copied a single slot, idx = " & $idx)
|
|
||||||
if checkAndPromote(table, 1): return table
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
proc helpCopy[K, V](table: var PConcTable[K, V]): PConcTable[K, V] =
|
|
||||||
var
|
|
||||||
newTable = cast[PConcTable[K, V]](atomic_load_n(table.next.addr,
|
|
||||||
ATOMIC_RELAXED))
|
|
||||||
result = newTable
|
|
||||||
if newTable != nil:
|
|
||||||
var
|
|
||||||
oldLen = atomic_load_n(table.len.addr, ATOMIC_RELAXED)
|
|
||||||
copyDone = atomic_load_n(table.copyDone.addr, ATOMIC_RELAXED)
|
|
||||||
copyIdx = 0
|
|
||||||
work = min(oldLen, minCopyWork)
|
|
||||||
#panicStart = -1
|
|
||||||
workDone = 0
|
|
||||||
if copyDone < oldLen:
|
|
||||||
var ok: bool
|
|
||||||
while not ok:
|
|
||||||
ok = atomic_compare_exchange_n(table.copyIdx.addr, copyIdx.addr,
|
|
||||||
copyIdx + work, false, ATOMIC_RELAXED, ATOMIC_RELAXED)
|
|
||||||
#echo("copy idx = ", copyIdx)
|
|
||||||
for i in 0..work-1:
|
|
||||||
var idx = (copyIdx + i) and (oldLen - 1)
|
|
||||||
if copySlot(idx, table, newTable):
|
|
||||||
workDone += 1
|
|
||||||
if workDone > 0:
|
|
||||||
#echo("did work ", workDone, " on thread ", cast[int](myThreadID[pointer]()))
|
|
||||||
if checkAndPromote(table, workDone): return table
|
|
||||||
# In case a thread finished all the work then got stalled before promotion
|
|
||||||
if checkAndPromote(table, 0): return table
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
proc setVal[K, V](table: var PConcTable[K, V], key: int, val: int,
|
|
||||||
expVal: int, match: bool): int =
|
|
||||||
#echo("-try set- in table ", " key = ", (popPtr[K](key)[]), " val = ", val)
|
|
||||||
when K is Raw:
|
|
||||||
var idx = hashInt(key)
|
|
||||||
else:
|
|
||||||
var idx = popPtr[K](key)[].hash
|
|
||||||
var
|
|
||||||
nextTable: PConcTable[K, V]
|
|
||||||
probes = 1
|
|
||||||
# spin until we find a key slot or build and jump to next table
|
|
||||||
while true:
|
|
||||||
idx = idx and (table.len - 1)
|
|
||||||
#echo("try set idx = " & $idx & "for" & $key)
|
|
||||||
var
|
|
||||||
probedKey = 0
|
|
||||||
openKey = atomic_compare_exchange_n(table[idx].key.addr, probedKey.addr,
|
|
||||||
key, false, ATOMIC_RELAXED, ATOMIC_RELAXED)
|
|
||||||
if openKey:
|
|
||||||
if val.isTomb:
|
|
||||||
#echo("val was tomb, bail, no reason to set an open slot to tomb")
|
|
||||||
return val
|
|
||||||
#increment used slots
|
|
||||||
#echo("found an open slot, total used = " &
|
|
||||||
#$atomic_add_fetch(table.used.addr, 1, ATOMIC_RELAXED))
|
|
||||||
discard atomic_add_fetch(table.used.addr, 1, ATOMIC_RELAXED)
|
|
||||||
break # We found an open slot
|
|
||||||
#echo("set idx ", idx, " key = ", key, " probed = ", probedKey)
|
|
||||||
if keyEQ[K](probedKey, key):
|
|
||||||
#echo("we found the matching slot")
|
|
||||||
break # We found a matching slot
|
|
||||||
if (not(expVal != 0 and match)) and (probes >= reProbeLimit or key.isTomb):
|
|
||||||
if key.isTomb: echo("Key is Tombstone")
|
|
||||||
#if probes >= reProbeLimit: echo("Too much probing " & $probes)
|
|
||||||
#echo("try to resize")
|
|
||||||
#create next bigger table
|
|
||||||
nextTable = resize(table)
|
|
||||||
#help do some copying
|
|
||||||
#echo("help copy old table to new")
|
|
||||||
nextTable = helpCopy(table)
|
|
||||||
#now setVal in the new table instead
|
|
||||||
#echo("jumping to next table to set val")
|
|
||||||
return setVal(nextTable, key, val, expVal, match)
|
|
||||||
else:
|
|
||||||
idx += 1
|
|
||||||
probes += 1
|
|
||||||
# Done spinning for a new slot
|
|
||||||
var oldVal = atomic_load_n(table[idx].value.addr, ATOMIC_RELAXED)
|
|
||||||
if val == oldVal:
|
|
||||||
#echo("this val is already in the slot")
|
|
||||||
return oldVal
|
|
||||||
nextTable = atomic_load_n(table.next.addr, ATOMIC_SEQ_CST)
|
|
||||||
if nextTable == nil and
|
|
||||||
((oldVal == 0 and
|
|
||||||
(probes >= reProbeLimit or table.used / table.len > 0.8)) or
|
|
||||||
(isPrime(oldVal))):
|
|
||||||
if table.used / table.len > 0.8: echo("resize because usage ratio = " &
|
|
||||||
$(table.used / table.len))
|
|
||||||
if isPrime(oldVal): echo("old val isPrime, should be a rare mem ordering event")
|
|
||||||
nextTable = resize(table)
|
|
||||||
if nextTable != nil:
|
|
||||||
#echo("tomb old slot then set in new table")
|
|
||||||
nextTable = copySlotAndCheck(table, idx)
|
|
||||||
return setVal(nextTable, key, val, expVal, match)
|
|
||||||
# Finally ready to add new val to table
|
|
||||||
while true:
|
|
||||||
if match and oldVal != expVal:
|
|
||||||
#echo("set failed, no match oldVal= " & $oldVal & " expVal= " & $expVal)
|
|
||||||
return oldVal
|
|
||||||
if atomic_compare_exchange_n(table[idx].value.addr, oldVal.addr,
|
|
||||||
val, false, ATOMIC_RELEASE, ATOMIC_RELAXED):
|
|
||||||
#echo("val set at table " & $cast[int](table))
|
|
||||||
if expVal != 0:
|
|
||||||
if (oldVal == 0 or isTomb(oldVal)) and not isTomb(val):
|
|
||||||
discard atomic_add_fetch(table.active.addr, 1, ATOMIC_RELAXED)
|
|
||||||
elif not (oldVal == 0 or isTomb(oldVal)) and isTomb(val):
|
|
||||||
discard atomic_add_fetch(table.active.addr, -1, ATOMIC_RELAXED)
|
|
||||||
if oldVal == 0 and expVal != 0:
|
|
||||||
return setTomb(oldVal)
|
|
||||||
else: return oldVal
|
|
||||||
if isPrime(oldVal):
|
|
||||||
nextTable = copySlotAndCheck(table, idx)
|
|
||||||
return setVal(nextTable, key, val, expVal, match)
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
proc getVal[K, V](table: var PConcTable[K, V], key: int): int =
|
|
||||||
#echo("-try get- key = " & $key)
|
|
||||||
when K is Raw:
|
|
||||||
var idx = hashInt(key)
|
|
||||||
else:
|
|
||||||
var idx = popPtr[K](key)[].hash
|
|
||||||
#echo("get idx ", idx)
|
|
||||||
var
|
|
||||||
probes = 0
|
|
||||||
val: int
|
|
||||||
while true:
|
|
||||||
idx = idx and (table.len - 1)
|
|
||||||
var
|
|
||||||
newTable: PConcTable[K, V] # = atomic_load_n(table.next.addr, ATOMIC_ACQUIRE)
|
|
||||||
probedKey = atomic_load_n(table[idx].key.addr, ATOMIC_SEQ_CST)
|
|
||||||
if keyEQ[K](probedKey, key):
|
|
||||||
#echo("found key after ", probes+1)
|
|
||||||
val = atomic_load_n(table[idx].value.addr, ATOMIC_ACQUIRE)
|
|
||||||
if not isPrime(val):
|
|
||||||
if isTomb(val):
|
|
||||||
#echo("val was tomb but not prime")
|
|
||||||
return 0
|
|
||||||
else:
|
|
||||||
#echo("-GotIt- idx = ", idx, " key = ", key, " val ", val )
|
|
||||||
return val
|
|
||||||
else:
|
|
||||||
newTable = copySlotAndCheck(table, idx)
|
|
||||||
return getVal(newTable, key)
|
|
||||||
else:
|
|
||||||
#echo("probe ", probes, " idx = ", idx, " key = ", key, " found ", probedKey )
|
|
||||||
if probes >= reProbeLimit*4 or key.isTomb:
|
|
||||||
if newTable == nil:
|
|
||||||
#echo("too many probes and no new table ", key, " ", idx )
|
|
||||||
return 0
|
|
||||||
else:
|
|
||||||
newTable = helpCopy(table)
|
|
||||||
return getVal(newTable, key)
|
|
||||||
idx += 1
|
|
||||||
probes += 1
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
#proc set*(table: var PConcTable[Raw,Raw], key: Raw, val: Raw) =
|
|
||||||
# discard setVal(table, pack(key), pack(key), 0, false)
|
|
||||||
|
|
||||||
#proc set*[V](table: var PConcTable[Raw,V], key: Raw, val: ptr V) =
|
|
||||||
# discard setVal(table, pack(key), cast[int](val), 0, false)
|
|
||||||
|
|
||||||
proc set*[K, V](table: var PConcTable[K, V], key: var K, val: var V) =
|
|
||||||
when not (K is Raw):
|
|
||||||
var newKey = cast[int](copyShared(key))
|
|
||||||
else:
|
|
||||||
var newKey = pack(key)
|
|
||||||
when not (V is Raw):
|
|
||||||
var newVal = cast[int](copyShared(val))
|
|
||||||
else:
|
|
||||||
var newVal = pack(val)
|
|
||||||
var oldPtr = pop(setVal(table, newKey, newVal, 0, false))
|
|
||||||
#echo("oldPtr = ", cast[int](oldPtr), " newPtr = ", cast[int](newPtr))
|
|
||||||
when not (V is Raw):
|
|
||||||
if newVal != oldPtr and oldPtr != 0:
|
|
||||||
deallocShared(cast[ptr V](oldPtr))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
proc get*[K, V](table: var PConcTable[K, V], key: var K): V =
|
|
||||||
when not (V is Raw):
|
|
||||||
when not (K is Raw):
|
|
||||||
return popPtr[V](getVal(table, cast[int](key.addr)))[]
|
|
||||||
else:
|
|
||||||
return popPtr[V](getVal(table, pack(key)))[]
|
|
||||||
else:
|
|
||||||
when not (K is Raw):
|
|
||||||
return popRaw(getVal(table, cast[int](key.addr)))
|
|
||||||
else:
|
|
||||||
return popRaw(getVal(table, pack(key)))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#proc `[]`[K,V](table: var PConcTable[K,V], key: K): PEntry[K,V] {.inline.} =
|
|
||||||
# getVal(table, key)
|
|
||||||
|
|
||||||
#proc `[]=`[K,V](table: var PConcTable[K,V], key: K, val: V): PEntry[K,V] {.inline.} =
|
|
||||||
# setVal(table, key, val)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#Tests ----------------------------
|
|
||||||
when not defined(testing) and isMainModule:
|
|
||||||
import locks, times, mersenne
|
|
||||||
|
|
||||||
const
|
|
||||||
numTests = 100000
|
|
||||||
numThreads = 10
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
type
|
|
||||||
TestObj = tuple
|
|
||||||
thr: int
|
|
||||||
f0: int
|
|
||||||
f1: int
|
|
||||||
|
|
||||||
Data = tuple[k: string, v: TestObj]
|
|
||||||
PDataArr = array[0..numTests-1, Data]
|
|
||||||
Dict = PConcTable[string, TestObj]
|
|
||||||
|
|
||||||
var
|
|
||||||
thr: array[0..numThreads-1, Thread[Dict]]
|
|
||||||
|
|
||||||
table = newLFTable[string, TestObj](8)
|
|
||||||
rand = newMersenneTwister(2525)
|
|
||||||
|
|
||||||
proc createSampleData(len: int): PDataArr =
|
|
||||||
#result = cast[PDataArr](allocShared0(sizeof(Data)*numTests))
|
|
||||||
for i in 0..len-1:
|
|
||||||
result[i].k = "mark" & $(i+1)
|
|
||||||
#echo("mark" & $(i+1), " ", hash("mark" & $(i+1)))
|
|
||||||
result[i].v.thr = 0
|
|
||||||
result[i].v.f0 = i+1
|
|
||||||
result[i].v.f1 = 0
|
|
||||||
#echo("key = " & $(i+1) & " Val ptr = " & $cast[int](result[i].v.addr))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
proc threadProc(tp: Dict) {.thread.} =
|
|
||||||
var t = cpuTime();
|
|
||||||
for i in 1..numTests:
|
|
||||||
var key = "mark" & $(i)
|
|
||||||
var got = table.get(key)
|
|
||||||
got.thr = cast[int](myThreadID[pointer]())
|
|
||||||
got.f1 = got.f1 + 1
|
|
||||||
table.set(key, got)
|
|
||||||
t = cpuTime() - t
|
|
||||||
echo t
|
|
||||||
|
|
||||||
|
|
||||||
var testData = createSampleData(numTests)
|
|
||||||
|
|
||||||
for i in 0..numTests-1:
|
|
||||||
table.set(testData[i].k, testData[i].v)
|
|
||||||
|
|
||||||
var i = 0
|
|
||||||
while i < numThreads:
|
|
||||||
createThread(thr[i], threadProc, table)
|
|
||||||
i += 1
|
|
||||||
|
|
||||||
joinThreads(thr)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var fails = 0
|
|
||||||
|
|
||||||
for i in 0..numTests-1:
|
|
||||||
var got = table.get(testData[i].k)
|
|
||||||
if got.f0 != i+1 or got.f1 != numThreads:
|
|
||||||
fails += 1
|
|
||||||
echo(got)
|
|
||||||
|
|
||||||
echo("Failed read or write = ", fails)
|
|
||||||
|
|
||||||
|
|
||||||
#for i in 1..numTests:
|
|
||||||
# echo(i, " = ", hashInt(i) and 8191)
|
|
||||||
|
|
||||||
deleteConcTable(table)
|
|
||||||
|
|
@ -1,104 +0,0 @@
|
||||||
#
|
|
||||||
#
|
|
||||||
# Nim's Runtime Library
|
|
||||||
# (c) Copyright 2011 Alexander Mitchell-Robinson
|
|
||||||
#
|
|
||||||
# See the file "copying.txt", included in this
|
|
||||||
# distribution, for details about the copyright.
|
|
||||||
#
|
|
||||||
|
|
||||||
## :Author: Alexander Mitchell-Robinson
|
|
||||||
##
|
|
||||||
## Unstable API.
|
|
||||||
##
|
|
||||||
## This module implements an event system that is not dependent on external
|
|
||||||
## graphical toolkits. It was originally called `NimEE` because
|
|
||||||
## it was inspired by Python's PyEE module. There are two ways you can use
|
|
||||||
## events: one is a python-inspired way; the other is more of a C-style way.
|
|
||||||
##
|
|
||||||
## .. code-block:: Nim
|
|
||||||
## var ee = initEventEmitter()
|
|
||||||
## var genericargs: EventArgs
|
|
||||||
## proc handleevent(e: EventArgs) =
|
|
||||||
## echo("Handled!")
|
|
||||||
##
|
|
||||||
## # Python way
|
|
||||||
## ee.on("EventName", handleevent)
|
|
||||||
## ee.emit("EventName", genericargs)
|
|
||||||
##
|
|
||||||
## # C/Java way
|
|
||||||
## # Declare a type
|
|
||||||
## type
|
|
||||||
## SomeObject = object of RootObj
|
|
||||||
## SomeEvent: EventHandler
|
|
||||||
## var myobj: SomeObject
|
|
||||||
## myobj.SomeEvent = initEventHandler("SomeEvent")
|
|
||||||
## myobj.SomeEvent.addHandler(handleevent)
|
|
||||||
## ee.emit(myobj.SomeEvent, genericargs)
|
|
||||||
|
|
||||||
{.deprecated.}
|
|
||||||
|
|
||||||
type
|
|
||||||
EventArgs* = object of RootObj ## Base object for event arguments that are passed to callback functions.
|
|
||||||
EventHandler* = tuple[name: string, handlers: seq[proc(e: EventArgs) {.closure.}]] ## An eventhandler for an event.
|
|
||||||
|
|
||||||
type
|
|
||||||
EventEmitter* = object ## An object that fires events and holds event handlers for an object.
|
|
||||||
s: seq[EventHandler]
|
|
||||||
EventError* = object of ValueError
|
|
||||||
|
|
||||||
proc initEventHandler*(name: string): EventHandler =
|
|
||||||
## Initializes an EventHandler with the specified name and returns it.
|
|
||||||
result.handlers = @[]
|
|
||||||
result.name = name
|
|
||||||
|
|
||||||
proc addHandler*(handler: var EventHandler, fn: proc(e: EventArgs) {.closure.}) =
|
|
||||||
## Adds the callback to the specified event handler.
|
|
||||||
handler.handlers.add(fn)
|
|
||||||
|
|
||||||
proc removeHandler*(handler: var EventHandler, fn: proc(e: EventArgs) {.closure.}) =
|
|
||||||
## Removes the callback from the specified event handler.
|
|
||||||
for i in countup(0, len(handler.handlers)-1):
|
|
||||||
if fn == handler.handlers[i]:
|
|
||||||
handler.handlers.del(i)
|
|
||||||
break
|
|
||||||
|
|
||||||
proc containsHandler*(handler: var EventHandler, fn: proc(e: EventArgs) {.closure.}): bool =
|
|
||||||
## Checks if a callback is registered to this event handler.
|
|
||||||
return handler.handlers.contains(fn)
|
|
||||||
|
|
||||||
|
|
||||||
proc clearHandlers*(handler: var EventHandler) =
|
|
||||||
## Clears all of the callbacks from the event handler.
|
|
||||||
setLen(handler.handlers, 0)
|
|
||||||
|
|
||||||
proc getEventHandler(emitter: var EventEmitter, event: string): int =
|
|
||||||
for k in 0..high(emitter.s):
|
|
||||||
if emitter.s[k].name == event: return k
|
|
||||||
return -1
|
|
||||||
|
|
||||||
proc on*(emitter: var EventEmitter, event: string, fn: proc(e: EventArgs) {.closure.}) =
|
|
||||||
## Assigns a event handler with the specified callback. If the event
|
|
||||||
## doesn't exist, it will be created.
|
|
||||||
var i = getEventHandler(emitter, event)
|
|
||||||
if i < 0:
|
|
||||||
var eh = initEventHandler(event)
|
|
||||||
addHandler(eh, fn)
|
|
||||||
emitter.s.add(eh)
|
|
||||||
else:
|
|
||||||
addHandler(emitter.s[i], fn)
|
|
||||||
|
|
||||||
proc emit*(emitter: var EventEmitter, eventhandler: var EventHandler,
|
|
||||||
args: EventArgs) =
|
|
||||||
## Fires an event handler with specified event arguments.
|
|
||||||
for fn in items(eventhandler.handlers): fn(args)
|
|
||||||
|
|
||||||
proc emit*(emitter: var EventEmitter, event: string, args: EventArgs) =
|
|
||||||
## Fires an event handler with specified event arguments.
|
|
||||||
var i = getEventHandler(emitter, event)
|
|
||||||
if i >= 0:
|
|
||||||
emit(emitter, emitter.s[i], args)
|
|
||||||
|
|
||||||
proc initEventEmitter*(): EventEmitter =
|
|
||||||
## Creates and returns a new EventEmitter.
|
|
||||||
result.s = @[]
|
|
||||||
6
lib/deprecated/pure/future.nim
Normal file
6
lib/deprecated/pure/future.nim
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
## This module is a deprecated alias for the `sugar` module. Deprecated since 0.19.0.
|
||||||
|
|
||||||
|
{.deprecated: "Use the new 'sugar' module instead".}
|
||||||
|
|
||||||
|
import sugar
|
||||||
|
export sugar
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
#
|
#
|
||||||
|
|
||||||
## This module is deprecated, `import std/os` instead.
|
## This module is deprecated since 0.20.0, `import std/os` instead.
|
||||||
|
|
||||||
{.deprecated: "use `std/os` instead".}
|
{.deprecated: "use `std/os` instead".}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,155 +0,0 @@
|
||||||
#
|
|
||||||
#
|
|
||||||
# Nim's Runtime Library
|
|
||||||
# (c) Copyright 2015 Andreas Rumpf
|
|
||||||
#
|
|
||||||
# See the file "copying.txt", included in this
|
|
||||||
# distribution, for details about the copyright.
|
|
||||||
#
|
|
||||||
|
|
||||||
## This module provides the standard Nim command line parser.
|
|
||||||
## It supports one convenience iterator over all command line options and some
|
|
||||||
## lower-level features.
|
|
||||||
##
|
|
||||||
## Supported syntax:
|
|
||||||
##
|
|
||||||
## 1. short options - `-abcd`, where a, b, c, d are names
|
|
||||||
## 2. long option - `--foo:bar`, `--foo=bar` or `--foo`
|
|
||||||
## 3. argument - everything else
|
|
||||||
|
|
||||||
{.deprecated: "Use the 'parseopt' module instead".}
|
|
||||||
{.push debugger: off.}
|
|
||||||
|
|
||||||
include "system/inclrtl"
|
|
||||||
|
|
||||||
import
|
|
||||||
os, strutils
|
|
||||||
|
|
||||||
type
|
|
||||||
CmdLineKind* = enum ## the detected command line token
|
|
||||||
cmdEnd, ## end of command line reached
|
|
||||||
cmdArgument, ## argument detected
|
|
||||||
cmdLongOption, ## a long option `--option` detected
|
|
||||||
cmdShortOption ## a short option `-c` detected
|
|
||||||
OptParser* =
|
|
||||||
object of RootObj ## this object implements the command line parser
|
|
||||||
cmd: seq[string]
|
|
||||||
pos: int
|
|
||||||
remainingShortOptions: string
|
|
||||||
kind*: CmdLineKind ## the detected command line token
|
|
||||||
key*, val*: string ## key and value pair; `key` is the option
|
|
||||||
## or the argument, `value` is not "" if
|
|
||||||
## the option was given a value
|
|
||||||
|
|
||||||
proc initOptParser*(cmdline: seq[string]): OptParser {.rtl.} =
|
|
||||||
## Initializes option parses with cmdline. cmdline should not contain
|
|
||||||
## argument 0 - program name.
|
|
||||||
## If cmdline.len == 0 default to current command line arguments.
|
|
||||||
result.remainingShortOptions = ""
|
|
||||||
when not defined(createNimRtl):
|
|
||||||
if cmdline.len == 0:
|
|
||||||
result.cmd = commandLineParams()
|
|
||||||
return
|
|
||||||
else:
|
|
||||||
assert cmdline != nil, "Cannot determine command line arguments."
|
|
||||||
|
|
||||||
result.cmd = @cmdline
|
|
||||||
|
|
||||||
when not defined(createNimRtl):
|
|
||||||
proc initOptParser*(): OptParser =
|
|
||||||
## Initializes option parser from current command line arguments.
|
|
||||||
return initOptParser(commandLineParams())
|
|
||||||
|
|
||||||
proc next*(p: var OptParser) {.rtl, extern: "npo2$1".}
|
|
||||||
|
|
||||||
proc nextOption(p: var OptParser, token: string, allowEmpty: bool) =
|
|
||||||
for splitchar in [':', '=']:
|
|
||||||
if splitchar in token:
|
|
||||||
let pos = token.find(splitchar)
|
|
||||||
p.key = token[0..pos-1]
|
|
||||||
p.val = token[pos+1..token.len-1]
|
|
||||||
return
|
|
||||||
|
|
||||||
p.key = token
|
|
||||||
if allowEmpty:
|
|
||||||
p.val = ""
|
|
||||||
else:
|
|
||||||
p.remainingShortOptions = token[0..token.len-1]
|
|
||||||
p.next()
|
|
||||||
|
|
||||||
proc next(p: var OptParser) =
|
|
||||||
if p.remainingShortOptions.len != 0:
|
|
||||||
p.kind = cmdShortOption
|
|
||||||
p.key = p.remainingShortOptions[0..0]
|
|
||||||
p.val = ""
|
|
||||||
p.remainingShortOptions = p.remainingShortOptions[1..p.remainingShortOptions.len-1]
|
|
||||||
return
|
|
||||||
|
|
||||||
if p.pos >= p.cmd.len:
|
|
||||||
p.kind = cmdEnd
|
|
||||||
return
|
|
||||||
|
|
||||||
let token = p.cmd[p.pos]
|
|
||||||
p.pos += 1
|
|
||||||
|
|
||||||
if token.startsWith("--"):
|
|
||||||
p.kind = cmdLongOption
|
|
||||||
nextOption(p, token[2..token.len-1], allowEmpty=true)
|
|
||||||
elif token.startsWith("-"):
|
|
||||||
p.kind = cmdShortOption
|
|
||||||
nextOption(p, token[1..token.len-1], allowEmpty=true)
|
|
||||||
else:
|
|
||||||
p.kind = cmdArgument
|
|
||||||
p.key = token
|
|
||||||
p.val = ""
|
|
||||||
|
|
||||||
proc cmdLineRest*(p: OptParser): string {.rtl, extern: "npo2$1".} =
|
|
||||||
## Returns the part of command line string that has not been parsed yet,
|
|
||||||
## properly quoted.
|
|
||||||
return p.cmd[p.pos..p.cmd.len-1].quoteShellCommand
|
|
||||||
|
|
||||||
type
|
|
||||||
GetoptResult* = tuple[kind: CmdLineKind, key, val: string]
|
|
||||||
|
|
||||||
iterator getopt*(p: var OptParser): GetoptResult =
|
|
||||||
## This is an convenience iterator for iterating over the given OptParser object.
|
|
||||||
## Example:
|
|
||||||
##
|
|
||||||
## .. code-block:: nim
|
|
||||||
## var p = initOptParser("--left --debug:3 -l=4 -r:2")
|
|
||||||
## for kind, key, val in p.getopt():
|
|
||||||
## case kind
|
|
||||||
## of cmdArgument:
|
|
||||||
## filename = key
|
|
||||||
## of cmdLongOption, cmdShortOption:
|
|
||||||
## case key
|
|
||||||
## of "help", "h": writeHelp()
|
|
||||||
## of "version", "v": writeVersion()
|
|
||||||
## of cmdEnd: assert(false) # cannot happen
|
|
||||||
## if filename == "":
|
|
||||||
## # no filename has been given, so we show the help:
|
|
||||||
## writeHelp()
|
|
||||||
p.pos = 0
|
|
||||||
while true:
|
|
||||||
next(p)
|
|
||||||
if p.kind == cmdEnd: break
|
|
||||||
yield (p.kind, p.key, p.val)
|
|
||||||
|
|
||||||
when declared(paramCount):
|
|
||||||
iterator getopt*(): GetoptResult =
|
|
||||||
## This is an convenience iterator for iterating over the command line arguments.
|
|
||||||
## This create a new OptParser object.
|
|
||||||
## See above for a more detailed example
|
|
||||||
##
|
|
||||||
## .. code-block:: nim
|
|
||||||
## for kind, key, val in getopt():
|
|
||||||
## # this will iterate over all arguments passed to the cmdline.
|
|
||||||
## continue
|
|
||||||
##
|
|
||||||
var p = initOptParser()
|
|
||||||
while true:
|
|
||||||
next(p)
|
|
||||||
if p.kind == cmdEnd: break
|
|
||||||
yield (p.kind, p.key, p.val)
|
|
||||||
|
|
||||||
{.pop.}
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
## This module is a deprecated alias for the `sha1` module.
|
## This module is a deprecated alias for the `sha1` module. Deprecated since 0.18.1.
|
||||||
|
|
||||||
{.deprecated: "use `std/sha1` instead".}
|
{.deprecated: "use `std/sha1` instead".}
|
||||||
|
|
||||||
include "../std/sha1"
|
import "../std/sha1"
|
||||||
|
export sha1
|
||||||
|
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
|
|
||||||
{.deprecated: "Use the new 'sugar' module instead".}
|
|
||||||
|
|
||||||
include sugar
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# Include file that implements 'getEnv' and friends. Do not import it!
|
# Include file that implements 'getEnv' and friends. Do not import it!
|
||||||
|
|
||||||
when not declared(os) and not declared(ospaths):
|
when not declared(os):
|
||||||
{.error: "This is an include file for os.nim!".}
|
{.error: "This is an include file for os.nim!".}
|
||||||
|
|
||||||
when not defined(nimscript):
|
when not defined(nimscript):
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# Include file that implements 'osErrorMsg' and friends. Do not import it!
|
# Include file that implements 'osErrorMsg' and friends. Do not import it!
|
||||||
|
|
||||||
when not declared(os) and not declared(ospaths):
|
when not declared(os):
|
||||||
{.error: "This is an include file for os.nim!".}
|
{.error: "This is an include file for os.nim!".}
|
||||||
|
|
||||||
when not defined(nimscript):
|
when not defined(nimscript):
|
||||||
|
|
|
||||||
|
|
@ -602,7 +602,6 @@ proc makeRawTest(test, options: string, cat: Category): TTest {.used.} =
|
||||||
|
|
||||||
# TODO: fix these files
|
# TODO: fix these files
|
||||||
const disabledFilesDefault = @[
|
const disabledFilesDefault = @[
|
||||||
"LockFreeHash.nim",
|
|
||||||
"tableimpl.nim",
|
"tableimpl.nim",
|
||||||
"setimpl.nim",
|
"setimpl.nim",
|
||||||
"hashcommon.nim",
|
"hashcommon.nim",
|
||||||
|
|
|
||||||
|
|
@ -1,48 +0,0 @@
|
||||||
discard """
|
|
||||||
output: '''
|
|
||||||
HandlePrintEvent: Output -> Handled print event
|
|
||||||
HandlePrintEvent2: Output -> printing for ME
|
|
||||||
HandlePrintEvent2: Output -> printing for ME
|
|
||||||
'''
|
|
||||||
"""
|
|
||||||
|
|
||||||
import events
|
|
||||||
|
|
||||||
type
|
|
||||||
PrintEventArgs = object of EventArgs
|
|
||||||
user*: string
|
|
||||||
|
|
||||||
proc handleprintevent*(e: EventArgs) =
|
|
||||||
write(stdout, "HandlePrintEvent: Output -> Handled print event\n")
|
|
||||||
|
|
||||||
proc handleprintevent2*(e: EventArgs) =
|
|
||||||
var args: PrintEventArgs = PrintEventArgs(e)
|
|
||||||
write(stdout, "HandlePrintEvent2: Output -> printing for " & args.user)
|
|
||||||
|
|
||||||
var ee = initEventEmitter()
|
|
||||||
|
|
||||||
var eventargs: PrintEventArgs
|
|
||||||
eventargs.user = "ME\n"
|
|
||||||
|
|
||||||
##method one test
|
|
||||||
|
|
||||||
ee.on("print", handleprintevent)
|
|
||||||
ee.on("print", handleprintevent2)
|
|
||||||
|
|
||||||
ee.emit("print", eventargs)
|
|
||||||
|
|
||||||
##method two test
|
|
||||||
|
|
||||||
type
|
|
||||||
SomeObject = object of RootObj
|
|
||||||
printEvent: EventHandler
|
|
||||||
|
|
||||||
var obj: SomeObject
|
|
||||||
obj.printEvent = initEventHandler("print")
|
|
||||||
obj.printEvent.addHandler(handleprintevent2)
|
|
||||||
|
|
||||||
ee.emit(obj.printEvent, eventargs)
|
|
||||||
|
|
||||||
obj.printEvent.removeHandler(handleprintevent2)
|
|
||||||
|
|
||||||
ee.emit(obj.printEvent, eventargs)
|
|
||||||
|
|
@ -1,66 +1,17 @@
|
||||||
discard """
|
discard """
|
||||||
cmd: "nim $target --threads:on $options $file"
|
cmd: "nim $target --threads:on $options $file"
|
||||||
errormsg: "illegal recursion in type 'TIRC'"
|
errormsg: "illegal recursion in type 'TIRC'"
|
||||||
line: 16
|
line: 12
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import events
|
|
||||||
import net
|
import net
|
||||||
import strutils
|
import strutils
|
||||||
import os
|
import os
|
||||||
|
|
||||||
type
|
type
|
||||||
TMessageReceivedEventArgs = object of EventArgs
|
|
||||||
Nick*: string
|
|
||||||
Message*: string
|
|
||||||
TIRC = object
|
TIRC = object
|
||||||
EventEmitter: EventEmitter
|
|
||||||
MessageReceivedHandler*: EventHandler
|
|
||||||
Socket: Socket
|
Socket: Socket
|
||||||
Thread: Thread[TIRC]
|
Thread: Thread[TIRC]
|
||||||
|
|
||||||
proc initIRC*(): TIRC =
|
proc initIRC*(): TIRC =
|
||||||
result.Socket = socket()
|
result.Socket = socket()
|
||||||
result.EventEmitter = initEventEmitter()
|
|
||||||
result.MessageReceivedHandler = initEventHandler("MessageReceived")
|
|
||||||
|
|
||||||
proc IsConnected*(irc: var TIRC): bool =
|
|
||||||
return running(irc.Thread)
|
|
||||||
|
|
||||||
|
|
||||||
proc sendRaw*(irc: var TIRC, message: string) =
|
|
||||||
irc.Socket.send(message & "\r\L")
|
|
||||||
proc handleData(irc: TIRC) {.thread.} =
|
|
||||||
var connected = False
|
|
||||||
while connected:
|
|
||||||
var tup = @[irc.Socket]
|
|
||||||
var o = select(tup, 200)
|
|
||||||
echo($o)
|
|
||||||
echo($len(tup))
|
|
||||||
if len(tup) == 1:
|
|
||||||
#Connected
|
|
||||||
connected = True
|
|
||||||
|
|
||||||
#Parse data here
|
|
||||||
|
|
||||||
else:
|
|
||||||
#Disconnected
|
|
||||||
connected = False
|
|
||||||
return
|
|
||||||
|
|
||||||
proc Connect*(irc: var TIRC, nick: string, host: string, port: int = 6667) =
|
|
||||||
connect(irc.Socket, host, TPort(port), TDomain.AF_INET)
|
|
||||||
send(irc.Socket,"USER " & nick & " " & nick & " " & nick & " " & nick & "\r\L")
|
|
||||||
send(irc.Socket,"NICK " & nick & "\r\L")
|
|
||||||
var thread: Thread[TIRC]
|
|
||||||
createThread(thread, handleData, irc)
|
|
||||||
irc.Thread = thread
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
when true:
|
|
||||||
var irc = initIRC()
|
|
||||||
irc.Connect("AmryBot[Nim]","irc.freenode.net",6667)
|
|
||||||
irc.sendRaw("JOIN #nim")
|
|
||||||
os.Sleep(4000)
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue