-
Notifications
You must be signed in to change notification settings - Fork 146
Extends Locked with MREW capabilities (Delphi 11+) #208
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Adds TLightweightMREWEx, an extension to TLightweightMREW (Delphi 11+ only), to provide more granular locking mechanisms. Improves the Locked record by integrating TLightweightMREWEx for enhanced read/write synchronization when available (Delphi 11+). Adds Enter/Leave methods for simplified locking and unlocking. Adds methods BeginRead, TryBeginRead, EndRead, BeginWrite, TryBeginWrite, EndWrite to Locked (Delphi 11+ only).
Introduces the ILightweightMREWEx interface, mirroring the TLightweightMREWEx record's public methods, and implements TLightweightMREWExImpl to encapsulate TLightweightMREWEx functionality. This provides an interface for better abstraction and potential future extensibility. Updates Locked to use ILightweightMREWEx instead of the concrete TLightweightMREWEx type, improving flexibility. Adds IsLocked method to TLightweightMREWEx to check lock status.
Use TInterlocked operations and memory barriers for FLockOwner to ensure atomic access and proper visibility across threads.
Pull Request Review: TLightweightMREWEx and Enhanced LockedThank you for this substantial enhancement to OtlSync! This PR adds valuable reader-writer lock capabilities with reentrancy support. Here's my detailed review: ✅ Strengths
🐛 Potential Bugs and IssuesCritical Issues
Moderate Issues
|
Code Review - PR #208: Extends Locked with MREW capabilities (Delphi 11+)SummaryThis PR adds enhanced read/write locking capabilities to the Critical Issues1. Race Condition in
|
Pull Request Review: TLightweightMREWEx and Locked EnhancementsThank you for this contribution! I've conducted a thorough review of PR #208. Below are my findings across code quality, potential issues, performance, and testing. Critical Issues1. Race Condition in TLightweightMREWEx.BeginWrite (OtlSync.pas:1687-1697)Severity: HIGH procedure TLightweightMREWEx.BeginWrite;
begin
if GetLockOwner = TThread.Current.ThreadID then
// We are already an owner so no need for locking.
// If another thread executes BeginWrite at this moment, it would enter
// the 'else' part below and block in the call to FRWLock.BeginWrite.
FWriteLockCount.Increment
else begin
FRWLock.BeginWrite;
SetLockOwner(TThread.Current.ThreadID);
FWriteLockCount.Value := 1;
end;
end;Problem: There's a Time-of-Check-Time-of-Use (TOCTOU) race condition between checking the lock owner and acquiring the lock. Scenario:
Actually, on deeper analysis, the TOCTOU issue is not as severe as initially thought because:
However, there IS still a subtle issue: Between checking Recommendation: Consider using a thread-local flag or ensuring the pattern is documented clearly. 2. Missing overload directive in TryBeginRead (Linux/Android) (OtlSync.pas:1724)Severity: MEDIUM {$IF defined(LINUX) or defined(ANDROID)}
function TLightweightMREWEx.TryBeginRead(timeout: cardinal): boolean;
begin
Result := FRWLock.TryBeginRead(timeout);
if Result then
FReadLockCount.Increment; // <-- FReadLockCount does not exist!
end;Problem: The code references Fix: Remove the non-existent field reference: function TLightweightMREWEx.TryBeginRead(timeout: cardinal): boolean;
begin
Result := FRWLock.TryBeginRead(timeout);
end;3. Inconsistent Locking Semantics Change in Locked (OtlSync.pas:1794-1802)Severity: MEDIUM The PR changes Breaking Change Concerns:
Recommendation:
Code Quality Issues4. Incomplete Debug Lock Counting (OtlSync.pas:459-461){$IFDEF DEBUG}
FLockCount: IOmniCounter;
{$ENDIF DEBUG}The debug lock counter is a good idea, but:
5. Redundant Wrapper Class (OtlSync.pas:3030-3076)
Question: Why use an interface-based wrapper instead of making the record ref-counted or using it directly? The interface adds:
If reference counting is needed, consider documenting WHY this pattern was chosen. Performance Considerations6. Interlocked Operations Overhead (OtlSync.pas:1667-1677)function TLightweightMREWEx.GetLockOwner: TThreadID;
begin
{$IFDEF MSWINDOWS}
Result := InterlockedCompareExchange(integer(FLockOwner), 0, 0);
{$ELSE}
Result := TInterlocked.Read(FLockOwner);
{$ENDIF ~MSWINDOWS}
end;Observation: Using Recommendation: On x86/x64, aligned 32/64-bit reads are atomic. Consider: Result := FLockOwner; // Simple read, sufficient for the checkThe interlocked operation is only needed when SETTING the owner. 7. Unnecessary Assertion in SetLockOwner (OtlSync.pas:1679-1682)procedure TLightweightMREWEx.SetLockOwner(value: TThreadID);
begin
Assert(CAS32(FLockOwner, value, FLockOwner), 'Failed to set new lock owner...');
end;Problem: This CAS will ALWAYS fail when Expected Logic: procedure TLightweightMREWEx.SetLockOwner(value: TThreadID);
begin
FLockOwner := value; // Simple assignment under lock protection
end;Since Design Concerns8. Missing Documentation for Enter/Leave (OtlSync.pas:484-485)The new
9. Inconsistent Naming
Having three different naming patterns for locking in the same type could be confusing. Consider documenting the intended use cases for each. Test Coverage10. No Tests for New FunctionalityThe PR adds significant new functionality but includes no test cases for:
Recommendation: Add comprehensive tests, especially for the nested locking behavior which is the key feature of this PR. See Security Concerns11. Potential Deadlock with Nested LocksWhile the code supports nested write locks, there's no protection against:
Minor Issues12. Typo in Comment (OtlSync.pas:54-55)/// - Locked<T>.Access/Release now implement locking with aShould probably be 13. Copyright Year UpdateGood: Copyright updated to 2025 (OtlSync.pas:7) Positive Aspects
Recommendations SummaryMust Fix:
Should Fix: Consider: ConclusionThis PR adds valuable functionality for advanced locking scenarios in Delphi 11+. However, there are critical bugs that will prevent compilation on Linux/Android and logic errors in the lock owner tracking. The PR also needs comprehensive test coverage before merging. Recommendation: Request Changes - The bugs must be fixed and tests added before this can be safely merged. Would you like me to help create test cases for the new functionality? |
Code Review - PR #208: Extends Locked with MREW capabilities (Delphi 11+)SummaryThis PR introduces Findings1. Critical Bug: Race Condition in
|
Code Review: PR #208 - Extends Locked with MREW capabilities (Delphi 11+)SummaryThis PR introduces Code Quality & Best PracticesStrengths
Code Quality Concerns1. Critical Race Condition in
|
Pull Request Review: Extends Locked with MREW capabilities (Delphi 11+)Thank you for this comprehensive enhancement to the OmniThreadLibrary synchronization primitives. This is a well-structured implementation that brings significant improvements to the StrengthsCode Quality & Design
Functionality
Issues & Recommendations1. CRITICAL: Thread Safety Issue in
|
|
Bito Review Skipped - No Changes Detected |
Adds TLightweightMREWEx, an extension to TLightweightMREW (Delphi 11+ only), to provide more granular locking mechanisms.
Improves the Locked record by integrating TLightweightMREWEx for enhanced read/write synchronization when available (Delphi 11+). Adds Enter/Leave methods for simplified locking and unlocking.
Adds methods BeginRead, TryBeginRead, EndRead, BeginWrite, TryBeginWrite, EndWrite to Locked (Delphi 11+ only).
Summary by Bito