private TValue[] TryGetBatchMixed(IReadOnlyCollection <TKey> keys, BatchLoad batch) { // construct a list of keys to load var keysToLoad = new List <TKey>(batch.ToLoadCount); var originalIndexes = new List <int>(batch.ToLoadCount); int i = 0; foreach (var key in keys) { if (!batch.AlreadyLoading[i]) { keysToLoad.Add(key); originalIndexes.Add(i); } i++; } // the following line may block TValue[] loaded = keysToLoad.Count > 0 ? _batchDataSource.GetBatch(keysToLoad) : new TValue[0]; // set the results of the all the TCS we added i = 0; foreach (var l in loaded) { int idx = originalIndexes[i]; Task.Run(() => batch.TaskCompletionSources[idx].TrySetResult(l)); i++; } // remove all keys that we loaded RemoveAllKeys(keysToLoad); // construct results from TCS results return(ResultsFromBatchTCS(keys, batch)); }
private TValue[] UpdateCacheAndResults(BatchLoad batch, TValue[] fromDataSource) { lock (SyncRoot) { int keyIdx = 0; foreach (var loaded in fromDataSource) { if (!ValueEquality.Equals(loaded, default(TValue))) { var idx = batch.MissedKeyIdx[keyIdx]; TValue cached; if (batch.Version != Version && TryGetAnyGen(batch.MissedKeys[keyIdx], out cached)) { // another thread loaded our value batch.Results[idx] = cached; unchecked { Version++; } } else { // we loaded the value, store it in the cache AddToGen0(batch.MissedKeys[keyIdx], loaded); batch.Results[idx] = loaded; } } keyIdx++; } } return(batch.Results); }
static TValue[] ResultsFromBatchTCS(IReadOnlyCollection <TKey> keys, BatchLoad batch) { var results = new TValue[keys.Count]; int i = 0; foreach (var tcs in batch.TaskCompletionSources) { results[i] = tcs.Task.Result; i++; } return(results); }
private BatchLoad TryGetBatchFromCache(IReadOnlyCollection <TKey> keys) { var batch = new BatchLoad(keys.Count, Version); int i = 0; foreach (var key in keys) { TValue value; if (TryGetAnyGen(key, out value)) { batch.Results[i] = value; } else { batch.MissedKeys.Add(key); batch.MissedKeyIdx.Add(i); } i++; } return(batch); }