| @@ -1,85 +1,92 | |||
| 
             | 
        1 | 1 | using System; | 
| 
             | 
        2 | 2 | using Implab.Parallels; | 
| 
             | 
        3 | 3 | using System.Threading; | 
| 
             | 
        4 | 4 | |
| 
             | 
        5 | 5 | namespace Implab { | 
| 
             | 
        6 | 6 | public class ObjectPool<T> : IDisposable { | 
| 
             | 
        7 | 7 | readonly Func<T> m_factory; | 
| 
             | 
        8 | 8 | readonly Action<T> m_cleanup; | 
| 
             | 
        9 | 9 | readonly int m_size; | 
| 
             | 
        10 | 10 | readonly MTQueue<T> m_queue = new MTQueue<T>(); | 
| 
             | 
        11 | 11 | |
| 
             | 
        12 | 
            
                      | 
    |
| 
             | 
        12 | bool m_disposed; | |
| 
             | 
        13 | 13 | |
| 
             | 
        14 | 
            
                      | 
    |
| 
             | 
        14 | int m_count; | |
| 
             | 
        15 | 15 | |
| 
             | 
        16 | 16 | public ObjectPool(Func<T> factory, Action<T> cleanup, int size) { | 
| 
             | 
        17 | 17 | Safe.ArgumentNotNull(factory, "factory"); | 
| 
             | 
        18 | 18 | Safe.ArgumentInRange(size, 1, size, "size"); | 
| 
             | 
        19 | 19 | |
| 
             | 
        20 | 20 | m_factory = factory; | 
| 
             | 
        21 | 21 | m_cleanup = cleanup; | 
| 
             | 
        22 | 22 | m_size = size; | 
| 
             | 
        23 | 23 | } | 
| 
             | 
        24 | 24 | |
| 
             | 
        25 | 25 | public ObjectPool(Func<T> factory, Action<T> cleanup) : this(factory,cleanup,Environment.ProcessorCount+1) { | 
| 
             | 
        26 | 26 | } | 
| 
             | 
        27 | 27 | |
| 
             | 
        28 | 28 | public ObjectPool(Func<T> factory) : this(factory,null,Environment.ProcessorCount+1) { | 
| 
             | 
        29 | 29 | } | 
| 
             | 
        30 | 30 | |
| 
             | 
        31 | public ObjectPoolWrapper<T> Allocate() { | |
| 
             | 
        31 | public ObjectPoolWrapper<T> AllocateAuto() { | |
| 
             | 
        32 | ||
| 
             | 
        33 | return new ObjectPoolWrapper<T>(Allocate(), this); | |
| 
             | 
        34 | } | |
| 
             | 
        35 | ||
| 
             | 
        36 | public T Allocate() { | |
| 
             | 
        32 | 37 | if (m_disposed) | 
| 
             | 
        33 | 38 | throw new ObjectDisposedException(this.ToString()); | 
| 
             | 
        34 | 39 | |
| 
             | 
        35 | 40 | T instance; | 
| 
             | 
        36 | 41 | if (m_queue.TryDequeue(out instance)) { | 
| 
             | 
        37 | 42 | Interlocked.Decrement(ref m_count); | 
| 
             | 
        38 | return instance; | |
| 
             | 
        39 | 43 | } else { | 
| 
             | 
        40 | 44 | instance = m_factory(); | 
| 
             | 
        41 | 45 | } | 
| 
             | 
        42 | 
            
                         return  | 
    |
| 
             | 
        46 | return instance; | |
| 
             | 
        43 | 47 | } | 
| 
             | 
        44 | 48 | |
| 
             | 
        45 | 49 | public void Release(T instance) { | 
| 
             | 
        50 | Thread.MemoryBarrier(); | |
| 
             | 
        46 | 51 | if (m_count < m_size && !m_disposed) { | 
| 
             | 
        47 | 52 | Interlocked.Increment(ref m_count); | 
| 
             | 
        48 | 53 | |
| 
             | 
        49 | 54 | if (m_cleanup != null) | 
| 
             | 
        50 | 55 | m_cleanup(instance); | 
| 
             | 
        51 | 56 | |
| 
             | 
        52 | 57 | m_queue.Enqueue(instance); | 
| 
             | 
        53 | 58 | |
| 
             | 
        54 | 59 | // пока элемент возвращался в кеш, была начата операция освобождения всего кеша | 
| 
             | 
        55 | 60 | // и возможно уже законцена, в таком случае следует извлечь элемент обратно и | 
| 
             | 
        56 | 61 | // освободить его. Если операция освобождения кеша еще не заврешилась, то будет | 
| 
             | 
        57 | 62 | // изъят и освобожден произвольный элемен, что не повлияет на ход всего процесса. | 
| 
             | 
        58 | if (m_disposed && m_queue.TryDequeue(out instance)) | |
| 
             | 
        59 | 
            
                                  | 
    |
| 
             | 
        63 | if (m_disposed && m_queue.TryDequeue(out instance) && instance is IDisposable) | |
| 
             | 
        64 | ((IDisposable)instance).Dispose() ; | |
| 
             | 
        60 | 65 | |
| 
             | 
        61 | 66 | } else { | 
| 
             | 
        62 | 
            
                              | 
    |
| 
             | 
        67 | if (instance is IDisposable) | |
| 
             | 
        68 | ((IDisposable)instance).Dispose(); | |
| 
             | 
        63 | 69 | } | 
| 
             | 
        64 | 70 | } | 
| 
             | 
        65 | 71 | |
| 
             | 
        66 | 72 | protected virtual void Dispose(bool disposing) { | 
| 
             | 
        67 | 73 | if (disposing) { | 
| 
             | 
        68 | 74 | m_disposed = true; | 
| 
             | 
        69 | 75 | T instance; | 
| 
             | 
        70 | 76 | while (m_queue.TryDequeue(out instance)) | 
| 
             | 
        71 | 
            
                                  | 
    |
| 
             | 
        77 | if (instance is IDisposable) | |
| 
             | 
        78 | ((IDisposable)instance).Dispose(); | |
| 
             | 
        72 | 79 | } | 
| 
             | 
        73 | 80 | } | 
| 
             | 
        74 | 81 | |
| 
             | 
        75 | 82 | #region IDisposable implementation | 
| 
             | 
        76 | 83 | |
| 
             | 
        77 | 84 | public void Dispose() { | 
| 
             | 
        78 | 85 | Dispose(true); | 
| 
             | 
        79 | 86 | GC.SuppressFinalize(this); | 
| 
             | 
        80 | 87 | } | 
| 
             | 
        81 | 88 | |
| 
             | 
        82 | 89 | #endregion | 
| 
             | 
        83 | 90 | } | 
| 
             | 
        84 | 91 | } | 
| 
             | 
        85 | 92 | |
        
        General Comments 0
    
    
  
  
                      You need to be logged in to leave comments.
                      Login now
                    
                