lkqueueeventer.inc 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. {% lkqueueeventer.inc included by levents.pas }
  2. {$ifdef BSD}
  3. { TLKQueueEventer }
  4. constructor TLKQueueEventer.Create;
  5. begin
  6. inherited Create;
  7. Inflate;
  8. FFreeSlot := 0;
  9. FTimeout.tv_sec := 0;
  10. FTimeout.tv_nsec := 0;
  11. FQueue := KQueue;
  12. if FQueue < 0 then
  13. raise Exception.Create('Unable to create kqueue');
  14. end;
  15. destructor TLKQueueEventer.Destroy;
  16. begin
  17. fpClose(FQueue);
  18. inherited Destroy;
  19. end;
  20. function TLKQueueEventer.GetTimeout: DWord;
  21. begin
  22. Result := FTimeout.tv_sec + FTimeout.tv_nsec * 1000 * 1000;
  23. end;
  24. procedure TLKQueueEventer.SetTimeout(const Value: DWord);
  25. begin
  26. FTimeout.tv_sec := Value div 1000;
  27. FTimeout.tv_nsec := (Value mod 1000) * 1000;
  28. end;
  29. procedure TLKQueueEventer.HandleIgnoreRead(aHandle: TLHandle);
  30. const
  31. INBOOL: array[Boolean] of Integer = (EV_ENABLE, EV_DISABLE);
  32. begin
  33. EV_SET(@FChanges[FFreeSlot], aHandle.FHandle, EVFILT_READ,
  34. INBOOL[aHandle.IgnoreRead], 0, 0, Pointer(aHandle));
  35. Inc(FFreeSlot);
  36. if FFreeSlot > Length(FChanges) then
  37. Inflate;
  38. end;
  39. procedure TLKQueueEventer.Inflate;
  40. const
  41. BASE_SIZE = 100;
  42. var
  43. OldLength: Integer;
  44. begin
  45. OldLength := Length(FChanges);
  46. if OldLength > 1 then begin
  47. SetLength(FChanges, Sqr(OldLength));
  48. SetLength(FEvents, Sqr(OldLength));
  49. end else begin
  50. SetLength(FChanges, BASE_SIZE);
  51. SetLength(FEvents, BASE_SIZE);
  52. end;
  53. end;
  54. function TLKQueueEventer.AddHandle(aHandle: TLHandle): Boolean;
  55. begin
  56. Result := inherited AddHandle(aHandle);
  57. if FFreeSlot > Length(FChanges) then
  58. Inflate;
  59. EV_SET(@FChanges[FFreeSlot], aHandle.FHandle, EVFILT_WRITE,
  60. EV_ADD or EV_CLEAR, 0, 0, Pointer(aHandle));
  61. Inc(FFreeSlot);
  62. if FFreeSlot > Length(FChanges) then
  63. Inflate;
  64. if not aHandle.FIgnoreRead then begin
  65. EV_SET(@FChanges[FFreeSlot], aHandle.FHandle, EVFILT_READ,
  66. EV_ADD, 0, 0, Pointer(aHandle));
  67. Inc(FFreeSlot);
  68. end;
  69. end;
  70. function TLKQueueEventer.CallAction: Boolean;
  71. var
  72. i, n: Integer;
  73. Temp: TLHandle;
  74. begin
  75. n := KEvent(FQueue, @FChanges[0], FFreeSlot,
  76. @FEvents[0], Length(FEvents), @FTimeout);
  77. FFreeSlot := 0;
  78. if n < 0 then
  79. Bail('Error on kqueue: ', LSocketError);
  80. Result := n > 0;
  81. if Result then begin
  82. FInLoop := True;
  83. for i := 0 to n-1 do begin
  84. Temp := TLHandle(FEvents[i].uData);
  85. if (not Temp.FDispose)
  86. and (FEvents[i].Filter = EVFILT_WRITE) then
  87. if Assigned(Temp.FOnWrite) and not Temp.IgnoreWrite then
  88. Temp.FOnWrite(Temp);
  89. if (not Temp.FDispose)
  90. and (FEvents[i].Filter = EVFILT_READ) then
  91. if Assigned(Temp.FOnRead) and not Temp.IgnoreRead then
  92. Temp.FOnRead(Temp);
  93. if (not Temp.FDispose)
  94. and ((FEvents[i].Flags and EV_ERROR) > 0) then
  95. if Assigned(Temp.FOnError) and not Temp.IgnoreError then
  96. Temp.FOnError(Temp, 'Handle error' + LStrError(LSocketError));
  97. if Temp.FDispose then
  98. AddForFree(Temp);
  99. end;
  100. FInLoop := False;
  101. if Assigned(FFreeRoot) then
  102. FreeHandles;
  103. end;
  104. end;
  105. function BestEventerClass: TLEventerClass;
  106. begin
  107. Result := TLKQueueEventer;
  108. end;
  109. {$endif} // BSD