Skip to content

Conversation

Copilot
Copy link
Contributor

@Copilot Copilot AI commented Oct 2, 2025

Summary

This PR addresses feedback from #2427 to review lock usage versus ConcurrentDictionary for interrupt state management in the Tca955x driver. The goal was to improve consistency and thread safety by using ConcurrentDictionary where appropriate while documenting cases where locks remain necessary.

Changes

1. Converted _interruptPinsSubscribedEvents to ConcurrentDictionary

Before:

private readonly Dictionary<int, PinEventTypes> _interruptPinsSubscribedEvents = new Dictionary<int, PinEventTypes>();

After:

private readonly ConcurrentDictionary<int, PinEventTypes> _interruptPinsSubscribedEvents = new ConcurrentDictionary<int, PinEventTypes>();

This provides consistency with _eventHandlers and _interruptLastInputValues, which already use ConcurrentDictionary. All three collections now use the same thread-safe pattern for interrupt state management.

2. Reduced Lock Scope

AddCallbackForPinValueChangedEvent:

  • Moved subscription state updates outside the lock
  • Only the I2C read operation remains locked
  • Reduces lock contention while maintaining safety

RemoveCallbackForPinValueChangedEvent:

  • Removed lock entirely
  • Now uses only thread-safe ConcurrentDictionary operations

3. Comprehensive Lock Documentation

Added clear comments explaining why each lock is necessary:

// Lock protects:
// 1. I2C bus access - I2C operations must be atomic and sequential
// 2. _pinValues dictionary - tightly coupled with I2C read/write operations
// 3. Interrupt task coordination - _interruptProcessingTask and _interruptPending state
private object _interruptHandlerLock = new object();

Each of the 8 remaining lock statements now has an inline comment explaining its purpose (I2C bus access, task coordination, etc.).

Why Some Locks Remain

I2C Bus Operations (5 locks)

The I2C protocol requires atomic, sequential access. Read-modify-write sequences cannot be interleaved without corrupting device state. This is a hardware limitation, not a software design choice.

Task Coordination (2 locks)

The _interruptProcessingTask and _interruptPending fields work together as a state machine to queue interrupts. They must be checked and updated atomically to prevent race conditions and ensure only one interrupt processing task runs at a time.

_pinValues Dictionary

This remains a regular Dictionary because it's always accessed within the same critical sections as I2C operations. Converting it to ConcurrentDictionary would provide no benefit since the lock is already held for I2C access.

Benefits

  • More consistent - All interrupt subscription state uses ConcurrentDictionary
  • Better documented - Every lock has clear rationale
  • Reduced contention - Smaller critical sections where possible
  • Maintained safety - All existing thread safety guarantees preserved

Related

Fixes feedback from #2427 (comment: #2427 (comment))

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • 1k9vsblobprodcus379.vsblob.vsassets.io
    • Triggering command: /home/REDACTED/work/iot/iot//.dotnet/dotnet build (dns block)
  • 37cvsblobprodcus359.vsblob.vsassets.io
    • Triggering command: /home/REDACTED/work/iot/iot//.dotnet/dotnet build (dns block)
  • 5dkvsblobprodcus355.vsblob.vsassets.io
    • Triggering command: /home/REDACTED/work/iot/iot//.dotnet/dotnet build (dns block)
  • c50vsblobprodcus330.vsblob.vsassets.io
    • Triggering command: /home/REDACTED/work/iot/iot//.dotnet/dotnet build (dns block)
  • c78vsblobprodcus322.vsblob.vsassets.io
    • Triggering command: /home/REDACTED/work/iot/iot//.dotnet/dotnet build (dns block)
  • dlbvsblobprodcus316.vsblob.vsassets.io
    • Triggering command: /home/REDACTED/work/iot/iot//.dotnet/dotnet build (dns block)
  • fdpvsblobprodcus345.vsblob.vsassets.io
    • Triggering command: /home/REDACTED/work/iot/iot//.dotnet/dotnet build (dns block)
  • kh4vsblobprodcus325.vsblob.vsassets.io
    • Triggering command: /home/REDACTED/work/iot/iot//.dotnet/dotnet build (dns block)
  • l49vsblobprodcus358.vsblob.vsassets.io
    • Triggering command: /home/REDACTED/work/iot/iot//.dotnet/dotnet build (dns block)
  • m6xvsblobprodcus342.vsblob.vsassets.io
    • Triggering command: /home/REDACTED/work/iot/iot//.dotnet/dotnet build (dns block)
  • o3svsblobprodcus318.vsblob.vsassets.io
    • Triggering command: /home/REDACTED/work/iot/iot//.dotnet/dotnet build (dns block)
  • pkvvsblobprodcus321.vsblob.vsassets.io
    • Triggering command: /home/REDACTED/work/iot/iot//.dotnet/dotnet build (dns block)
  • uy6vsblobprodcus34.vsblob.vsassets.io
    • Triggering command: /home/REDACTED/work/iot/iot//.dotnet/dotnet build (dns block)
  • yttvsblobprodcus357.vsblob.vsassets.io
    • Triggering command: /home/REDACTED/work/iot/iot//.dotnet/dotnet build (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Original prompt

This section details on the original issue you should resolve

<issue_title>Review lock usage vs. ConcurrentDictionary in Tca955x interrupt state management</issue_title>
<issue_description>There is a mix of lock-based synchronization and usage of ConcurrentDictionary for interrupt state management in the Tca955x driver. Based on feedback in PR #2427 (see review comment), please review all code in the Tca955x driver where locks are used for state management and evaluate if ConcurrentDictionary can be used instead for consistency and thread safety. If lock usage is still required, add rationale as comments in the code.

References:

Action items:

  • Audit interrupt state management code in Tca955x for locks
  • Replace locks with ConcurrentDictionary where possible
  • Add comments justifying any remaining locks
    </issue_description>

Comments on the Issue (you are @copilot in this section)

Fixes #2428

💬 Share your feedback on Copilot coding agent for the chance to win a $200 gift card! Click here to start the survey.

Microsoft Reviewers: Open in CodeFlow

@Copilot Copilot AI assigned Copilot and krwq Oct 2, 2025
@dotnet-policy-service dotnet-policy-service bot added area-System.Device.Gpio Contains types for using general-purpose I/O (GPIO) pins area-device-bindings Device Bindings for audio, sensor, motor, and display hardware that can used with System.Device.Gpio labels Oct 2, 2025
…cument lock usage

Co-authored-by: krwq <660048+krwq@users.noreply.github.com>
@Copilot Copilot AI changed the title [WIP] Review lock usage vs. ConcurrentDictionary in Tca955x interrupt state management Review and improve lock usage in Tca955x interrupt state management Oct 2, 2025
@Copilot Copilot AI requested a review from krwq October 2, 2025 16:12
Copilot finished work on behalf of krwq October 2, 2025 16:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-device-bindings Device Bindings for audio, sensor, motor, and display hardware that can used with System.Device.Gpio area-System.Device.Gpio Contains types for using general-purpose I/O (GPIO) pins
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Review lock usage vs. ConcurrentDictionary in Tca955x interrupt state management
2 participants