FreeBSD support
[lcore.git] / lcoreselect.pas
index ad816002eced002543ec03de43363c7b4331ca24..d3685ae03760f4b81f7e48386fcf8b35a8dd03a1 100644 (file)
@@ -220,10 +220,22 @@ begin
 end;\r
 \r
 \r
+{\r
+select in linux/sysV subtracts from timeout for time spent in it, but in BSD it doesn't\r
+enabling select_no_autotv here makes doSelect mimic the decrement behavior, in case the caller needs it\r
+the caller here in lcoreselect does not need it, and enabling it would have a slight perf hit.\r
+it is safe for this to be enabled even if the OS does it too (it will not subtract twice)\r
+it is currently disabled but can be enabled if needed\r
+}\r
+{$ifndef linux}{-$define select_no_autotv}{$endif}\r
+\r
 Function  doSelect(timeOut:PTimeVal):longint;//inline;\r
 var\r
   localtimeval : ttimeval;\r
   maxslocal    : integer;\r
+  {$ifdef select_no_autotv}\r
+  timeoutcopy,tvstart,tvend : ttimeval;\r
+  {$endif}\r
 begin\r
   //unblock signals\r
   //zeromemory(@sset,sizeof(sset));\r
@@ -243,6 +255,15 @@ begin
   {$ifndef nosignal}\r
     sigprocmask(SIG_UNBLOCK,@blockset,nil);\r
   {$endif}\r
+\r
+  {$ifdef select_no_autotv}\r
+  if assigned(timeout) then begin\r
+    timeoutcopy.tv_sec := timeOut.tv_sec;\r
+    timeoutcopy.tv_usec := timeOut.tv_usec;\r
+    gettimemonotonic(tvstart);\r
+  end;\r
+  {$endif}\r
+\r
   result := select(maxslocal+1,@FDSR,@FDSW,nil,timeout);\r
   if result <= 0 then begin\r
     fd_zero(FDSR);\r
@@ -253,8 +274,27 @@ begin
       end else begin\r
         raise esocketexception.create('select returned error '+inttostr(linuxerror));\r
       end;\r
+    end\r
+  {$ifdef select_no_autotv}\r
+    else if (result = 0) and assigned(timeout) then begin\r
+      //timeout reached: zero the timeval\r
+      timeout.tv_sec := 0;\r
+      timeout.tv_usec := 0;\r
     end;\r
+  end else if assigned(timeout) then begin\r
+    //successful result: subtract elapsed time\r
+    gettimemonotonic(tvend);\r
+    tv_subtract(tvend,tvstart);\r
+    tv_subtract(timeoutcopy,tvend);\r
+    timeout.tv_sec := timeoutcopy.tv_sec;\r
+    timeout.tv_usec := timeoutcopy.tv_usec;\r
+    if (timeout.tv_sec < 0) then begin\r
+      timeout.tv_sec := 0;\r
+      timeout.tv_usec := 0;\r
+    end;\r
+  {$endif} //select_no_autotv\r
   end;\r
+\r
   {$ifndef nosignal}\r
     sigprocmask(SIG_BLOCK,@blockset,nil);\r
   {$endif}\r