@@ -247,18 +247,18 @@ when defined(windows) or defined(nimdoc):
247
247
ioPort: Handle
248
248
handles: HashSet[AsyncFD]
249
249
250
- CustomOverlapped = object of OVERLAPPED
250
+ CustomObj = object of OVERLAPPED
251
251
data* : CompletionData
252
252
253
- PCustomOverlapped * = ref CustomOverlapped
253
+ CustomRef * = ref CustomObj
254
254
255
255
AsyncFD* = distinct int
256
256
257
257
PostCallbackData = object
258
258
ioPort: Handle
259
259
handleFd: AsyncFD
260
260
waitFd: Handle
261
- ovl: owned PCustomOverlapped
261
+ ovl: owned CustomRef
262
262
PostCallbackDataPtr = ptr PostCallbackData
263
263
264
264
AsyncEventImpl = object
@@ -336,13 +336,15 @@ when defined(windows) or defined(nimdoc):
336
336
337
337
var lpNumberOfBytesTransferred: DWORD
338
338
var lpCompletionKey: ULONG_PTR
339
- var customOverlapped: PCustomOverlapped
339
+ var customOverlapped: CustomRef
340
340
let res = getQueuedCompletionStatus(p.ioPort,
341
341
addr lpNumberOfBytesTransferred, addr lpCompletionKey,
342
342
cast[ptr POVERLAPPED](addr customOverlapped), llTimeout).bool
343
343
result = true
344
- when defined(gcDestructors):
345
- GC_ref(customOverlapped)
344
+ # For 'gcDestructors' the destructor of 'customOverlapped' will
345
+ # be called at the end and we are the only owner here. This means
346
+ # We do not have to 'GC_unref(customOverlapped)' because the destructor
347
+ # does that for us.
346
348
347
349
# http://stackoverflow.com/a/12277264/492186
348
350
# TODO: http://www.serverframework.com/handling-multiple-pending-socket-read-and-write-operations.html
@@ -359,7 +361,8 @@ when defined(windows) or defined(nimdoc):
359
361
if customOverlapped.data.cell.data != nil:
360
362
system.dispose(customOverlapped.data.cell)
361
363
362
- GC_unref(customOverlapped)
364
+ when not defined(gcDestructors):
365
+ GC_unref(customOverlapped)
363
366
else:
364
367
let errCode = osLastError()
365
368
if customOverlapped != nil:
@@ -368,7 +371,8 @@ when defined(windows) or defined(nimdoc):
368
371
lpNumberOfBytesTransferred, errCode)
369
372
if customOverlapped.data.cell.data != nil:
370
373
system.dispose(customOverlapped.data.cell)
371
- GC_unref(customOverlapped)
374
+ when not defined(gcDestructors):
375
+ GC_unref(customOverlapped)
372
376
else:
373
377
if errCode.int32 == WAIT_TIMEOUT:
374
378
# Timed out
@@ -409,6 +413,13 @@ when defined(windows) or defined(nimdoc):
409
413
getAcceptExSockAddrs = cast[WSAPROC_GETACCEPTEXSOCKADDRS](fun)
410
414
close(dummySock)
411
415
416
+ proc newCustom*(): CustomRef =
417
+ result = CustomRef() # 0
418
+ GC_ref(result ) # 1 prevent destructor from doing a premature free.
419
+ # destructor of newCustom's caller --> 0. This means
420
+ # Windows holds a ref for us with RC == 0 (single owner).
421
+ # This is passed back to us in the IO completion port.
422
+
412
423
proc recv*(socket: AsyncFD, size: int ,
413
424
flags = {SocketFlag.SafeDisconn}): owned (Future[string ]) =
414
425
## Reads **up to** ``size`` bytes from ``socket``. Returned future will
@@ -435,8 +446,7 @@ when defined(windows) or defined(nimdoc):
435
446
436
447
var bytesReceived: DWORD
437
448
var flagsio = flags.toOSFlags().DWORD
438
- var ol = PCustomOverlapped()
439
- GC_ref(ol)
449
+ var ol = newCustom()
440
450
ol.data = CompletionData(fd: socket, cb:
441
451
proc (fd: AsyncFD, bytesCount: DWORD, errcode: OSErrorCode) =
442
452
if not retFuture.finished:
@@ -512,8 +522,7 @@ when defined(windows) or defined(nimdoc):
512
522
513
523
var bytesReceived: DWORD
514
524
var flagsio = flags.toOSFlags().DWORD
515
- var ol = PCustomOverlapped()
516
- GC_ref(ol)
525
+ var ol = newCustom()
517
526
ol.data = CompletionData(fd: socket, cb:
518
527
proc (fd: AsyncFD, bytesCount: DWORD, errcode: OSErrorCode) =
519
528
if not retFuture.finished:
@@ -565,8 +574,7 @@ when defined(windows) or defined(nimdoc):
565
574
dataBuf.len = size.ULONG
566
575
567
576
var bytesReceived, lowFlags: DWORD
568
- var ol = PCustomOverlapped()
569
- GC_ref(ol)
577
+ var ol = newCustom()
570
578
ol.data = CompletionData(fd: socket, cb:
571
579
proc (fd: AsyncFD, bytesCount: DWORD, errcode: OSErrorCode) =
572
580
if not retFuture.finished:
@@ -616,8 +624,7 @@ when defined(windows) or defined(nimdoc):
616
624
zeroMem(addr(staddr[ 0]), 128 )
617
625
copyMem(addr (staddr[0 ]), saddr, saddrLen)
618
626
619
- var ol = PCustomOverlapped()
620
- GC_ref(ol)
627
+ var ol = newCustom()
621
628
ol.data = CompletionData(fd: socket, cb:
622
629
proc (fd: AsyncFD, bytesCount: DWORD, errcode: OSErrorCode) =
623
630
if not retFuture.finished:
@@ -658,8 +665,7 @@ when defined(windows) or defined(nimdoc):
658
665
var bytesReceived = 0.DWORD
659
666
var lowFlags = 0.DWORD
660
667
661
- var ol = PCustomOverlapped()
662
- GC_ref(ol)
668
+ var ol = newCustom()
663
669
ol.data = CompletionData(fd: socket, cb:
664
670
proc (fd: AsyncFD, bytesCount: DWORD, errcode: OSErrorCode) =
665
671
if not retFuture.finished:
@@ -754,8 +760,7 @@ when defined(windows) or defined(nimdoc):
754
760
clientSock.close()
755
761
retFuture.fail(getCurrentException())
756
762
757
- var ol = PCustomOverlapped()
758
- GC_ref(ol)
763
+ var ol = newCustom()
759
764
ol.data = CompletionData(fd: socket, cb:
760
765
proc (fd: AsyncFD, bytesCount: DWORD, errcode: OSErrorCode) =
761
766
if not retFuture.finished:
@@ -799,7 +804,7 @@ when defined(windows) or defined(nimdoc):
799
804
800
805
{.push stackTrace: off .}
801
806
proc waitableCallback(param: pointer ,
802
- timerOrWaitFired: WINBOOL): void {.stdcall.} =
807
+ timerOrWaitFired: WINBOOL) {.stdcall.} =
803
808
var p = cast[PostCallbackDataPtr](param)
804
809
discard postQueuedCompletionStatus(p.ioPort, timerOrWaitFired.DWORD,
805
810
ULONG_PTR(p.handleFd),
@@ -815,8 +820,7 @@ when defined(windows) or defined(nimdoc):
815
820
var pcd = cast[PostCallbackDataPtr](allocShared0(sizeof(PostCallbackData)))
816
821
pcd.ioPort = p.ioPort
817
822
pcd.handleFd = fd
818
- var ol = PCustomOverlapped()
819
- GC_ref(ol)
823
+ var ol = newCustom()
820
824
821
825
ol.data = CompletionData(fd: fd, cb:
822
826
proc(fd: AsyncFD, bytesCount: DWORD, errcode: OSErrorCode) {.gcsafe.} =
@@ -931,8 +935,7 @@ when defined(windows) or defined(nimdoc):
931
935
let handleFD = AsyncFD(hEvent)
932
936
pcd.ioPort = p.ioPort
933
937
pcd.handleFd = handleFD
934
- var ol = PCustomOverlapped()
935
- GC_ref(ol)
938
+ var ol = newCustom()
936
939
ol.data.fd = handleFD
937
940
ol.data.cb = handleCallback
938
941
# We need to protect our callback environment value, so GC will not free it
@@ -1621,8 +1624,7 @@ when defined(windows) or defined(nimdoc):
1621
1624
let retFuture = newFuture[void ]("doConnect")
1622
1625
result = retFuture
1623
1626
1624
- var ol = PCustomOverlapped()
1625
- GC_ref(ol)
1627
+ var ol = newCustom()
1626
1628
ol.data = CompletionData(fd: socket, cb:
1627
1629
proc (fd: AsyncFD, bytesCount: DWORD, errcode: OSErrorCode) =
1628
1630
if not retFuture.finished:
0 commit comments