| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124 | // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.using System;#if !NO_WEAKTABLEusing System.Runtime.CompilerServices;#endifnamespace System.Reactive.Concurrency{    internal abstract class SchedulerWrapper : IScheduler, IServiceProvider    {        protected readonly IScheduler _scheduler;        public SchedulerWrapper(IScheduler scheduler)        {            _scheduler = scheduler;#if !NO_WEAKTABLE            _cache = new ConditionalWeakTable<IScheduler, IScheduler>();#endif        }        public DateTimeOffset Now        {            get { return _scheduler.Now; }        }        public IDisposable Schedule<TState>(TState state, Func<IScheduler, TState, IDisposable> action)        {            if (action == null)                throw new ArgumentNullException("action");            return _scheduler.Schedule(state, Wrap(action));        }        public IDisposable Schedule<TState>(TState state, TimeSpan dueTime, Func<IScheduler, TState, IDisposable> action)        {            if (action == null)                throw new ArgumentNullException("action");            return _scheduler.Schedule(state, dueTime, Wrap(action));        }        public IDisposable Schedule<TState>(TState state, DateTimeOffset dueTime, Func<IScheduler, TState, IDisposable> action)        {            if (action == null)                throw new ArgumentNullException("action");            return _scheduler.Schedule(state, dueTime, Wrap(action));        }        protected virtual Func<IScheduler, TState, IDisposable> Wrap<TState>(Func<IScheduler, TState, IDisposable> action)        {            return (self, state) => action(GetRecursiveWrapper(self), state);        }#if !NO_WEAKTABLE        private readonly ConditionalWeakTable<IScheduler, IScheduler> _cache;        public SchedulerWrapper(IScheduler scheduler, ConditionalWeakTable<IScheduler, IScheduler> cache)        {            _scheduler = scheduler;            _cache = cache;        }        protected IScheduler GetRecursiveWrapper(IScheduler scheduler)        {            return _cache.GetValue(scheduler, s => Clone(s, _cache));        }        protected abstract SchedulerWrapper Clone(IScheduler scheduler, ConditionalWeakTable<IScheduler, IScheduler> cache);#else            private readonly object _gate = new object();            private IScheduler _recursiveOriginal;            private IScheduler _recursiveWrapper;            protected IScheduler GetRecursiveWrapper(IScheduler scheduler)            {                var recursiveWrapper = default(IScheduler);                lock (_gate)                {                    //                    // Chances are the recursive scheduler will remain the same. In practice, this                    // single-shot caching scheme works out quite well. Notice we propagate our                    // mini-cache to recursive raw scheduler wrappers too.                    //                    if (!object.ReferenceEquals(scheduler, _recursiveOriginal))                    {                        _recursiveOriginal = scheduler;                        var wrapper = Clone(scheduler);                        wrapper._recursiveOriginal = scheduler;                        wrapper._recursiveWrapper = wrapper;                        _recursiveWrapper = wrapper;                    }                    recursiveWrapper = _recursiveWrapper;                }                return recursiveWrapper;            }            protected abstract SchedulerWrapper Clone(IScheduler scheduler);#endif        public object GetService(Type serviceType)        {            var serviceProvider = _scheduler as IServiceProvider;            if (serviceProvider == null)                return null;            var result = default(object);            if (TryGetService(serviceProvider, serviceType, out result))                return result;            return serviceProvider.GetService(serviceType);        }        protected abstract bool TryGetService(IServiceProvider provider, Type serviceType, out object service);    }}
 |