// Copyright Epic Games, Inc. All Rights Reserved.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace Gauntlet
{
public class AccountPool
{
///
/// Singleton
///
private static IManagedAccountPool _Instance;
public static void Initialize()
{
Initialize ();
}
~AccountPool()
{
if (_Instance != null)
{
_Instance.Dispose();
}
}
public static void Initialize()
{
object PossiblePool = Activator.CreateInstance(typeof(T));
if (PossiblePool is IManagedAccountPool)
{
if (_Instance != null)
{
_Instance.Dispose();
}
_Instance = (IManagedAccountPool)PossiblePool;
}
}
public static IManagedAccountPool Instance
{
get
{
if (_Instance == null)
{
Initialize();
}
return _Instance;
}
}
public static void Shutdown()
{
if (_Instance != null)
{
_Instance.Dispose();
_Instance = null;
}
}
}
public interface IManagedAccountPool: IDisposable
{
void RegisterAccount(Account InAccount);
void ReleaseAccount(Account InAccount);
Account ReserveAccount();
}
///
/// A pool of accounts for tests to use. The pool should be filled by the project-specific script that derives from
/// RunUnrealTests
///
public class ManagedAccountPool : IManagedAccountPool
{
///
/// Object used for locking access to internal data
///
protected Object LockObject = new Object();
///
/// List of all registered accounts
///
protected List AllAccounts = new List();
///
/// Accounts that have been reserved
///
protected Dictionary ReservedAccounts = new Dictionary();
///
/// A random ordering of AllAccounts
///
protected List RandomlyOrderedList = new List();
~ManagedAccountPool()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
///
/// Perform actual dispose behavior
///
///
protected void Dispose(bool disposing)
{
lock (LockObject)
{
if (disposing)
{
IEnumerable StillReserved = ReservedAccounts.Keys.Where(K => ReservedAccounts[K] == true);
StillReserved.ToList().ForEach(A => Log.Warning("Account {0} was still reserved on dispose!", A));
ReservedAccounts.Clear();
RandomlyOrderedList.Clear();
ReservedAccounts.Clear();
}
}
}
public void RegisterAccount(Account InAccount)
{
AllAccounts.Add(InAccount);
}
public void ClearReservatios()
{
lock (LockObject)
{
RandomlyOrderedList.Clear();
ReservedAccounts.Clear();
}
}
public void ReleaseAccount(Account InAccount)
{
lock (LockObject)
{
ReservedAccounts[InAccount] = false;
}
}
virtual public Account ReserveAccount()
{
lock (LockObject)
{
// if number of avail accounts has changed...
if (RandomlyOrderedList.Count + ReservedAccounts.Keys.Count != AllAccounts.Count)
{
// list of all available accounts
List SelectionList = AllAccounts.Where(A => ReservedAccounts.ContainsKey(A) == false).ToList();
Random Rand = new Random();
while (SelectionList.Count > 0)
{
int Index = Rand.Next(SelectionList.Count);
RandomlyOrderedList.Add(SelectionList[Index]);
SelectionList.RemoveAt(Index);
}
}
if (RandomlyOrderedList.Count == 0)
{
throw new Exception("Unable to find free account!");
}
Account SelectedAccount = RandomlyOrderedList.First();
RandomlyOrderedList.RemoveAt(0);
ReservedAccounts[SelectedAccount] = true;
return SelectedAccount;
}
}
}
}