// Copyright © 2015 The CefSharp Authors. All rights reserved.
//
// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace CefSharp.Internals
{
///
/// Class to store TaskCompletionSources indexed by a unique id. There are two distinct ConcurrentDictionary
/// instances as we have some Tasks that are created from the browser process (EvaluateScriptAsync) calls, and
/// some that are created for instances for which the Id's are created
/// in the render process.
///
/// The type of the result produced by the tasks held.
public sealed class PendingTaskRepository
{
private readonly ConcurrentDictionary> pendingTasks =
new ConcurrentDictionary>();
private readonly ConcurrentDictionary> callbackPendingTasks =
new ConcurrentDictionary>();
//should only be accessed by Interlocked.Increment
private long lastId;
///
/// Creates a new pending task with a timeout.
///
/// The maximum running time of the task.
/// The unique id of the newly created pending task and the newly created .
public KeyValuePair> CreatePendingTask(TimeSpan? timeout = null)
{
var taskCompletionSource = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
var id = Interlocked.Increment(ref lastId);
pendingTasks.TryAdd(id, taskCompletionSource);
if (timeout.HasValue)
{
taskCompletionSource = taskCompletionSource.WithTimeout(timeout.Value, () => RemovePendingTask(id));
}
return new KeyValuePair>(id, taskCompletionSource);
}
///
/// Creates a new pending task with a timeout.
///
/// Id passed in from the render process
/// The maximum running time of the task.
/// The unique id of the newly created pending task and the newly created .
public KeyValuePair> CreateJavascriptCallbackPendingTask(long id, TimeSpan? timeout = null)
{
var taskCompletionSource = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
callbackPendingTasks.TryAdd(id, taskCompletionSource);
if (timeout.HasValue)
{
taskCompletionSource = taskCompletionSource.WithTimeout(timeout.Value, () => RemoveJavascriptCallbackPendingTask(id));
}
return new KeyValuePair>(id, taskCompletionSource);
}
///
/// If a is found matching
/// then it is removed from the ConcurrentDictionary and returned.
///
/// Unique id of the pending task.
///
/// The associated with the given id
/// or null if no matching TaskComplectionSource found.
///
public TaskCompletionSource RemovePendingTask(long id)
{
TaskCompletionSource result;
if (pendingTasks.TryRemove(id, out result))
{
return result;
}
return null;
}
///
/// If a is found matching
/// then it is removed from the ConcurrentDictionary and returned.
///
/// Unique id of the pending task.
///
/// The associated with the given id
/// or null if no matching TaskComplectionSource found.
///
public TaskCompletionSource RemoveJavascriptCallbackPendingTask(long id)
{
TaskCompletionSource result;
if (callbackPendingTasks.TryRemove(id, out result))
{
return result;
}
return null;
}
}
}