public void Queue(QueueGroupKey queueGroupKey) { lock (queueGroupKeyToExecutionTimeDict) { QueueGroup queueGroup = DictionaryExtension.ValueOrDefault(queueGroupKeyToExecutionTimeDict, queueGroupKey); if (queueGroup != null) { // Runnable already pending with given QueueGroupKey return; } queueGroup = new QueueGroup(queueGroupKey); queueGroupKeyToExecutionTimeDict.Add(queueGroupKey, queueGroup); bool queueGroupAdded = false; // Insert the QueueGroup at the right position of pending QueueGroups // At index 0 is the latest of all, at max-index the next triggering QueueGroup for (int a = 0, size = pendingQueueGroups.Count; a < size; a++) { QueueGroup pendingQueueGroup = pendingQueueGroups[a]; if (queueGroup.ExecutionTime >= pendingQueueGroup.ExecutionTime) { // If new QueueGroup executes AFTER or EQUAL TO the current investigated QueueGroup, // insert the new QueueGroup BEFORE in the list pendingQueueGroups.Insert(a, queueGroup); queueGroupAdded = true; break; } } if (!queueGroupAdded) { pendingQueueGroups.Add(queueGroup); } } }
public NextQueue GetQueue(IHttpContext context) { if (Type == ThreadQueueType.Single) { return(QueueGroup.Queues[0]); } else if (Type == ThreadQueueType.Multiple) { return(QueueGroup.Next()); } else if (Type == ThreadQueueType.DataUnique) { string value = null; if (UniqueName != null) { context.Data.TryGetString(UniqueName, out value); } if (value == null) { value = context.Request.Url; } int index = System.Math.Abs(value.GetHashCode() % mUniqueQueueGroup.Queues.Count); return(mUniqueQueueGroup.Queues[index]); } return(QueueGroup.Next()); }
/// <summary>Find the next task that should be executed, based on priorities and fairness and the like.</summary> /// <param name="targetTask">The found task, or null if none was found.</param> /// <param name="queueForTargetTask"> /// The scheduler associated with the found task. Due to security checks inside of TPL, /// this scheduler needs to be used to execute that task. /// </param> void FindNextTaskNeedsLock(out Task targetTask, out QueuedTaskSchedulerQueue queueForTargetTask) { targetTask = null; queueForTargetTask = null; // Look through each of our queue groups in sorted order. // This ordering is based on the priority of the queues. foreach (var queueGroup in _queueGroups) { QueueGroup queues = queueGroup.Value; // Within each group, iterate through the queues in a round-robin // fashion. Every time we iterate again and successfully find a task, // we'll start in the next location in the group. foreach (int i in queues.CreateSearchOrder()) { queueForTargetTask = queues[i]; Queue <Task> items = queueForTargetTask._workItems; if (items.Count > 0) { targetTask = items.Dequeue(); if (queueForTargetTask._disposed && items.Count == 0) { RemoveQueueNeedsLock(queueForTargetTask); } queues.NextQueueIndex = (queues.NextQueueIndex + 1) % queueGroup.Value.Count; return; } } } }
/// <summary> /// Flushes all entities from the in queue into the matchmaker. /// </summary> /// <returns>The groups inserted into the queue.</returns> private IEnumerable <QueueGroup> FlushInQueue() { Queue <QueueGroup> toInform = new Queue <QueueGroup>(); lock (inQueue) { while (inQueue.Count > 0) { QueueGroup queueGroup = inQueue.Dequeue(); //Copy suitability metrics into the other entities foreach (Match match in queueGroup.matches) { match.other.matches.AddLast(new Match { other = queueGroup, value = match.value }); } queue.AddLast(queueGroup); toInform.Enqueue(queueGroup); } } return(toInform); }
public void Queue <T>(QueueGroupKey <T> queueGroupKey, IEnumerable <T> items) { lock (queueGroupKeyToExecutionTimeDict) { QueueGroup queueGroup = DictionaryExtension.ValueOrDefault(queueGroupKeyToExecutionTimeDict, queueGroupKey); if (queueGroup != null) { // Runnable already pending with given QueueGroupKey IList queue2 = queueGroup.Queue; foreach (T item in items) { queue2.Add(item); } return; } queueGroup = new QueueGroup(queueGroupKey, new List <T>()); queueGroupKeyToExecutionTimeDict.Add(queueGroupKey, queueGroup); IList queue = queueGroup.Queue; foreach (T item in items) { queue.Add(item); } QueueIntern <T>(queueGroup); } }
/// <summary> /// Flushes all the entities in the out queue from the matchmaker. /// </summary> /// <returns>The groups removed from the queue.</returns> private IEnumerable <QueueGroup> FlushOutQueue() { Queue <QueueGroup> toInform = new Queue <QueueGroup>(); lock (outQueue) { while (outQueue.Count > 0) { RankingMatchmakerQueueTask <T> task = outQueue.Dequeue(); //Get group and check it exists QueueGroup queueGroup = queue.FirstOrDefault((g) => g.task == task); if (queueGroup != null) { //Remove the group queue.Remove(queueGroup); //Remove all matches it had so we don't consider it in matchmaking foreach (QueueGroup other in queue) { other.matches.Remove(new Match { other = queueGroup }); } //If removed, inform it that it was cancelled toInform.Enqueue(queueGroup); } } } return(toInform); }
/// <summary>Removes a scheduler from the group.</summary> /// <param name="queue">The scheduler to be removed.</param> private void RemoveQueue_NeedsLock(QueuedTaskSchedulerQueue queue) { QueueGroup group = this._queueGroups[queue._priority]; int index = group.IndexOf(queue); if (group.NextQueueIndex >= index) { group.NextQueueIndex--; } group.RemoveAt(index); }
/// <summary> /// Calculates and adds matches to the given group. /// </summary> /// <param name="group">The group to calculate for.</param> /// <param name="groups">The groups to calculate against.</param> /// <param name="context">The context for the matchmaker.</param> private void AddMatchesToQueueGroup(QueueGroup group, IEnumerable <QueueGroup> groups, MatchRankingContext <T> context) { foreach (QueueGroup other in groups) { float outerAcc = 0; bool failed = false; foreach (T entity in group.task.Entities) { float acc = 0; foreach (T otherEntity in other.task.Entities) { float value = GetSuitabilityMetric(entity, otherEntity, context); //Check individual discard threshold, if not enough ignore the group if (value < DiscardThreshold) { failed = true; break; } acc += value; } //If we've already failed then just skip the reset if (failed) { break; } outerAcc += acc / other.task.Entities.Count; } //Already failed, don't add match if (failed) { continue; } outerAcc /= group.task.Entities.Count; //If a good enough match then add to our list of posible matches if (outerAcc >= GroupDiscardThreshold) { group.matches.AddLast(new Match { other = other, value = outerAcc }); } } }
/// <summary>Creates and activates a new scheduling queue for this scheduler.</summary> /// <param name="priority">The priority level for the new queue.</param> /// <returns>The newly created and activated queue at the specified priority.</returns> public TaskScheduler ActivateNewQueue(int priority) { QueuedTaskSchedulerQueue item = new QueuedTaskSchedulerQueue(priority, this); lock (this._queueGroups) { QueueGroup group; if (!this._queueGroups.TryGetValue(priority, out group)) { group = new QueueGroup(); this._queueGroups.Add(priority, group); } group.Add(item); } return(item); }
/// <summary>Removes a scheduler from the group.</summary> /// <param name="queue">The scheduler to be removed.</param> void RemoveQueueNeedsLock(QueuedTaskSchedulerQueue queue) { // Find the group that contains the queue and the queue's index within the group QueueGroup queueGroup = _queueGroups[queue._priority]; int index = queueGroup.IndexOf(queue); // We're about to remove the queue, so adjust the index of the next // round-robin starting location if it'll be affected by the removal if (queueGroup.NextQueueIndex >= index) { queueGroup.NextQueueIndex--; } // Remove it queueGroup.RemoveAt(index); }
public void Queue <T>(QueueGroupKey <T> queueGroupKey, T item) { lock (queueGroupKeyToExecutionTimeDict) { QueueGroup queueGroup = DictionaryExtension.ValueOrDefault(queueGroupKeyToExecutionTimeDict, queueGroupKey); if (queueGroup != null) { // Runnable already pending with given QueueGroupKey queueGroup.Queue.Add(item); return; } queueGroup = new QueueGroup(queueGroupKey, new List <T>()); queueGroupKeyToExecutionTimeDict.Add(queueGroupKey, queueGroup); queueGroup.Queue.Add(item); QueueIntern <T>(queueGroup); } }
/// <summary>Creates and activates a new scheduling queue for this scheduler.</summary> /// <param name="priority">The priority level for the new queue.</param> /// <returns>The newly created and activated queue at the specified priority.</returns> public TaskScheduler ActivateNewQueue(int priority) { // Create the queue var createdQueue = new QueuedTaskSchedulerQueue(priority, this); // Add the queue to the appropriate queue group based on priority lock (_queueGroups) { if (!_queueGroups.TryGetValue(priority, out QueueGroup list)) { list = new QueueGroup(); _queueGroups.Add(priority, list); } list.Add(createdQueue); } // Hand the new queue back return(createdQueue); }
private void CheckForPendingQueues() { lock (queueGroupKeyToExecutionTimeDict) { DateTime now = DateTime.Now; for (int a = pendingQueueGroups.Count; a-- > 0;) { // Look at the last QueueGroup QueueGroup queueGroup = pendingQueueGroups[a]; if (now < queueGroup.ExecutionTime) { // If the next QueueGroup is not ready, the others won't be, too break; } pendingQueueGroups.RemoveAt(a); AbstractQueueGroupKey queueGroupKey = queueGroup.QueueGroupKey; queueGroupKeyToExecutionTimeDict.Remove(queueGroupKey); lock (queueGroupKeyToExecuteDict) { IList <QueueGroup> currentExecutedQueueGroups = DictionaryExtension.ValueOrDefault(queueGroupKeyToExecuteDict, queueGroupKey); if (currentExecutedQueueGroups != null) { // There is already a thread executing the key. Nothing to do here currentExecutedQueueGroups.Add(queueGroup); return; } // List container for concurrent QueueGroup of the same key currentExecutedQueueGroups = new List <QueueGroup>(); queueGroupKeyToExecuteDict[queueGroupKey] = currentExecutedQueueGroups; } if (queueGroup.QueueGroupKey.InvokeFromGuiThread && SyncContext != null) { SyncContext.Post(ExecuteQueuedDelegate, queueGroup); continue; } Queue(delegate() { ExecuteQueuedDelegate(queueGroup); }); } } }
private void ExecuteQueuedDelegate(Object state) { QueueGroup queueGroup = (QueueGroup)state; AbstractQueueGroupKey queueGroupKey = queueGroup.QueueGroupKey; bool doRun = true; while (doRun) { try { if (queueGroupKey is QueueGroupKey) { ((QueueGroupKey)queueGroupKey).QueuedDelegate.Invoke(); } else { Delegate delegateObj = (Delegate)queueGroupKey.GetType().GetProperty("QueuedDelegate").GetValue(queueGroupKey, null); delegateObj.DynamicInvoke(queueGroup.Queue); } } finally { lock (queueGroupKeyToExecuteDict) { IList <QueueGroup> currentExecutedQueueGroups = DictionaryExtension.ValueOrDefault(queueGroupKeyToExecuteDict, queueGroupKey); if (currentExecutedQueueGroups.Count > 0) { // There is another queueGroup of the same key ready to be executed. Do it now immediately queueGroup = currentExecutedQueueGroups[0]; queueGroupKey = queueGroup.QueueGroupKey; currentExecutedQueueGroups.RemoveAt(0); } else { queueGroupKeyToExecuteDict.Remove(queueGroupKey); doRun = false; } } } } }
public NextQueue GetQueue(IHttpContext context) { if (Type == ThreadQueueType.Single) { return(QueueGroup.Queues[0]); } else if (Type == ThreadQueueType.Multiple) { return(QueueGroup.Next()); } else if (Type == ThreadQueueType.DataUnique) { string value = null; if (UniqueName != null) { if (string.Compare(UniqueName, "$path", true) == 0) { value = context.Request.GetSourcePath(); } else if (UniqueName.IndexOf("__") == 0) { return(mUniqueQueueGroup.Has(UniqueName.GetHashCode())); } else { value = context.Request.Header[UniqueName]; if (value == null) { context.Data.TryGetString(UniqueName, out value); } } } if (value == null) { value = context.Request.GetSourceUrl(); } return(mUniqueQueueGroup.Has(value.GetHashCode())); } return(QueueGroup.Next()); }
void Awake() { if (queuesSet) { Destroy(this); return; } for (int i = 0; i < queueGroups.Length; i++) { QueueGroup group = queueGroups[i]; for (int m = 0; m < group.materials.Length; m++) { if (group.materials[m] != null) { group.materials[m].renderQueue = group.queue; } } } Destroy(this); }
protected void QueueIntern <T>(QueueGroup queueGroup) { bool queueGroupAdded = false; // Insert the QueueGroup at the right position of pending QueueGroups // At index 0 is the latest of all, at max-index the next triggering QueueGroup for (int a = 0, size = pendingQueueGroups.Count; a < size; a++) { QueueGroup pendingQueueGroup = pendingQueueGroups[a]; if (queueGroup.ExecutionTime >= pendingQueueGroup.ExecutionTime) { // If new QueueGroup executes AFTER or EQUAL TO the current investigated QueueGroup, // insert the new QueueGroup BEFORE in the list pendingQueueGroups.Insert(a, queueGroup); queueGroupAdded = true; break; } } if (!queueGroupAdded) { pendingQueueGroups.Add(queueGroup); } }
/// <inheritdoc/> public IMatchmakerQueueTask <T> EnqueueGroup(EntityGroup <T> entities, EventHandler <MatchmakingStateChangedEventArgs <T> > callback = null) { RankingMatchmakerQueueTask <T> task = new RankingMatchmakerQueueTask <T>(this, entities, callback); QueueGroup queueGroup = new QueueGroup { task = task }; MatchRankingContext <T> context = new MatchRankingContext <T>(DiscardThreshold); //Look at all other entities in queue and rate them lock (queueSnapshot) AddMatchesToQueueGroup(queueGroup, queueSnapshot, context); lock (inQueue) { //Rate those to be added in future AddMatchesToQueueGroup(queueGroup, inQueue, context); //Add to in queue for next tick/flush inQueue.Enqueue(queueGroup); } return(task); }
/// <summary>Find the next task that should be executed, based on priorities and fairness and the like.</summary> /// <param name="targetTask">The found task, or null if none was found.</param> /// <param name="queueForTargetTask"> /// The scheduler associated with the found task. Due to security checks inside of TPL, /// this scheduler needs to be used to execute that task. /// </param> private void FindNextTask_NeedsLock(out Task targetTask, out QueuedTaskSchedulerQueue queueForTargetTask) { targetTask = null; queueForTargetTask = null; foreach (KeyValuePair <int, QueueGroup> pair in this._queueGroups) { QueueGroup group = pair.Value; foreach (int num in group.CreateSearchOrder()) { queueForTargetTask = group[num]; Queue <Task> queue = queueForTargetTask._workItems; if (queue.Count > 0) { targetTask = queue.Dequeue(); if (queueForTargetTask._disposed && (queue.Count == 0)) { this.RemoveQueue_NeedsLock(queueForTargetTask); } group.NextQueueIndex = (group.NextQueueIndex + 1) % pair.Value.Count; break; } } } }
public static string DecideColumnColour(QueueGroup queueGroup, MonitorData monitorData) { double seerviceLevel = (Convert.ToDouble(monitorData.HandledWithinSL) / Convert.ToDouble(monitorData.Offered)) * 100; return(seerviceLevel >= queueGroup.SLA_Percent ? Constants.Green : Constants.Red); }
public async Task QueueUp(DiscordChannel channel, DiscordMember user, PlayerRole role, DiscordMember other = null) { var inhouseQueue = InhouseQueues.FirstOrDefault(x => x.ChannelId == channel.Id); if (inhouseQueue == null) { return; } var queueGroup = inhouseQueue.PlayersInQueue.FirstOrDefault(x => x.Players.Any(y => y.Player.Id == user.Id)); InhousePlayer inhousePlayer = null; if (queueGroup == null) { queueGroup = new QueueGroup(); inhousePlayer = new InhousePlayer(user); queueGroup.Players.Add(inhousePlayer); inhouseQueue.PlayersInQueue.Add(queueGroup); } else { inhousePlayer = queueGroup.Players.FirstOrDefault(x => x.Player.Id == user.Id); } // if the player in question is already a fill player, do nothing if (!inhousePlayer.QueuedRoles[PlayerRole.Fill]) { switch (role) { case PlayerRole.Top: inhousePlayer.QueuedRoles[PlayerRole.Top] = true; break; case PlayerRole.Jgl: inhousePlayer.QueuedRoles[PlayerRole.Jgl] = true; break; case PlayerRole.Mid: inhousePlayer.QueuedRoles[PlayerRole.Mid] = true; break; case PlayerRole.Bot: inhousePlayer.QueuedRoles[PlayerRole.Bot] = true; break; case PlayerRole.Sup: inhousePlayer.QueuedRoles[PlayerRole.Sup] = true; break; case PlayerRole.Fill: inhousePlayer.QueuedRoles[PlayerRole.Top] = false; inhousePlayer.QueuedRoles[PlayerRole.Jgl] = false; inhousePlayer.QueuedRoles[PlayerRole.Mid] = false; inhousePlayer.QueuedRoles[PlayerRole.Bot] = false; inhousePlayer.QueuedRoles[PlayerRole.Sup] = false; inhousePlayer.QueuedRoles[PlayerRole.Fill] = true; break; } if (inhousePlayer.QueuedRoles[PlayerRole.Top] && inhousePlayer.QueuedRoles[PlayerRole.Jgl] && inhousePlayer.QueuedRoles[PlayerRole.Mid] && inhousePlayer.QueuedRoles[PlayerRole.Bot] && inhousePlayer.QueuedRoles[PlayerRole.Sup]) { inhousePlayer.QueuedRoles[PlayerRole.Top] = false; inhousePlayer.QueuedRoles[PlayerRole.Jgl] = false; inhousePlayer.QueuedRoles[PlayerRole.Mid] = false; inhousePlayer.QueuedRoles[PlayerRole.Bot] = false; inhousePlayer.QueuedRoles[PlayerRole.Sup] = false; inhousePlayer.QueuedRoles[PlayerRole.Fill] = true; } } // attempt to join team if provided if (other != null) { await TeamUp(channel, user, other).ConfigureAwait(false); } else { await ShowQueue(channel).ConfigureAwait(false); } await AttemptMatchmake(channel).ConfigureAwait(false); }