// Copyright © 2020 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.Threading;
namespace CefSharp.Internals
{
///
/// Tracks the number of browser instances currently open
/// The cound will be incrmented and decremented each time a CefBrowser is created/closed.
/// This includes CefBrowser popup instances.
///
///
/// Roughtly based on , unforeunately
/// doesn't reset the internal when Count is aleady 0.
/// In our case it's valid to increase the number of browsers and reset the event.
///
public class BrowserRefCounter : IBrowserRefCounter
{
private volatile int count = 0;
private ManualResetEventSlim manualResetEvent = new ManualResetEventSlim();
/// TODO: Refactor this so it's not static.
public static IBrowserRefCounter Instance = new NoOpBrowserRefCounter();
///
/// Increment browser count
///
void IBrowserRefCounter.Increment()
{
var newCount = Interlocked.Increment(ref count);
if (newCount > 0)
{
manualResetEvent.Reset();
}
}
///
/// Decrement browser count
///
bool IBrowserRefCounter.Decrement()
{
var newCount = Interlocked.Decrement(ref count);
if (newCount == 0)
{
manualResetEvent.Set();
return true;
}
if (newCount < 0)
{
//If we went below 0 then reset to 0
// TODO: something went wrong with our tracking
Interlocked.Exchange(ref count, 0);
manualResetEvent.Set();
}
return false;
}
///
/// Gets the number of CefBrowser instances currently open (this includes popups)
///
///
/// The count.
///
int IBrowserRefCounter.Count
{
get
{
int observedCount = count;
return observedCount < 0 ? 0 : observedCount;
}
}
///
/// Blocks until the CefBrowser count has reached 0 or the timeout has been reached
///
/// (Optional) The timeout in miliseconds.
void IBrowserRefCounter.WaitForBrowsersToClose(int timeoutInMiliseconds)
{
if (!manualResetEvent.IsSet)
{
manualResetEvent.Wait(timeoutInMiliseconds);
}
}
///
/// Blocks until the CefBrowser count has reached 0 or the timeout has been reached
///
/// (Optional) The timeout in miliseconds.
/// (Optional) The cancellation token.
void IBrowserRefCounter.WaitForBrowsersToClose(int timeoutInMiliseconds, CancellationToken cancellationToken)
{
if (!manualResetEvent.IsSet)
{
manualResetEvent.Wait(timeoutInMiliseconds, cancellationToken);
}
}
}
}