Example #1
0
        /// <summary>
        /// Creates new instance and adds to pool
        /// </summary>
        protected virtual async Task <PoolServiceDescriptor <TService> > CreateNew(IContainerScope scope, bool locked)
        {
            PoolServiceDescriptor <TService> descriptor = new PoolServiceDescriptor <TService>();

            descriptor.Locked         = locked;
            descriptor.Scope          = scope;
            descriptor.LockExpiration = DateTime.UtcNow.Add(Options.MaximumLockDuration);

            if (Type == ImplementationType.Scoped && scope != null)
            {
                //we couldn't find any created instance. create new.
                object instance = await Container.CreateInstance(typeof(TImplementation), scope);

                scope.PutItem(typeof(TService), instance);
                descriptor.Instance = (TService)instance;
            }
            else
            {
                object instance = await Container.CreateInstance(typeof(TImplementation), scope);

                descriptor.Instance = (TService)instance;
            }

            if (_func != null)
            {
                _func(descriptor.Instance);
            }

            lock (_descriptors)
                _descriptors.Add(descriptor);

            return(descriptor);
        }
Example #2
0
        /// <summary>
        /// Waits until an item is available.
        /// If any available item cannot be found, creates new if exceed possible. Otherwise returns null
        /// </summary>
        private async Task WaitForAvailable(IContainerScope scope, TaskCompletionSource <PoolServiceDescriptor <TService> > state)
        {
            //try to get when available
            if (Options.WaitAvailableDuration > TimeSpan.Zero)
            {
                DateTime waitMax = DateTime.UtcNow.Add(Options.WaitAvailableDuration);
                while (DateTime.UtcNow < waitMax)
                {
                    await Task.Delay(5);

                    PoolServiceDescriptor <TService> pdesc = GetFromCreatedItem(scope);

                    if (pdesc != null)
                    {
                        state.SetResult(pdesc);
                        return;
                    }
                }
            }

            //tried to get but timed out, if we can exceed limit, create new one and return
            PoolServiceDescriptor <TService> result = Options.ExceedLimitWhenWaitTimeout ? (await CreateNew(scope, true)) : null;

            state.SetResult(result);
        }
Example #3
0
        /// <summary>
        /// Gets service descriptor for re-use from already created services list
        /// </summary>
        private PoolServiceDescriptor <TService> GetFromCreatedItem(IContainerScope scope)
        {
            lock (Descriptors)
            {
                if (Type == ImplementationType.Scoped)
                {
                    PoolServiceDescriptor <TService> scoped = Descriptors.FirstOrDefault(x => x.Scope == scope);

                    if (scoped != null)
                    {
                        if (Options.IdleTimeout > TimeSpan.Zero)
                        {
                            scoped.IdleTimeout = DateTime.UtcNow + Options.IdleTimeout;
                        }
                        else
                        {
                            scoped.IdleTimeout = null;
                        }
                    }

                    return(scoped);
                }

                PoolServiceDescriptor <TService> transient = Descriptors.FirstOrDefault(x => !x.Locked || x.LockExpiration < DateTime.UtcNow);
                if (transient == null)
                {
                    return(null);
                }

                transient.Scope          = scope;
                transient.Locked         = true;
                transient.LockExpiration = DateTime.UtcNow.Add(Options.MaximumLockDuration);

                if (Options.IdleTimeout > TimeSpan.Zero)
                {
                    transient.IdleTimeout = DateTime.UtcNow + Options.IdleTimeout;
                }
                else
                {
                    transient.IdleTimeout = null;
                }

                return(transient);
            }
        }
Example #4
0
        /// <summary>
        /// Gets service descriptor for re-use from already created services list
        /// </summary>
        private PoolServiceDescriptor <TService> GetFromCreatedItem(IContainerScope scope)
        {
            lock (_descriptors)
            {
                if (Type == ImplementationType.Scoped)
                {
                    PoolServiceDescriptor <TService> scoped = _descriptors.FirstOrDefault(x => x.Scope == scope);
                    return(scoped);
                }

                PoolServiceDescriptor <TService> transient = _descriptors.FirstOrDefault(x => !x.Locked || x.LockExpiration < DateTime.UtcNow);
                if (transient == null)
                {
                    return(null);
                }

                transient.Scope          = scope;
                transient.Locked         = true;
                transient.LockExpiration = DateTime.UtcNow.Add(Options.MaximumLockDuration);
                return(transient);
            }
        }
Example #5
0
        /// <summary>
        /// Creates new instance and adds to pool
        /// </summary>
        protected virtual PoolServiceDescriptor <TService> CreateNew(IContainerScope scope, bool locked)
        {
            PoolServiceDescriptor <TService> descriptor = new PoolServiceDescriptor <TService>();

            descriptor.Locked         = locked;
            descriptor.Scope          = scope;
            descriptor.LockExpiration = DateTime.UtcNow.Add(Options.MaximumLockDuration);
            if (Options.IdleTimeout > TimeSpan.Zero)
            {
                descriptor.IdleTimeout = DateTime.UtcNow + Options.IdleTimeout;
            }
            else
            {
                descriptor.IdleTimeout = null;
            }

            object instance = Descriptor.CreateInstance((TwinoServiceProvider)Container.GetProvider(), scope);

            if (Type == ImplementationType.Scoped && scope != null)
            {
                //we couldn't find any created instance. create new.
                scope.PutItem(typeof(TService), instance);
                descriptor.Instance = (TService)instance;
            }
            else
            {
                descriptor.Instance = (TService)instance;
            }

            if (_func != null)
            {
                _func(descriptor.Instance);
            }

            lock (Descriptors)
                Descriptors.Add(descriptor);

            return(descriptor);
        }
Example #6
0
        /// <summary>
        /// Get an item from pool and locks it to prevent multiple usage at same time.
        /// The item should be released with Release method.
        /// </summary>
        public async Task <PoolServiceDescriptor> GetAndLock(IContainerScope scope = null)
        {
            PoolServiceDescriptor <TService> descriptor = GetFromCreatedItem(scope);

            if (descriptor != null)
            {
                return(descriptor);
            }

            //if there is no available instance and we have space in pool, create new
            int count;

            lock (_descriptors)
                count = _descriptors.Count;

            if (count < Options.PoolMaxSize)
            {
                return(await CreateNew(scope, true));
            }

            //if there is no available instance and there is no space to create new
            TaskCompletionSource <PoolServiceDescriptor <TService> > completionSource = new TaskCompletionSource <PoolServiceDescriptor <TService> >(TaskCreationOptions.RunContinuationsAsynchronously);

            ThreadPool.UnsafeQueueUserWorkItem(async state =>
            {
                try
                {
                    await WaitForAvailable(scope, state);
                }
                catch (Exception e)
                {
                    completionSource.SetException(e);
                }
            }, completionSource, false);

            return(await completionSource.Task);
        }
Example #7
0
 /// <summary>
 /// Releases pool item for re-using
 /// </summary>
 public void Release(PoolServiceDescriptor descriptor)
 {
     descriptor.Locked = false;
 }