<commit_before>using System;
using System.Collections.Generic;
using System.Linq;
using System.Diagnostics;
using System.IO;
using Microsoft.Xna.Framework.Graphics;

namespace Cocos2D
{
    public class CCTextureCache : IDisposable, ICCSelectorProtocol
    {
        struct AsyncStruct
        {
            public string  FileName;
            public Action<CCTexture2D> Action;
        };

        private List<AsyncStruct> _asyncLoadedImages = new List<AsyncStruct>();
        private Action _processingAction;
        private object _task;

        private static CCTextureCache s_sharedTextureCache;

        private readonly object m_pDictLock = new object();
        protected Dictionary<string, CCTexture2D> m_pTextures = new Dictionary<string, CCTexture2D>();

        ~CCTextureCache() 
        {
            Dispose();
        }

        private CCTextureCache()
        {
            _processingAction = new Action(
                () =>
                {
                    while (true)
                    {
                        AsyncStruct image;

                        lock (_asyncLoadedImages)
                        {
                            if (_asyncLoadedImages.Count == 0)
                            {
                                _task = null;
                                return;
                            }
                            image = _asyncLoadedImages[0];
                            _asyncLoadedImages.RemoveAt(0);
                        }

                        try
                        {
                            var texture = AddImage(image.FileName);

                            if (image.Action != null)
                            {
                                CCDirector.SharedDirector.Scheduler.ScheduleSelector(
                                    f => image.Action(texture), this, 0, 0, 0, false
                                    );
                            }
                        }
                        catch (Exception ex)
                        {
                            CCLog.Log("Failed to load image");
                            CCLog.Log(ex.ToString());
                        }
                    }
                }
                );
        }

        public void Update(float dt)
        {
        }

        public static CCTextureCache SharedTextureCache
        {
            get 
            {
                if (s_sharedTextureCache == null)
                {
                    s_sharedTextureCache = new CCTextureCache();
                }
                return (s_sharedTextureCache);
            }
        }

        public static void PurgeSharedTextureCache()
        {
            if (s_sharedTextureCache != null)
            {
                s_sharedTextureCache.Dispose();
                s_sharedTextureCache = null;
            }
        }

        public void UnloadContent()
        {
            m_pTextures.Clear();
        }

        public bool Contains(string assetFile)
        {
            return m_pTextures.ContainsKey(assetFile);
        }

        public void AddImageAsync(string fileimage, Action<CCTexture2D> action)
        {
            Debug.Assert(!String.IsNullOrEmpty(fileimage), "TextureCache: fileimage MUST not be NULL");

            lock (_asyncLoadedImages)
            {
                _asyncLoadedImages.Add(new AsyncStruct() {FileName = fileimage, Action = action});
            }

            if (_task == null)
            {
                _task = CCTask.RunAsync(_processingAction);
            }
        }

        public CCTexture2D AddImage(string fileimage)
        {
            Debug.Assert(!String.IsNullOrEmpty(fileimage), "TextureCache: fileimage MUST not be NULL");

            lock (m_pDictLock)
            {
                CCTexture2D texture;

                var assetName = fileimage;
                if (Path.HasExtension(assetName))
                {
                    assetName = CCFileUtils.RemoveExtension(assetName);
                }

                if (!m_pTextures.TryGetValue(assetName, out texture))
                {
                    texture = new CCTexture2D();

                    if (texture.InitWithFile(fileimage))
                    {
                        m_pTextures.Add(assetName, texture);
                    }
                    else
                    {
                        return null;
                    }
                }
                
                return texture;
            }
        }

        public CCTexture2D AddImage(byte[] data, string assetName, SurfaceFormat format)
        {
            lock (m_pDictLock)
            {
                CCTexture2D texture;

                if (!m_pTextures.TryGetValue(assetName, out texture))
                {
                    texture = new CCTexture2D();
                    
                    if (texture.InitWithData(data, format))
                    {
                        m_pTextures.Add(assetName, texture);
                    }
                    else
                    {
                        return null;
                    }<commit_msg>fixed lock around file i/o operation that did not need to be locked. this removes a potential deadlock on android where i/o is considerably slower to physical storage.<commit_after>using System;
using System.Collections.Generic;
using System.Linq;
using System.Diagnostics;
using System.IO;
using Microsoft.Xna.Framework.Graphics;

namespace Cocos2D
{
    public class CCTextureCache : IDisposable, ICCSelectorProtocol
    {
        struct AsyncStruct
        {
            public string  FileName;
            public Action<CCTexture2D> Action;
        };

        private List<AsyncStruct> _asyncLoadedImages = new List<AsyncStruct>();
        private Action _processingAction;
        private object _task;

        private static CCTextureCache s_sharedTextureCache;

        private readonly object m_pDictLock = new object();
        protected Dictionary<string, CCTexture2D> m_pTextures = new Dictionary<string, CCTexture2D>();

        ~CCTextureCache() 
        {
            Dispose();
        }

        private CCTextureCache()
        {
            _processingAction = new Action(
                () =>
                {
                    while (true)
                    {
                        AsyncStruct image;

                        lock (_asyncLoadedImages)
                        {
                            if (_asyncLoadedImages.Count == 0)
                            {
                                _task = null;
                                return;
                            }
                            image = _asyncLoadedImages[0];
                            _asyncLoadedImages.RemoveAt(0);
                        }

                        try
                        {
                            var texture = AddImage(image.FileName);
						CCLog.Log("Loaded texture: {0}", image.FileName);
                            if (image.Action != null)
                            {
                                CCDirector.SharedDirector.Scheduler.ScheduleSelector(
                                    f => image.Action(texture), this, 0, 0, 0, false
                                    );
                            }
                        }
                        catch (Exception ex)
                        {
						    CCLog.Log("Failed to load image {0}", image.FileName);
                            CCLog.Log(ex.ToString());
                        }
                    }
                }
                );
        }

        public void Update(float dt)
        {
        }

        public static CCTextureCache SharedTextureCache
        {
            get 
            {
                if (s_sharedTextureCache == null)
                {
                    s_sharedTextureCache = new CCTextureCache();
                }
                return (s_sharedTextureCache);
            }
        }

        public static void PurgeSharedTextureCache()
        {
            if (s_sharedTextureCache != null)
            {
                s_sharedTextureCache.Dispose();
                s_sharedTextureCache = null;
            }
        }

        public void UnloadContent()
        {
            m_pTextures.Clear();
        }

        public bool Contains(string assetFile)
        {
            return m_pTextures.ContainsKey(assetFile);
        }

        public void AddImageAsync(string fileimage, Action<CCTexture2D> action)
        {
            Debug.Assert(!String.IsNullOrEmpty(fileimage), "TextureCache: fileimage MUST not be NULL");

            lock (_asyncLoadedImages)
            {
                _asyncLoadedImages.Add(new AsyncStruct() {FileName = fileimage, Action = action});
            }

            if (_task == null)
            {
                _task = CCTask.RunAsync(_processingAction);
            }
        }

        public CCTexture2D AddImage(string fileimage)
		{
			Debug.Assert (!String.IsNullOrEmpty (fileimage), "TextureCache: fileimage MUST not be NULL");

			CCTexture2D texture = null;

			var assetName = fileimage;
			if (Path.HasExtension (assetName)) {
				assetName = CCFileUtils.RemoveExtension (assetName);
			}

			lock (m_pDictLock) {
				m_pTextures.TryGetValue (assetName, out texture);
			}
			if (texture == null) {
				texture = new CCTexture2D ();

				if (texture.InitWithFile (fileimage)) {
					lock (m_pDictLock) {
						m_pTextures[assetName] = texture;
					}
				} else {
					return null;
				}
			}
                
			return texture;
		}

        public CCTexture2D AddImage(byte[] data, string assetName, SurfaceFormat format)
        {
            lock (m_pDictLock)
            {
                CCTexture2D texture;

                if (!m_pTextures.TryGetValue(assetName, out texture))
                {
                    texture = new CCTexture2D();
                    
                    if (texture.InitWithData(data, format))
                    {
                        m_pTextures.Add(assetName, texture);
                    }
                    else
                    {
                        return null;
                    }
{'fraction_non_alphanumeric': 0.0708838482596793, 'fraction_numerical': 0.0035197497066875244, 'mean_word_length': 1.0794877007521855, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5880431', 'n_tokens_mistral': 2586, 'n_tokens_neox': 2303, 'n_words': 500}