Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/rx.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'Rx.NET/System.Reactive.PlatformServices/Reactive/Concurrency/ConcurrencyAbstractionLayerImpl.cs')
-rw-r--r--Rx.NET/System.Reactive.PlatformServices/Reactive/Concurrency/ConcurrencyAbstractionLayerImpl.cs215
1 files changed, 215 insertions, 0 deletions
diff --git a/Rx.NET/System.Reactive.PlatformServices/Reactive/Concurrency/ConcurrencyAbstractionLayerImpl.cs b/Rx.NET/System.Reactive.PlatformServices/Reactive/Concurrency/ConcurrencyAbstractionLayerImpl.cs
new file mode 100644
index 0000000..2d86ea7
--- /dev/null
+++ b/Rx.NET/System.Reactive.PlatformServices/Reactive/Concurrency/ConcurrencyAbstractionLayerImpl.cs
@@ -0,0 +1,215 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
+
+#if !NO_THREAD
+using System;
+using System.Collections.Generic;
+using System.Reactive.Disposables;
+using System.Threading;
+
+namespace System.Reactive.Concurrency
+{
+ //
+ // WARNING: This code is kept *identically* in two places. One copy is kept in System.Reactive.Core for non-PLIB platforms.
+ // Another copy is kept in System.Reactive.PlatformServices to enlighten the default lowest common denominator
+ // behavior of Rx for PLIB when used on a more capable platform.
+ //
+ internal class /*Default*/ConcurrencyAbstractionLayerImpl : IConcurrencyAbstractionLayer
+ {
+ public IDisposable StartTimer(Action<object> action, object state, TimeSpan dueTime)
+ {
+ return new Timer(action, state, Normalize(dueTime));
+ }
+
+ public IDisposable StartPeriodicTimer(Action action, TimeSpan period)
+ {
+ //
+ // MSDN documentation states the following:
+ //
+ // "If period is zero (0) or negative one (-1) milliseconds and dueTime is positive, callback is invoked once;
+ // the periodic behavior of the timer is disabled, but can be re-enabled using the Change method."
+ //
+ if (period <= TimeSpan.Zero)
+ throw new ArgumentOutOfRangeException("period");
+
+ return new PeriodicTimer(action, period);
+ }
+
+ public IDisposable QueueUserWorkItem(Action<object> action, object state)
+ {
+ System.Threading.ThreadPool.QueueUserWorkItem(_ => action(_), state);
+ return Disposable.Empty;
+ }
+
+#if USE_SLEEP_MS
+ public void Sleep(TimeSpan timeout)
+ {
+ System.Threading.Thread.Sleep((int)Normalize(timeout).TotalMilliseconds);
+ }
+#else
+ public void Sleep(TimeSpan timeout)
+ {
+ System.Threading.Thread.Sleep(Normalize(timeout));
+ }
+#endif
+
+ public IStopwatch StartStopwatch()
+ {
+#if !NO_STOPWATCH
+ return new StopwatchImpl();
+#else
+ return new DefaultStopwatch();
+#endif
+ }
+
+ public bool SupportsLongRunning
+ {
+ get { return true; }
+ }
+
+ public void StartThread(Action<object> action, object state)
+ {
+ new Thread(() =>
+ {
+ action(state);
+ }).Start();
+ }
+
+ private static TimeSpan Normalize(TimeSpan dueTime)
+ {
+ if (dueTime < TimeSpan.Zero)
+ return TimeSpan.Zero;
+
+ return dueTime;
+ }
+
+ class Timer : IDisposable
+ {
+ //
+ // Note: the dictionary exists to "root" the timers so that they are not garbage collected and finalized while they are running.
+ //
+#if !NO_HASHSET
+ private static readonly HashSet<System.Threading.Timer> s_timers = new HashSet<System.Threading.Timer>();
+#else
+ private static readonly Dictionary<System.Threading.Timer, object> s_timers = new Dictionary<System.Threading.Timer, object>();
+#endif
+
+ private Action<object> _action;
+ private System.Threading.Timer _timer;
+
+ private bool _hasAdded;
+ private bool _hasRemoved;
+
+ public Timer(Action<object> action, object state, TimeSpan dueTime)
+ {
+ _action = action;
+ _timer = new System.Threading.Timer(Tick, state, dueTime, TimeSpan.FromMilliseconds(System.Threading.Timeout.Infinite));
+
+ lock (s_timers)
+ {
+ if (!_hasRemoved)
+ {
+#if !NO_HASHSET
+ s_timers.Add(_timer);
+#else
+ s_timers.Add(_timer, null);
+#endif
+
+ _hasAdded = true;
+ }
+ }
+ }
+
+ private void Tick(object state)
+ {
+ try
+ {
+ _action(state);
+ }
+ finally
+ {
+ Dispose();
+ }
+ }
+
+ public void Dispose()
+ {
+ _action = Stubs<object>.Ignore;
+
+ var timer = default(System.Threading.Timer);
+
+ lock (s_timers)
+ {
+ if (!_hasRemoved)
+ {
+ timer = _timer;
+ _timer = null;
+
+ if (_hasAdded && timer != null)
+ s_timers.Remove(timer);
+
+ _hasRemoved = true;
+ }
+ }
+
+ if (timer != null)
+ timer.Dispose();
+ }
+ }
+
+ class PeriodicTimer : IDisposable
+ {
+ //
+ // Note: the dictionary exists to "root" the timers so that they are not garbage collected and finalized while they are running.
+ //
+#if !NO_HASHSET
+ private static readonly HashSet<System.Threading.Timer> s_timers = new HashSet<System.Threading.Timer>();
+#else
+ private static readonly Dictionary<System.Threading.Timer, object> s_timers = new Dictionary<System.Threading.Timer, object>();
+#endif
+
+ private Action _action;
+ private System.Threading.Timer _timer;
+
+ public PeriodicTimer(Action action, TimeSpan period)
+ {
+ _action = action;
+ _timer = new System.Threading.Timer(Tick, null, period, period);
+
+ lock (s_timers)
+ {
+#if !NO_HASHSET
+ s_timers.Add(_timer);
+#else
+ s_timers.Add(_timer, null);
+#endif
+ }
+ }
+
+ private void Tick(object state)
+ {
+ _action();
+ }
+
+ public void Dispose()
+ {
+ var timer = default(System.Threading.Timer);
+
+ lock (s_timers)
+ {
+ timer = _timer;
+ _timer = null;
+
+ if (timer != null)
+ s_timers.Remove(timer);
+ }
+
+ if (timer != null)
+ {
+ timer.Dispose();
+ _action = Stubs.Nop;
+ }
+ }
+ }
+ }
+}
+#endif \ No newline at end of file