#region COPYRIGHT
//
//     THIS IS GENERATED BY TEMPLATE
//     
//     AUTHOR  :     ROYE
//     DATE       :     2011
//
//     COPYRIGHT (C) 2011, TIANXIAHOTEL TECHNOLOGIES CO., LTD. ALL RIGHTS RESERVED.
//
#endregion

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace System.Caching
{
    public class ThreadSafeCache<TKey, TItem> : ICache<TKey, TItem>
    {
        private readonly ICache<TKey, TItem> chainedCache;
        private readonly object syncRoot;

        public ThreadSafeCache(ICache<TKey, TItem> chainedCache)
            : this(chainedCache, null)
        {
        }

        public ThreadSafeCache(ICache<TKey, TItem> chainedCache, object syncRoot)
        {
            Guard.ArgumentNotNull(chainedCache, "chainedCache");
            this.chainedCache = chainedCache;
            this.syncRoot = syncRoot ?? new object();
        }

        protected virtual void InternalAdd(TKey key, TItem item)
        {
        }

        protected virtual void InternalRemoveKey(TKey key)
        {
        }

        protected virtual void InternalGet(TKey key)
        {
        }

        public void Add(TKey key, TItem item)
        {
            lock (syncRoot)
            {
                InternalAdd(key, item);
                chainedCache.Add(key, item);
            }
        }

        public void Clear()
        {
            lock (syncRoot)
            {
                chainedCache.Clear();
            }
        }

        public bool ContainsKey(TKey key)
        {
            lock (syncRoot)
            {
                return chainedCache.ContainsKey(key);
            }
        }

        public void RemoveKey(TKey key)
        {
            lock (syncRoot)
            {
                InternalRemoveKey(key);
                chainedCache.RemoveKey(key);
            }
        }

        public TItem Get(TKey key, Func<TItem> generator)
        {
            return this.Get(key, true, generator);
        }

        public TItem Get(TKey key, bool markAsHit, Func<TItem> generator)
        {
            lock (syncRoot)
            {
                InternalGet(key);
                return chainedCache.Get(key, markAsHit, generator);
            }
        }

        public int Count
        {
            get { return chainedCache.Count; }
        }

        public object SyncRoot
        {
            get { return syncRoot; }
        }

        public IEnumerator<TItem> GetEnumerator()
        {
            lock (syncRoot)
            {
                var enumerator = chainedCache.GetEnumerator();
                while (enumerator.MoveNext())
                {
                    yield return enumerator.Current;
                }
            }
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    }
}
