public void SingleAssignment() { var d = new SingleAssignmentDisposable(); d.IsDisposed.IsFalse(); var id1 = new IdDisp(1); var id2 = new IdDisp(2); var id3 = new IdDisp(3); // dispose first d.Dispose(); d.IsDisposed.IsTrue(); d.Disposable = id1; id1.IsDisposed.IsTrue(); d.Disposable = id2; id2.IsDisposed.IsTrue(); d.Disposable = id3; id3.IsDisposed.IsTrue(); // normal flow d = new SingleAssignmentDisposable(); id1 = new IdDisp(1); id2 = new IdDisp(2); id3 = new IdDisp(3); d.Disposable = id1; id1.IsDisposed.IsFalse(); d.Dispose(); id1.IsDisposed.IsTrue(); d.Disposable = id2; id2.IsDisposed.IsTrue(); d.Disposable = id3; id3.IsDisposed.IsTrue(); // exception flow d = new SingleAssignmentDisposable(); id1 = new IdDisp(1); id2 = new IdDisp(2); id3 = new IdDisp(3); d.Disposable = id1; AssertEx.Catch<InvalidOperationException>(() => d.Disposable = id2); // null d = new SingleAssignmentDisposable(); id1 = new IdDisp(1); d.Disposable = null; d.Dispose(); d.Disposable = null; }
public IDisposable Run(TParent parent) { _active = false; _running = false; _queue = new Queue <System.Reactive.TimeInterval <TSource> >(); _hasCompleted = false; _completeAt = default(TimeSpan); _hasFailed = false; _exception = default(Exception); _watch = _scheduler.StartStopwatch(); RunCore(parent); var sourceSubscription = new SingleAssignmentDisposable(); _sourceSubscription = sourceSubscription; sourceSubscription.Disposable = parent._source.SubscribeSafe(this); return(StableCompositeDisposable.Create(_sourceSubscription, _cancelable)); }
public override void OnNext(TSource value) { IObservable <TResult> nextObservable; try { nextObservable = parent.selectorWithIndex(value, index++); } catch (Exception ex) { try { observer.OnError(ex); } finally { Dispose(); }; return; } var disposable = new SingleAssignmentDisposable(); collectionDisposable.Add(disposable); var collectionObserver = new SelectMany(this, disposable); disposable.Disposable = nextObservable.Subscribe(collectionObserver); }
public IDisposable Run() { leftSubscription = new SingleAssignmentDisposable(); rightSubscription = new SingleAssignmentDisposable(); var d = StableCompositeDisposable.Create(leftSubscription, rightSubscription); var left = new Amb(); left.targetDisposable = d; left.targetObserver = new AmbDecisionObserver(this, AmbState.Left, rightSubscription, left); var right = new Amb(); right.targetDisposable = d; right.targetObserver = new AmbDecisionObserver(this, AmbState.Right, leftSubscription, right); leftSubscription.Disposable = parent.source.Subscribe(left); rightSubscription.Disposable = parent.second.Subscribe(right); return(d); }
/// <summary> /// Submit the drain task via the appropriate scheduler if /// there is no drain currently running (wip > 0). /// </summary> private void Schedule() { if (Interlocked.Increment(ref _wip) == 1) { var newTask = new SingleAssignmentDisposable(); if (Disposable.TrySetMultiple(ref _task, newTask)) { newTask.Disposable = _scheduler.Schedule(this, DrainShortRunningFunc); } // If there was a cancellation, clear the queue // of items. This doesn't have to be inside the // wip != 0 (exclusive) mode as the queue // is of a multi-consumer type. if (Volatile.Read(ref _disposed)) { Clear(_queue); } } }
private void CreateTimer() { var m = new SingleAssignmentDisposable(); Disposable.TrySetSerial(ref _timerSerial, m); var isSpan = false; var isShift = false; if (_nextSpan == _nextShift) { isSpan = true; isShift = true; } else if (_nextSpan < _nextShift) { isSpan = true; } else { isShift = true; } var newTotalTime = isSpan ? _nextSpan : _nextShift; var ts = newTotalTime - _totalTime; _totalTime = newTotalTime; if (isSpan) { _nextSpan += _timeShift; } if (isShift) { _nextShift += _timeShift; } m.Disposable = _scheduler.ScheduleAction((@this: this, isSpan, isShift), ts, tuple => [email protected](tuple.isSpan, tuple.isShift)); }
public void SchedulePeriodic_Nested() { using (WinFormsTestUtils.RunTest(out var lbl)) { var evt = new ManualResetEvent(false); var id = Thread.CurrentThread.ManagedThreadId; var sch = new ControlScheduler(lbl); sch.Schedule(() => { lbl.Text = "Okay"; var d = new SingleAssignmentDisposable(); d.Disposable = sch.SchedulePeriodic(1, TimeSpan.FromSeconds(0.1), n => { lbl.Text = "Okay " + n; Assert.NotEqual(id, Thread.CurrentThread.ManagedThreadId); if (n == 3) { d.Dispose(); sch.Schedule(TimeSpan.FromSeconds(0.2), () => { Assert.Equal("Okay 3", lbl.Text); Assert.NotEqual(id, Thread.CurrentThread.ManagedThreadId); evt.Set(); }); } return(n + 1); }); }); evt.WaitOne(); } }
public ReactiveDerivedCollectionFromObservable( IObservable <T> observable, TimeSpan?withDelay = null, Action <Exception> onError = null, IScheduler scheduler = null) { scheduler = scheduler ?? RxApp.MainThreadScheduler; _inner = new SingleAssignmentDisposable(); onError = onError ?? (ex => RxApp.DefaultExceptionHandler.OnNext(ex)); if (withDelay == null) { _inner.Disposable = observable.ObserveOn(scheduler).Subscribe(InternalAdd, onError); return; } // On a timer, dequeue items from queue if they are available var queue = new Queue <T>(); var disconnect = Observable.Timer(withDelay.Value, withDelay.Value, scheduler) .Subscribe(_ => { if (queue.Count > 0) { InternalAdd(queue.Dequeue()); } }); _inner.Disposable = disconnect; // When new items come in from the observable, stuff them in the queue. observable.ObserveOn(scheduler).Subscribe(queue.Enqueue, onError); // This is a bit clever - keep a running count of the items actually // added and compare them to the final count of items provided by the // Observable. Combine the two values, and when they're equal, // disconnect the timer ItemsAdded.Scan(0, (acc, _) => acc + 1).Zip( observable.Aggregate(0, (acc, _) => acc + 1), (l, r) => l == r).Where(x => x).Subscribe(_ => disconnect.Dispose()); }
public IDisposable Subscribe( IMessagingSession messagingSession, string destination, Action <BinaryMessage, Action <bool> > callback, string messageType, int priority) { if (m_IsDisposing) { throw new ObjectDisposedException("ProcessingGroup " + Name); } var taskFactory = m_SchedulingStrategy.GetTaskFactory(priority); var subscription = new SingleAssignmentDisposable(); subscription.Disposable = messagingSession.Subscribe( destination, (message, ack) => { Interlocked.Increment(ref m_TasksInProgress); taskFactory.StartNew(() => { Interlocked.Increment(ref m_ReceivedMessages); //if subscription is disposed unack message immediately if (subscription.IsDisposed) { ack(false); } else { callback(message, ack); Interlocked.Increment(ref m_ProcessedMessages); } Interlocked.Decrement(ref m_TasksInProgress); }, TaskCreationOptions.HideScheduler); }, messageType); return(subscription); }
public IDisposable SchedulePeriodic <TState>(TState state, TimeSpan period, Func <TState, TState> action) { var failed = false; var d = new SingleAssignmentDisposable(); d.Disposable = _scheduler.SchedulePeriodic(state, period, state_ => { // // Cancellation may not be granted immediately; prevent from running user // code in that case. Periodic schedulers are assumed to introduce some // degree of concurrency, so we should return from the SchedulePeriodic // call eventually, allowing the d.Dispose() call in the catch block to // take effect. // if (failed) { return(default(TState)); } try { return(action(state_)); } catch (TException exception) { failed = true; if (!_handler(exception)) { throw; } d.Dispose(); return(default(TState)); } }); return(d); }
public static IObservable <TSource> SubscribeOn <TSource>( this IObservable <TSource> source, bool doNotScheduleDisposal, IScheduler scheduler) { if (!doNotScheduleDisposal) { return(source.SubscribeOn(scheduler)); } return(Observable.Create <TSource>(observer => { // Implementation is based on that of the native SubscribeOn operator in Rx var s = new SingleAssignmentDisposable(); var d = new SerialDisposable(); d.Disposable = s; s.Disposable = scheduler.Schedule(() => { d.Disposable = source.SubscribeSafe(observer); }); return d; })); }
private static void AttachPaginator(IPaginator paginator, DataGrid dataGrid) { var subscription = new SingleAssignmentDisposable(); SetPaginatorSubscription(dataGrid, subscription); var onPropertyChanged = new PropertyChangedEventHandler((sender, e) => UpdateByPaginator(dataGrid)); dataGrid.ItemsSource = paginator.CreateReactiveList(); dataGrid.Sorting += OnDataGridSorting; paginator.PropertyChanged += onPropertyChanged; subscription.Disposable = Disposable.Create(() => { dataGrid.ItemsSource = Array.Empty <object>(); dataGrid.Sorting -= OnDataGridSorting; paginator.PropertyChanged -= onPropertyChanged; }); UpdateByPaginator(dataGrid); }
public IDisposable Subscribe(IObserver <TResult> observer) { observers.Add(observer); SingleAssignmentDisposable dis = null; bool wasConnected = connected; var coll = disposables; // this is used to detach field reference at disposal (the field might be already null). if (wasConnected) { dis = new SingleAssignmentDisposable(); dis.Disposable = sub.Subscribe(observer); coll.Add(dis); } return(Disposable.Create(() => { observers.Remove(observer); if (wasConnected) // note: local variable. If it was not added, then do not add it. { coll.Remove(dis); dis.Dispose(); } })); }
private IDisposable ScheduleOnDispatcherNow <TState>(TState state, Func <IScheduler, TState, IDisposable> action) { try { Interlocked.CompareExchange(ref _dispatcher, CoreApplication.Views.FirstOrDefault()?.Dispatcher, null); } catch (Exception ex) { // Ignore } if (_dispatcher == null || _dispatcher.HasThreadAccess) { return(action(this, state)); } var d = new SingleAssignmentDisposable(); var dispatchResult = _dispatcher.RunAsync( Priority, () => { if (!d.IsDisposed) { try { d.Disposable = action(this, state); } catch (Exception ex) { RaiseUnhandledException(ex); } } }); return(StableCompositeDisposable.Create( d, Disposable.Create(() => dispatchResult.Cancel()))); }
/// <summary> /// Schedules an action to be executed. /// </summary> /// <typeparam name="TState">The type of the state passed to the scheduled action.</typeparam> /// <param name="state">State passed to the action to be executed.</param> /// <param name="action">Action to be executed.</param> /// <returns>The disposable object used to cancel the scheduled action (best effort).</returns> /// <exception cref="ArgumentNullException"><paramref name="action"/> is null.</exception> public override IDisposable Schedule <TState>(TState state, Func <IScheduler, TState, IDisposable> action) { if (action == null) { throw new ArgumentNullException(nameof(action)); } var d = new SingleAssignmentDisposable(); var cancel = s_cal.QueueUserWorkItem(_ => { if (!d.IsDisposed) { d.Disposable = action(this, state); } }, null); return(StableCompositeDisposable.Create( d, cancel )); }
private void CreateWindowClose() { var windowClose = default(IObservable <TWindowClosing>); try { windowClose = _windowClosingSelector(); } catch (Exception exception) { lock (_gate) { ForwardOnError(exception); } return; } var closingSubscription = new SingleAssignmentDisposable(); _m.Disposable = closingSubscription; closingSubscription.Disposable = windowClose.SubscribeSafe(new WindowClosingObserver(this, closingSubscription)); }
private static IDisposable InvokeAsync <TState>(IScheduler self, TState s, Func <IScheduler, TState, CancellationToken, Task <IDisposable> > action) { var c = new CancellationDisposable(); var d = new SingleAssignmentDisposable(); action(new CancelableScheduler(self, c.Token), s, c.Token).ContinueWith(t => { if (t.IsCanceled) { return; } if (t.Exception != null) { t.Exception.Handle(e => e is OperationCanceledException); } d.Disposable = t.Result; }, TaskContinuationOptions.ExecuteSynchronously); return(StableCompositeDisposable.Create(c, d)); }
public static void AreElementsEqual <T> (IObservable <T> expected, IObservable <T> actual, string message) { if (expected == null) { if (actual != null) { throw new ArgumentNullException("expected"); } else { return; } } int ie = 0, ia = 0, endE = 0, endA = 0; var iex = expected.Select(e => new Indexed <T> (ie++, e)).Finally(() => endE = ie); var iac = actual.Select(e => new Indexed <T> (ia++, e)).Finally(() => endA = ia); var source = iex.Zip(iac, (e, a) => { Assert.AreEqual(e.Value, a.Value, String.Format("{0} (Items differ at index {1})", message, e.Index)); return(Unit.Default); }); var dis = new SingleAssignmentDisposable(); dis.Disposable = source.Finally <Unit> (() => dis.Dispose()).Subscribe(v => {}, () => Assert.AreEqual(endE, endA, String.Format("{0} (Items counts differ: expected {1} but got {2})", endE, endA))); }
/// <summary> /// Schedules an action to be executed on the dispatcher. /// </summary> /// <typeparam name="TState">The type of the state passed to the scheduled action.</typeparam> /// <param name="state">State passed to the action to be executed.</param> /// <param name="action">Action to be executed.</param> /// <returns>The disposable object used to cancel the scheduled action (best effort).</returns> /// <exception cref="ArgumentNullException"><paramref name="action"/> is <c>null</c>.</exception> public override IDisposable Schedule <TState>(TState state, Func <IScheduler, TState, IDisposable> action) { if (action == null) { throw new ArgumentNullException(nameof(action)); } var d = new SingleAssignmentDisposable(); Dispatcher.BeginInvoke( new Action(() => { if (!d.IsDisposed) { d.Disposable = action(this, state); } }), Priority ); return(d); }
public void SchedulePeriodic_Nested() { var evt = new ManualResetEvent(false); var id = Thread.CurrentThread.ManagedThreadId; var lbl = CreateLabel(); var sch = new ControlScheduler(lbl); sch.Schedule(() => { lbl.Text = "Okay"; var d = new SingleAssignmentDisposable(); d.Disposable = sch.SchedulePeriodic(1, TimeSpan.FromSeconds(0.1), n => { lbl.Text = "Okay " + n; Assert.AreNotEqual(id, Thread.CurrentThread.ManagedThreadId); if (n == 3) { d.Dispose(); sch.Schedule(TimeSpan.FromSeconds(0.2), () => { Assert.AreEqual("Okay 3", lbl.Text); Assert.AreNotEqual(id, Thread.CurrentThread.ManagedThreadId); evt.Set(); }); } return n + 1; }); }); evt.WaitOne(); Application.Exit(); }
public IDisposable Run() { _scheduler = _parent._scheduler; _cancelable = new SerialDisposable(); _gate = new object(); _active = false; _running = false; _queue = new Queue <System.Reactive.TimeInterval <TSource> >(); _hasCompleted = false; _completeAt = default(TimeSpan); _hasFailed = false; _exception = default(Exception); _watch = _scheduler.StartStopwatch(); if (_parent._dueTimeA.HasValue) { _ready = false; var dueTimeA = _parent._dueTimeA.Value; _cancelable.Disposable = _scheduler.Schedule(dueTimeA, Start); } else { _ready = true; var dueTimeR = _parent._dueTimeR.Value; _delay = Scheduler.Normalize(dueTimeR); } var sourceSubscription = new SingleAssignmentDisposable(); _sourceSubscription = sourceSubscription; sourceSubscription.Disposable = _parent._source.SubscribeSafe(this); return(new CompositeDisposable(_sourceSubscription, _cancelable)); }
public virtual IObservable <bool> EstablishEncryptionAsync() { ValidateDisposed(); var future = new AsyncSubject <bool>(); var watchStatusChanged = new SingleAssignmentDisposable(); watchStatusChanged.Disposable = this.ObserveStatusChanged().Subscribe(x => { if (x == StatusCode.EncryptionFailedToEstablish) { watchStatusChanged.Dispose(); future.OnError(new EncryptionFailedToEstablishException()); } if (x == StatusCode.EncryptionEstablished) { watchStatusChanged.Dispose(); future.OnNext(true); future.OnCompleted(); } }); if (this.EstablishEncryption()) { return(future.Timeout(Timeout).Catch((Exception ex) => { watchStatusChanged.Dispose(); this.Disconnect(); return Observable.Throw <bool>(ex); })); } else { watchStatusChanged.Dispose(); return(Observable.Return(false)); } }
private void CreateBufferClose() { var bufferClose = default(IObservable <TBufferClosing>); try { bufferClose = _bufferClosingSelector(); } catch (Exception exception) { lock (_gate) { ForwardOnError(exception); } return; } var closingSubscription = new SingleAssignmentDisposable(); Disposable.TrySetSerial(ref _bufferClosingSerialDisposable, closingSubscription); closingSubscription.Disposable = bufferClose.SubscribeSafe(new BufferClosingObserver(this, closingSubscription)); }
public override IDisposable Schedule <TState>(TState state, TimeSpan dueTime, Func <IScheduler, TState, IDisposable> action) { if (action == null) { throw new ArgumentNullException("action"); } if (dueTime.Ticks <= 0) { return(Schedule <TState>(state, action)); } var timer = ConcurrencyAbstractionLayer.Current.StartStopwatch(); var m = new SingleAssignmentDisposable(); if (asyncLock == null) { asyncLock = new AsyncLock(); } asyncLock.Wait(() => { if (!m.IsDisposed) { var sleep = dueTime - timer.Elapsed; if (sleep.Ticks > 0) { ConcurrencyAbstractionLayer.Current.Sleep(sleep); } if (!m.IsDisposed) { m.Disposable = action(this, state); } } }); return(m); }
public override void OnError(Exception error) { TException val = error as TException; if (val != null) { UniRx.IObservable <T> observable; try { observable = ((!(parent.errorHandler == new Func <TException, UniRx.IObservable <T> >(Stubs.CatchIgnore <T>))) ? parent.errorHandler(val) : Observable.Empty <T>()); } catch (Exception error2) { try { observer.OnError(error2); } finally { Dispose(); } return; } SingleAssignmentDisposable singleAssignmentDisposable = new SingleAssignmentDisposable(); serialDisposable.Disposable = singleAssignmentDisposable; singleAssignmentDisposable.Disposable = observable.Subscribe(observer); } else { try { observer.OnError(error); } finally { Dispose(); } } }
/// <summary> /// Schedules an action to be executed. /// </summary> /// <typeparam name="TState">The type of the state passed to the scheduled action.</typeparam> /// <param name="state">State passed to the action to be executed.</param> /// <param name="action">Action to be executed.</param> /// <returns>The disposable object used to cancel the scheduled action (best effort).</returns> /// <exception cref="ArgumentNullException"><paramref name="action"/> is null.</exception> public override IDisposable Schedule <TState>(TState state, Func <IScheduler, TState, IDisposable> action) { if (action == null) { throw new ArgumentNullException(nameof(action)); } var d = new SingleAssignmentDisposable(); var res = global::Windows.System.Threading.ThreadPool.RunAsync(iaa => { if (!d.IsDisposed) { d.Disposable = action(this, state); } }, Priority, Options); return(new CompositeDisposable( d, Disposable.Create(res.Cancel) )); }
public void SchedulePeriodic() { using (DispatcherHelpers.RunTest(out var disp)) { var evt = new ManualResetEvent(false); var id = Thread.CurrentThread.ManagedThreadId; var sch = new DispatcherScheduler(disp); var d = new SingleAssignmentDisposable(); d.Disposable = sch.SchedulePeriodic(1, TimeSpan.FromSeconds(0.1), n => { Assert.NotEqual(id, Thread.CurrentThread.ManagedThreadId); if (n == 3) { d.Dispose(); sch.Schedule(TimeSpan.FromSeconds(0.2), () => { Assert.NotEqual(id, Thread.CurrentThread.ManagedThreadId); evt.Set(); }); } if (n > 3) { Assert.True(false); } return(n + 1); }); evt.WaitOne(); } }
protected void Subscribe(DuplexCallbackId id) { IObservableDuplexCallback observable; if (!obsevableCallbacks.TryGetValue(id.ClientId, out observable)) { throw new InvalidOperationException(Errors.ProtocolInvalidDuplexId); } #if TRACE var sourceId = GetSourceId(id); Log.Subscribing(observable.Name, false, true, sourceId, LogMessages.Received); #endif var subscription = new SingleAssignmentDisposable(); var subscriptionId = RegisterSubscription(new NamedDisposable(observable.Name, subscription)); try { subscription.Disposable = observable.Subscribe( value => SendOnNext(observable.Name, id, value), ex => SendOnError(observable.Name, id, ExceptionDispatchInfo.Capture(ex)), () => SendOnCompleted(observable.Name, id)); } catch (Exception ex) { SendOnError(observable.Name, id, ExceptionDispatchInfo.Capture(ex)); return; } #if TRACE Log.Subscribed(observable.Name, false, true, sourceId, LogMessages.Sending); #endif SendSubscribeResponse(id, subscriptionId); }
public IDisposable Run() { var srcs = _parent._sources.ToArray(); var N = srcs.Length; _queues = new Queue <TSource> [N]; for (int i = 0; i < N; i++) { _queues[i] = new Queue <TSource>(); } _isDone = new bool[N]; _subscriptions = new SingleAssignmentDisposable[N]; _gate = new object(); for (int i = 0; i < N; i++) { var j = i; var d = new SingleAssignmentDisposable(); _subscriptions[j] = d; var o = new SourceObserver(this, j); d.Disposable = srcs[j].SubscribeSafe(o); } return(new CompositeDisposable(_subscriptions) { Disposable.Create(() => { foreach (var q in _queues) { q.Clear(); } }) }); }
public void Error() { var resource = new SingleAssignmentDisposable(); var before = -1; var after = -1; var source = CompletableSource.Create(e => { e.SetResource(resource); before = e.IsDisposed() ? 1 : 0; e.OnError(new InvalidOperationException()); after = e.IsDisposed() ? 1 : 0; }); source.Test() .AssertFailure(typeof(InvalidOperationException)); Assert.AreEqual(0, before); Assert.AreEqual(1, after); Assert.True(resource.IsDisposed()); }
public void Basic() { var resource = new SingleAssignmentDisposable(); var before = -1; var after = -1; var source = CompletableSource.Create(e => { e.SetResource(resource); before = e.IsDisposed() ? 1 : 0; e.OnCompleted(); after = e.IsDisposed() ? 1 : 0; }); source.Test() .AssertResult(); Assert.AreEqual(0, before); Assert.AreEqual(1, after); Assert.True(resource.IsDisposed()); }
public virtual IObservable<bool> ConnectAsync(string serverAddress, string applicationName) { ValidateDisposed(); var future = new AsyncSubject<bool>(); var watchStatusChanged = new SingleAssignmentDisposable(); watchStatusChanged.Disposable = this.ObserveStatusChanged().Subscribe(x => { if (x == StatusCode.ExceptionOnConnect) { watchStatusChanged.Dispose(); future.OnError(new ConnectionFailedException(serverAddress, applicationName)); } if (x == StatusCode.Connect) { watchStatusChanged.Dispose(); future.OnNext(true); future.OnCompleted(); } }); if (this.Connect(serverAddress, applicationName)) { this.LastConnectServerAddress = serverAddress; this.LastConnectApplicationName = applicationName; return future.Timeout(Timeout).Catch((Exception ex) => { watchStatusChanged.Dispose(); this.Disconnect(); return Observable.Throw<bool>(ex); }); } else { watchStatusChanged.Dispose(); return Observable.Return(false); } }
public virtual IObservable<bool> EstablishEncryptionAsync() { ValidateDisposed(); var future = new AsyncSubject<bool>(); var watchStatusChanged = new SingleAssignmentDisposable(); watchStatusChanged.Disposable = this.ObserveStatusChanged().Subscribe(x => { if (x == StatusCode.EncryptionFailedToEstablish) { watchStatusChanged.Dispose(); future.OnError(new EncryptionFailedToEstablishException()); } if (x == StatusCode.EncryptionEstablished) { watchStatusChanged.Dispose(); future.OnNext(true); future.OnCompleted(); } }); if (this.EstablishEncryption()) { return future.Timeout(Timeout).Catch((Exception ex) => { watchStatusChanged.Dispose(); this.Disconnect(); return Observable.Throw<bool>(ex); }); } else { watchStatusChanged.Dispose(); return Observable.Return(false); } }