void OnPeek(MetaResourceBase resource)
        {
#if LOG_CONTENT_ACQUIRE
            log.Write("p  " +
                      //(ob != null ? ob.GetHashCode().ToString() : "null").PadRight(14) +
                      " " + resource);
#endif
        }
        void OnResetAcquire(MetaResourceBase resource, object ob)
        {
#if LOG_CONTENT
            log.Write("r+ " +
                      (ob != null ? ob.GetHashCode().ToString() : "null").PadRight(14) +
                      " " + resource);
#endif
        }
 static void VerifyMetaResourceType(MetaResourceBase metaResource)
 {
     if (metaResource == null)
     {
         return;
     }
     VerifyMetaResourceType(metaResource.GetType(), (error) => { throw new Exception(error); });
 }
 static void VerifyMetaResourceClone(MetaResourceBase metaResource)
 {
     if (metaResource == null)
     {
         return;
     }
     VerifyMetaResourceClone(metaResource, (MetaResourceBase)metaResource.Clone());
 }
        void OnDestroy(MetaResourceBase resource, object ob)
        {
#if LOG_CONTENT
            log.Write("-  " +
                      (ob != null ? ob.GetHashCode().ToString() : "null").PadRight(14) +
                      " " + resource);
#endif
#if CONTENT_STATISTICS
            pcNumberOfObjects.Decrement();
#endif
        }
        void OnAcquire(MetaResourceBase resource)
        {
#if LOG_CONTENT_ACQUIRE
            log.Write("a  " +
                      //(ob != null ? ob.GetHashCode().ToString() : "null").PadRight(14) +
                      " " + resource);
#endif
#if CONTENT_STATISTICS
            pcTotalNumberOfReferences.Increment();
#endif
        }
        void OnConstruct(MetaResourceBase resource, object ob)
        {
#if LOG_CONTENT
            log.Write("+  " +
                      (ob != null ? ob.GetHashCode().ToString() : "null").PadRight(14) + " " +
                      (ob != null ? ob.GetType().Name : "null").PadRight(14) +
                      " " + resource);
#endif
#if CONTENT_STATISTICS
            pcNumberOfObjects.Increment();
#endif
        }
 /// <summary>
 /// Returns the requested resource, specified by the MetaResource. The resource
 /// has to be Released once it's no longer used.
 /// </summary>
 public T Acquire <T>(MetaResourceBase metaResource) where T : class
 {
     VerifyMetaResource(metaResource);
     if (resetting)
     {
         return(ResetAcquire <T>(metaResource));
     }
     else
     {
         return(InnerAcquire <T>(metaResource));
     }
 }
        /// <summary>
        /// Temporary acquire of an object which does not need to be Released
        /// The object can only be guaranteed to be valid until the next Prune
        /// </summary>
        public T Peek <T>(MetaResourceBase metaResource) where T : class
        {
            if (metaResource == null)
            {
                return(default(T));
            }
            OnPeek(metaResource);
            VerifyMetaResource(metaResource);

            // This is a small optimization, just see if the last acquired object was the same as this one,
            // in that case return it. Turns out often around half the acquires can be handled like this
            if (Object.Equals(lastAcquiredMetaResource, metaResource))
            {
                lastAcquiredResource.LastAcquired = pruneK;
                return((T)lastAcquiredResource.Object);
            }

            var key = new Common.Tuple <MetaResourceBase, Type>(metaResource, typeof(T));

            Resource o = null;

#if THREAD_SAFE_CONTENT
            lock (lockObject)
#endif
            if (contentByMetaResourceAndType.TryGetValue(key, out o))
            {
                o.LastAcquired = pruneK;

                key.First = (MetaResourceBase)metaResource.Clone();

                lastAcquiredMetaResource = key;
                lastAcquiredResource     = o;
                return((T)o.Object);
            }

            T ob;
            if (resetting)
            {
                ob = ResetAcquire <T>(metaResource);
            }
            else
            {
                ob = Acquire <T>(metaResource);
            }
            Release(ob);
            return(ob);
        }
        T ResetAcquire <T>(MetaResourceBase metaResource) where T : class
        {
            if (metaResource == null)
            {
                return(default(T));
            }


            var key = new Common.Tuple <MetaResourceBase, Type>((MetaResourceBase)metaResource.Clone(), typeof(T));

            Resource o;

            // This object has already been reset
            if (resetResourcesById.TryGetValue(key, out o))
            {
                return((T)o.Object);
            }

            // This resource doesn't exists yet, create it
            bool ok = false;

#if THREAD_SAFE_CONTENT
            lock (lockObject)
#endif
            ok = contentByMetaResourceAndType.TryGetValue(key, out o);
            if (!ok)
            {
                return(InnerAcquire <T>(metaResource));
            }

            var mapperKey = new Common.Tuple <Type, Type>(o.MetaResource.GetType(), o.Object.GetType());

            o.Object = mappers[mapperKey].Do(MetaResourceDo.ResetDevice, o.MetaResource, this, o.Object);
            OnResetAcquire(o.MetaResource, o.Object);
#if THREAD_SAFE_CONTENT
            lock (lockObject)
#endif
            contentByResource.Add(o.Object, o);
            resetResourcesById.Add(key, o);

            return((T)o.Object);
        }
        static void VerifyMetaResourceClone(MetaResourceBase original, MetaResourceBase copy)
        {
            bool equals = Object.Equals(original, copy);

            foreach (var v in original.GetType().GetProperties())
            {
                if (typeof(MetaResourceBase).IsAssignableFrom(v.PropertyType))
                {
                    var o = (MetaResourceBase)((MetaResourceBase)v.GetValue(original, null));
                    if (o != null)
                    {
                        var c = (MetaResourceBase)o.Clone();
                        VerifyMetaResourceClone(o, c);
                    }
                }
            }
            if (!equals)
            {
                throw new Exception(original + " does not equal " + copy);
            }
        }
 static void VerifyMetaResource(MetaResourceBase metaResource)
 {
     VerifyMetaResourceType(metaResource);
     VerifyMetaResourceClone(metaResource);
 }
        T InnerAcquire <T>(MetaResourceBase metaResource) where T : class
        {
            if (metaResource == null)
            {
                return(default(T));
            }

            var key = new Common.Tuple <MetaResourceBase, Type>(metaResource, typeof(T));

            // This is a small optimization, just see if the last acquired object was the same as this one,
            // in that case return it. Turns out often around half the acquires can be handled like this
            if (Object.Equals(lastAcquiredMetaResource, metaResource))
            {
                OnAcquire(metaResource);
                lastAcquiredResource.References++;
                lastAcquiredResource.LastAcquired = pruneK;
                return((T)lastAcquiredResource.Object);
            }


            Resource o = null;

#if THREAD_SAFE_CONTENT
            lock (lockObject)
            {
#endif
            if (contentByMetaResourceAndType.TryGetValue(key, out o))
            {
                OnAcquire(metaResource);
                o.References++;
                o.LastAcquired           = pruneK;
                key.First                = (MetaResourceBase)metaResource.Clone();
                lastAcquiredMetaResource = key;
                lastAcquiredResource     = o;
                return((T)o.Object);
            }

            key.First = (MetaResourceBase)metaResource.Clone();
#if DEBUG_CONTENT
            if (key.First.GetHashCode() != metaResource.GetHashCode())
            {
                throw new Exception("Error in meta resource Clone or GetHashCode");
            }
            if (!Object.Equals(key.First, metaResource))
            {
                string diffs = "";
                key.First.ReportEqualsDiffs(metaResource, (d) => diffs += "\n" + d);
                throw new Exception("Error in meta resource Clone or Equals\n\nDiffs:\n" + diffs);
            }
#endif

            var mapperKey = new Common.Tuple <Type, Type>(metaResource.GetType(), typeof(T));
            object ob     = mappers[mapperKey].Do(MetaResourceDo.Construct, metaResource, this, null);
            OnConstruct(metaResource, ob);
            if (ob == null)
            {
                lastAcquiredMetaResource = new Common.Tuple <MetaResourceBase, Type>(null, null);
                lastAcquiredResource     = null;
                return((T)ob);
            }
#if DEBUG_CONTENT
            if (key.First.GetHashCode() != metaResource.GetHashCode())
            {
                throw new Exception("MetaResource was changed during construction (No longer the same hash code)");
            }
            if (!Object.Equals(key.First, metaResource))
            {
                throw new Exception("MetaResource was changed during construction (No longer Equals)");
            }
#endif

#if THREAD_SAFE_CONTENT
            //lock (lockObject)
            //{
#endif
            OnAcquire(metaResource);
            contentByMetaResourceAndType.Add(key, o = new Resource
            {
                MetaResource  = metaResource,
                Object        = ob,
                References    = 1,
                LastAcquired  = pruneK,
                FirstAcquired = pruneK
            });
#if DEBUG_CONTENT
            Resource debugR;
            if (contentByResource.TryGetValue(o.Object, out debugR))
            {
                throw new Exception("Content by resource old: " + debugR.MetaResource + " new: " + o.MetaResource);
            }
#endif
            contentByResource.Add(o.Object, o);

#if THREAD_SAFE_CONTENT
        }
#endif

            lastAcquiredMetaResource = key;
            lastAcquiredResource     = o;
            return((T)o.Object);
        }