lkqueueeventer.inc 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  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: ' + StrError(fpGetErrno));
  14. end;
  15. destructor TLKQueueEventer.Destroy;
  16. begin
  17. fpClose(FQueue);
  18. inherited Destroy;
  19. end;
  20. function TLKQueueEventer.GetTimeout: Integer;
  21. begin
  22. Result := FTimeout.tv_sec + FTimeout.tv_nsec * 1000 * 1000;
  23. end;
  24. procedure TLKQueueEventer.SetTimeout(const Value: Integer);
  25. begin
  26. if Value >= 0 then begin
  27. FTimeout.tv_sec := Value div 1000;
  28. FTimeout.tv_nsec := (Value mod 1000) * 1000;
  29. end else begin
  30. FTimeout.tv_sec := -1;
  31. FTimeout.tv_nsec := 0;
  32. end;
  33. end;
  34. procedure TLKQueueEventer.HandleIgnoreRead(aHandle: TLHandle);
  35. const
  36. INBOOL: array[Boolean] of Integer = (EV_ENABLE, EV_DISABLE);
  37. begin
  38. EV_SET(@FChanges[FFreeSlot], aHandle.FHandle, EVFILT_READ,
  39. INBOOL[aHandle.IgnoreRead], 0, 0, Pointer(aHandle));
  40. Inc(FFreeSlot);
  41. if FFreeSlot > Length(FChanges) then
  42. Inflate;
  43. end;
  44. procedure TLKQueueEventer.Inflate;
  45. const
  46. BASE_SIZE = 100;
  47. var
  48. OldLength: Integer;
  49. begin
  50. OldLength := Length(FChanges);
  51. if OldLength > 1 then begin
  52. SetLength(FChanges, Sqr(OldLength));
  53. SetLength(FEvents, Sqr(OldLength));
  54. end else begin
  55. SetLength(FChanges, BASE_SIZE);
  56. SetLength(FEvents, BASE_SIZE);
  57. end;
  58. end;
  59. function TLKQueueEventer.AddHandle(aHandle: TLHandle): Boolean;
  60. begin
  61. Result := inherited AddHandle(aHandle);
  62. if FFreeSlot > Length(FChanges) then
  63. Inflate;
  64. EV_SET(@FChanges[FFreeSlot], aHandle.FHandle, EVFILT_WRITE,
  65. EV_ADD or EV_CLEAR, 0, 0, Pointer(aHandle));
  66. Inc(FFreeSlot);
  67. if FFreeSlot > Length(FChanges) then
  68. Inflate;
  69. if not aHandle.FIgnoreRead then begin
  70. EV_SET(@FChanges[FFreeSlot], aHandle.FHandle, EVFILT_READ,
  71. EV_ADD, 0, 0, Pointer(aHandle));
  72. Inc(FFreeSlot);
  73. end;
  74. end;
  75. function TLKQueueEventer.CallAction: Boolean;
  76. var
  77. i, n: Integer;
  78. Temp: TLHandle;
  79. begin
  80. Result := False;
  81. if FInLoop then
  82. Exit;
  83. if FTimeout.tv_sec >= 0 then
  84. n := KEvent(FQueue, @FChanges[0], FFreeSlot,
  85. @FEvents[0], Length(FEvents), @FTimeout)
  86. else
  87. n := KEvent(FQueue, @FChanges[0], FFreeSlot,
  88. @FEvents[0], Length(FEvents), nil);
  89. FFreeSlot := 0;
  90. if n < 0 then
  91. Bail('Error on kqueue', LSocketError);
  92. Result := n > 0;
  93. if Result then begin
  94. FInLoop := True;
  95. for i := 0 to n-1 do begin
  96. Temp := TLHandle(FEvents[i].uData);
  97. if (not Temp.FDispose)
  98. and (FEvents[i].Filter = EVFILT_WRITE) then
  99. if Assigned(Temp.FOnWrite) and not Temp.IgnoreWrite then
  100. Temp.FOnWrite(Temp);
  101. if (not Temp.FDispose)
  102. and (FEvents[i].Filter = EVFILT_READ) then
  103. if Assigned(Temp.FOnRead) and not Temp.IgnoreRead then
  104. Temp.FOnRead(Temp);
  105. if (not Temp.FDispose)
  106. and ((FEvents[i].Flags and EV_ERROR) > 0) then
  107. if Assigned(Temp.FOnError) and not Temp.IgnoreError then
  108. Temp.FOnError(Temp, 'Handle error' + LStrError(LSocketError));
  109. if Temp.FDispose then
  110. AddForFree(Temp);
  111. end;
  112. FInLoop := False;
  113. if Assigned(FFreeRoot) then
  114. FreeHandles;
  115. end;
  116. end;
  117. function BestEventerClass: TLEventerClass;
  118. begin
  119. {$IFNDEF FORCE_SELECT}
  120. Result := TLKQueueEventer;
  121. {$ELSE}
  122. Result := TLSelectEventer;
  123. {$ENDIF}
  124. end;
  125. {$endif} // BSD