/// <summary> /// Executes a foreach loop in which iterations may run in parallel /// </summary> /// <typeparam name="T">Object type that the collection wraps</typeparam> /// <param name="threadCount">The number of concurrent execution threads to run</param> /// <param name="enumerable">An enumerable collection to iterate over</param> /// <param name="body">Method body to run for each object in the collection</param> public static void ForEach <T>(int threadCount, IEnumerable <T> enumerable, Action <T> body) { int counter = threadCount; AutoResetEvent threadFinishEvent = new AutoResetEvent(false); IEnumerator <T> enumerator = enumerable.GetEnumerator(); Exception exception = null; for (int i = 0; i < threadCount; i++) { WorkPool.QueueUserWorkItem( delegate(object o) { int threadIndex = (int)o; while (exception == null) { T entry; lock (enumerator) { if (!enumerator.MoveNext()) { break; } entry = (T)enumerator.Current; // Explicit typecast for Mono's sake } try { body(entry); } catch (Exception ex) { exception = ex; break; } } if (Interlocked.Decrement(ref counter) == 0) { threadFinishEvent.Set(); } }, i ); } threadFinishEvent.WaitOne(); if (exception != null) { throw exception; } }
/// <summary> /// Executes a for loop in which iterations may run in parallel /// </summary> /// <param name="threadCount">The number of concurrent execution threads to run</param> /// <param name="fromInclusive">The loop will be started at this index</param> /// <param name="toExclusive">The loop will be terminated before this index is reached</param> /// <param name="body">Method body to run for each iteration of the loop</param> public static void For(int threadCount, int fromInclusive, int toExclusive, Action <int> body) { int counter = threadCount; AutoResetEvent threadFinishEvent = new AutoResetEvent(false); Exception exception = null; --fromInclusive; for (int i = 0; i < threadCount; i++) { WorkPool.QueueUserWorkItem( delegate(object o) { int threadIndex = (int)o; while (exception == null) { int currentIndex = Interlocked.Increment(ref fromInclusive); if (currentIndex >= toExclusive) { break; } try { body(currentIndex); } catch (Exception ex) { exception = ex; break; } } if (Interlocked.Decrement(ref counter) == 0) { threadFinishEvent.Set(); } }, i ); } threadFinishEvent.WaitOne(); if (exception != null) { throw exception; } }
/// <summary> /// Executes a series of tasks in parallel /// </summary> /// <param name="threadCount">The number of concurrent execution threads to run</param> /// <param name="actions">A series of method bodies to execute</param> public static void Invoke(int threadCount, params Action[] actions) { int counter = threadCount; AutoResetEvent threadFinishEvent = new AutoResetEvent(false); int index = -1; Exception exception = null; for (int i = 0; i < threadCount; i++) { WorkPool.QueueUserWorkItem( delegate(object o) { int threadIndex = (int)o; while (exception == null) { int currentIndex = Interlocked.Increment(ref index); if (currentIndex >= actions.Length) { break; } try { actions[currentIndex](); } catch (Exception ex) { exception = ex; break; } } if (Interlocked.Decrement(ref counter) == 0) { threadFinishEvent.Set(); } }, i ); } threadFinishEvent.WaitOne(); if (exception != null) { throw exception; } }
/// <summary> /// Fire the events registered for this event type asynchronously /// </summary> /// <param name="capsEvent">Capability name</param> /// <param name="message">Decoded event body</param> /// <param name="simulator">Reference to the simulator that /// generated this event</param> internal void BeginRaiseEvent(string capsEvent, IMessage message, Simulator simulator) { bool specialHandler = false; Caps.EventQueueCallback callback; // Default handler first, if one exists if (_EventTable.TryGetValue(String.Empty, out callback)) { if (callback != null) { CapsCallbackWrapper wrapper; wrapper.Callback = callback; wrapper.CapsEvent = capsEvent; wrapper.Message = message; wrapper.Simulator = simulator; WorkPool.QueueUserWorkItem(_ThreadPoolCallback, wrapper); } } // Explicit handler next if (_EventTable.TryGetValue(capsEvent, out callback) && callback != null) { CapsCallbackWrapper wrapper; wrapper.Callback = callback; wrapper.CapsEvent = capsEvent; wrapper.Message = message; wrapper.Simulator = simulator; WorkPool.QueueUserWorkItem(_ThreadPoolCallback, wrapper); specialHandler = true; } if (!specialHandler) { Logger.Log("Unhandled CAPS event " + capsEvent, Helpers.LogLevel.Warning, Client); } }
/// <summary> /// Master Download Thread, Queues up downloads in the threadpool /// </summary> private void DownloadThread() { int slot; while (_Running) { // find free slots int pending = 0; int active = 0; TaskInfo nextTask = null; lock (_Transfers) { foreach (KeyValuePair <UUID, TaskInfo> request in _Transfers) { if (request.Value.State == TextureRequestState.Pending) { nextTask = request.Value; ++pending; } else if (request.Value.State == TextureRequestState.Progress) { ++active; } } } if (pending > 0 && active <= maxTextureRequests) { slot = -1; // find available slot for reset event lock (lockerObject) { for (int i = 0; i < threadpoolSlots.Length; i++) { if (threadpoolSlots[i] == -1) { // found a free slot threadpoolSlots[i] = 1; slot = i; break; } } } // -1 = slot not available if (slot != -1 && nextTask != null) { nextTask.State = TextureRequestState.Started; nextTask.RequestSlot = slot; //Logger.DebugLog(String.Format("Sending Worker thread new download request {0}", slot)); WorkPool.QueueUserWorkItem(TextureRequestDoWork, nextTask); continue; } } // Queue was empty or all download slots are inuse, let's give up some CPU time Thread.Sleep(500); } Logger.Log("Texture pipeline shutting down", Helpers.LogLevel.Info); }