Esempio n. 1
0
        /// <summary>
        /// Asynchronously load data for the provided given key.
        /// </summary>
        /// <param name="key">Key to use for loading data</param>
        /// <returns>
        /// An object representing a pending operation
        /// </returns>
        public virtual IDataLoaderResult <T> LoadAsync(TKey key)
        {
            lock (_sync)
            {
                //once it enters the lock, it is guaranteed to exit the lock, as it does not depend on external code
                if (_cachedList != null)
                {
                    if (_cachedList.TryGetValue(key, out var ret2))
                    {
                        return(ret2);
                    }
                }
                if (_list != null)
                {
                    if (_list.TryGetValue(key, out var ret2))
                    {
                        return(ret2);
                    }

                    if (_list.Count >= MaxBatchSize)
                    {
                        _list = new DataLoaderList(this);
                    }
                }
                else
                {
                    _list = new DataLoaderList(this);
                }
                var ret = new DataLoaderPair <TKey, T>(_list, key);
                _list.Add(key, ret);
                _cachedList?.Add(key, ret);
                return(ret);
            }
        }
Esempio n. 2
0
 /// <summary>
 /// Internally used by DataLoaderList to start the fetch operation.
 /// </summary>
 /// <returns>A Task representing the asynchronous fetch operation</returns>
 private Task StartLoading(DataLoaderList listToLoad, CancellationToken cancellationToken)
 {
     if (listToLoad == null)
     {
         throw new ArgumentNullException(nameof(listToLoad));
     }
     lock (_sync)
     {
         //once it enters the lock, it is guaranteed to exit the lock, as it does not depend on external code
         if (_list == listToLoad)
         {
             _list = null;
         }
     }
     return(FetchAsync(listToLoad.Values, cancellationToken));
 }
Esempio n. 3
0
        /// <summary>
        /// Dispatch any pending operations.
        /// </summary>
        /// <param name="cancellationToken">Optional <seealso cref="CancellationToken"/> to pass to the fetch delegate</param>
        public Task DispatchAsync(CancellationToken cancellationToken = default)
        {
            //start loading the currently queued items
            DataLoaderList listToLoad;

            lock (_sync)
            {
                //once it enters the lock, it is guaranteed to exit the lock, as it does not depend on external code
                //cannot use Interlocked.Exchange here because that can execute during another lock
                listToLoad = _list;
                _list      = null;
            }
            if (listToLoad == null)
            {
                return(Task.CompletedTask);
            }
            return(listToLoad.DispatchAsync(cancellationToken));
        }
Esempio n. 4
0
        /// <summary>
        /// Asynchronously load data for the provided given key.
        /// If the key is <see langword="null"/> then a <see cref="DataLoaderResult{T}"/> containing
        /// <see langword="null"/> will be immediately returned.
        /// </summary>
        /// <param name="key">Key to use for loading data</param>
        /// <returns>
        /// An object representing a pending operation
        /// </returns>
        public virtual IDataLoaderResult <T> LoadAsync(TKey key)
        {
            // dictionaries do not support keys with null values (null reference values or null value types),
            // so in this case bypass the data loader and return null
            if (key == null)
            {
                return(DataLoaderResult <T> .DefaultValue);
            }

            lock (_sync)
            {
                //once it enters the lock, it is guaranteed to exit the lock, as it does not depend on external code
                if (_cachedList != null)
                {
                    if (_cachedList.TryGetValue(key, out var ret2))
                    {
                        return(ret2);
                    }
                }
                if (_list != null)
                {
                    if (_list.TryGetValue(key, out var ret2))
                    {
                        return(ret2);
                    }

                    if (_list.Count >= MaxBatchSize)
                    {
                        _list = new DataLoaderList(this);
                    }
                }
                else
                {
                    _list = new DataLoaderList(this);
                }
                var ret = new DataLoaderPair <TKey, T>(_list, key);
                _list.Add(key, ret);
                _cachedList?.Add(key, ret);
                return(ret);
            }
        }