dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
15.03k stars 4.68k forks source link

[SyncContext(contextName)] #60336

Open kefyru opened 2 years ago

kefyru commented 2 years ago

Add attribute [SyncContext(contextName)] for fields, properties and methods Compiler will check if member with this attribute using outside lock(context) {...} block than cause warning member should use inside lock(contextName) block

Example

public class ConsumerProducer<TP, TResult>
where TP : IProducer<TResult> // implements Task<TResult> GetResult(object arg) for example
 {
    private object _syncContext = new object();

    [SyncContext(nameof(_syncContext))] // should use in lock(_syncContext) block, or get warning
    private Stack<TP> _pool = new();

    [SyncContext(nameof(_syncContext))] // should use in lock(_syncContext) block, or get warning
    private Queue<(object arg, TaskCompletionSource<TResult> tcs)> _queue = new();

    // process queue
    private void Process() 
    {
       (object arg, TaskCompletionSource<TResult> tcs)? consumer;
       TP? producer;

       lock(_syncContext) {         
          if (_pool.Count * _queue.Count == 0) return;
          // other thread can make _queue or _pool empty here
          // if _queue or _pool using outside lock(_syncContext) block
          consumer = _queue.Dequeue(); // exception if _queue is empty 
          producer = _pool.Pop();  //  exception if _pool is empty
       }

       producer.GetResult(consumer.arg).ContinueWith(task => {
            consumer.tcs.SetResult(task.Result);
            _pool.Push(producer);  // Compiler warning: _pool should use with lock(_syncContext)
           Process();
       })
    }

    // return result or put to queue
    public Task<TResult> GetResult(object arg) 
    {
       var tcs = new TaskCompletionSource<TResult>();
       (object arg, TaskCompletionSource<TResult> tcs) consumer = new (arg, tcs); 
        _queue.Enqueue(consumer);  // Compiler warning: _queue should use with lock(_syncContext)
       return tcs.Task;
    }
}
ghost commented 2 years ago

Tagging subscribers to this area: @mangod9 See info in area-owners.md if you want to be subscribed.

Issue Details
Add attribute ```[SyncContext(contextName)]``` for fields, properties and methods Compiler will check if member with this attribute using outside ```lock(context) {...}``` block than cause warning ```member should use inside lock(contextName) block``` Example ```C# public class ConsumerProducer where TP : IProducer // implements Task GetResult(object arg) for example { private object _syncContext = new object(); [SyncContext(nameof(_syncContext))] // should use in lock(_syncContext) block, or get warning private Stack _pool = new(); [SyncContext(nameof(_syncContext))] // should use in lock(_syncContext) block, or get warning private Queue<(object arg, TaskCompletionSource tcs)> _queue = new(); // process queue private void Process() { (object arg, TaskCompletionSource tcs)? consumer; TP? producer; lock(_syncContext) { if (_pool.Count * _queue.Count == 0) return; // other thread can make _queue or _pool empty here // if _queue or _pool using outside lock(_syncContext) block consumer = _queue.Dequeue(); // exception if _queue is empty producer = _pool.Pop(); // exception if _pool is empty } producer.GetResult(consumer.arg).ContinueWith(task => { consumer.tcs.SetResult(task.Result); _pool.Push(producer); // Compiler warning: _pool should use with lock(_syncContext) Process(); }) } // return result or put to queue public Task GetResult(object arg) { var tcs = new TaskCompletionSource(); (object arg, TaskCompletionSource tcs) consumer = new (arg, tcs); _queue.Enqueue(consumer); // Compiler warning: _queue should use with lock(_syncContext) return tcs.Task; } } ```
Author: kefyru
Assignees: -
Labels: `area-System.Threading`, `untriaged`
Milestone: -
svick commented 2 years ago

Why should this be part of the runtime/compiler, when it could be a 3rd party Roslyn analyzer instead?