public static void Log(ThreadWorker worker, string message, bool logToConsole = false) { #if WDEBUG //seems that conditional does not work in some cases if (!logging) { return; } if (log.Count > 50000) { log.RemoveRange(0, 20000); } LogEntity logEntity = new LogEntity() { worker = worker, name = message, stage = worker.stage, stop = worker.stop, threadId = Thread.CurrentThread.ManagedThreadId }; if (worker.threadCondition != null) { if (worker.threadCondition()) { logEntity.threadCondition = LogEntity.ConditionMet.True; } else { logEntity.threadCondition = LogEntity.ConditionMet.False; } } if (worker.applyCondition != null) { if (worker.applyCondition()) { logEntity.applyCondition = LogEntity.ConditionMet.True; } else { logEntity.applyCondition = LogEntity.ConditionMet.False; } } logEntity.time = DateTime.Now; logEntity.locked = worker.lockWasTaken; log.Add(logEntity); if (logToConsole) { Debug.LogError(worker.name + " " + message); } #endif }
public static void UpdateThreads() //called each time any thread is complete { try{ if (!on || queue.Count == 0) { return; } #if WDEBUG if (IsMainThread) { Profiler.BeginSample("Update Threads"); } #endif int threadsRunning = 0; //current number of threads then multithreading is on //calculating number of threads running int queueCount = queue.Count; for (int i = 0; i < queueCount; i++) { if (queue[i].stage == Stage.threadRunning) { threadsRunning++; } } //guard if all possible threads already started: exit with no queue locking if (threadsRunning >= maxThreads) { #if WDEBUG if (IsMainThread) { Profiler.EndSample(); } #endif return; } //staring new threads lock (queue) while (threadsRunning < maxThreads) { //finding suitable worker with highest priority float maxProirity = -2000000; // int maxProirityNum = -1; ThreadWorker maxPriorityWorker = null; queueCount = queue.Count; for (int i = 0; i < queueCount; i++) { ThreadWorker worker = queue[i]; if (worker == null) { continue; } if (worker.priority < maxProirity) { continue; } if (worker.stage != Stage.threadEnqueued) { continue; //if object destroyed or other stage } if (worker.threadCondition != null && !worker.threadCondition()) { continue; } maxPriorityWorker = worker; maxProirity = worker.priority; // maxProirityNum = i; } //no suitable threads if (maxPriorityWorker == null) { break; } //starting thread //lock (maxPriorityWorker.locker) Monitor.Enter(maxPriorityWorker.locker); maxPriorityWorker.lockWasTaken = true; try { if (maxPriorityWorker.stage != Stage.threadEnqueued) { return; //this could happen if two threads selecting one worker, or worker stopped while being selected } if (logging) { Log(maxPriorityWorker, "Refresh:ThreadSelected (max" + maxProirity + ") "); } threadsRunning++; if (multithreading) { maxPriorityWorker.thread = new Thread(maxPriorityWorker.ThreadFn); maxPriorityWorker.thread.IsBackground = true; maxPriorityWorker.SwitchStage(Stage.threadRunning, "Refresh: start thread"); //before actually starting maxPriorityWorker.thread.Start(); } else { maxPriorityWorker.ThreadFn(); if (IsMainThread) { Profiler.EndSample(); } if (oneThreadPerFrame) { break; } } } finally { Monitor.Exit(maxPriorityWorker.locker); maxPriorityWorker.lockWasTaken = false; } } #if WDEBUG if (IsMainThread) { Profiler.EndSample(); } #endif } catch (System.Exception e) { Debug.LogError("Spinner Error: " + e); } }