⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 weakhashtable.cs

📁 Perst开源实时数据库
💻 CS
字号:
namespace Perst.Impl
{
    using System;
    using Perst;
	
    public class WeakHashTable : OidHashTable
    {
        internal Entry[] table;
        internal const float loadFactor = 0.75f;
        internal int count;
        internal int threshold;
        internal bool flushing;
		
        public WeakHashTable(int initialCapacity)
        {
            threshold = (int) (initialCapacity * loadFactor);
            table = new Entry[initialCapacity];
        }
		
        public bool remove(int oid)
        {
            lock(this)
            {
                Entry[] tab = table;
                int index = (oid & 0x7FFFFFFF) % tab.Length;
                for (Entry e = tab[index], prev = null; e != null; prev = e, e = e.next)
                {
                    if (e.oid == oid)
                    {
                        if (prev != null)
                        {
                            prev.next = e.next;
                        }
                        else
                        {
                            tab[index] = e.next;
                        }
                        e.clear();
                        count -= 1;
                        return true;
                    }
                }
                return false;
            }
        }
		
        public void  put(int oid, IPersistent obj)
        {
            lock(this)
            {
                Entry[] tab = table;
                int index = (oid & 0x7FFFFFFF) % tab.Length;
                for (Entry e = tab[index]; e != null; e = e.next)
                {
                    if (e.oid == oid)
                    {
                        e.oref.Target = obj;
                        return ;
                    }
                }
                if (count >= threshold && !flushing)
                {
                    // Rehash the table if the threshold is exceeded
                    rehash();
                    tab = table;
                    index = (oid & 0x7FFFFFFF) % tab.Length;
                }
				
                // Creates the new entry.
                tab[index] = new Entry(oid, new WeakReference(obj), tab[index]);
                count++;
            }
        }
		
        public IPersistent get(int oid)
        {
            while (true) 
            { 
                lock(this)
                {
                    Entry[] tab = table;
                    int index = (oid & 0x7FFFFFFF) % tab.Length;
                    for (Entry e = tab[index], prev = null; e != null; prev = e, e = e.next)
                    {
                        if (e.oid == oid)
                        {
                            IPersistent obj = (IPersistent)e.oref.Target;
                            if (obj == null) 
                            {
                                if (e.dirty > 0) 
                                {
                                    goto waitFinalization;
                                }
                            } 
                            else if (obj.IsDeleted()) 
                            {
                                if (prev != null)
                                {
                                    prev.next = e.next;
                                }
                                else
                                {
                                    tab[index] = e.next;
                                }
                                e.clear();
                                count -= 1;
                                return null;
                            }
                            return obj;
                        }
                    }
                    return null;
                }
            waitFinalization:
                GC.WaitForPendingFinalizers();
            }
        }
		

        internal void  rehash()
        {
            int oldCapacity = table.Length;
            Entry[] oldMap = table;
            int i;
            for (i = oldCapacity; --i >= 0; )
            {
                Entry e, next, prev;
                for (prev = null, e = oldMap[i]; e != null; e = next) 
                { 
                    next = e.next;
                    IPersistent obj = (IPersistent)e.oref.Target;
                    if ((obj == null || obj.IsDeleted()) && e.dirty == 0)
                    {
                        count -= 1;
                        e.clear();
                        if (prev == null)
                        {
                            oldMap[i] = next;
                        }
                        else
                        {
                            prev.next = next;
                        }
                    }
                    else
                    {
                        prev = e;
                    }
                }
            }
			
            if ((uint)count <= ((uint)threshold >> 1))
            {
                return ;
            }
            int newCapacity = oldCapacity * 2 + 1;
            Entry[] newMap = new Entry[newCapacity];
			
            threshold = (int) (newCapacity * loadFactor);
            table = newMap;
			
            for (i = oldCapacity; --i >= 0; )
            {
                for (Entry old = oldMap[i]; old != null; )
                {
                    Entry e = old;
                    old = old.next;
					
                    int index = (e.oid & 0x7FFFFFFF) % newCapacity;
                    e.next = newMap[index];
                    newMap[index] = e;
                }
            }
        }
		
        public void flush() 
        {
            while (true) 
            {
                lock (this) 
                { 
                    flushing = true;
                    for (int i = 0; i < table.Length; i++) 
                    { 
                        for (Entry e = table[i]; e != null; e = e.next) 
                        { 
                            IPersistent obj = (IPersistent)e.oref.Target;
                            if (obj != null) 
                            { 
                                if (obj.IsModified()) 
                                { 
                                    obj.Store();
                                }
                            } 
                            else if (e.dirty != 0) 
                            { 
                                goto waitFinalization;
                            }
                        }
                    }
                    flushing = false;
                    if (count >= threshold) 
                    {
                        // Rehash the table if the threshold is exceeded
                        rehash();
                    }
                    return;
                }
            waitFinalization:
                GC.WaitForPendingFinalizers();
            }
        }

        public void clear() 
        {
            lock(this) 
            {
                Entry[] tab = table;
                for (int i = 0; i < tab.Length; i++)
                { 
                    tab[i] = null;
                }
                count = 0;
            }
        }

        public void invalidate() 
        {
            while (true) 
            {
                lock (this) 
                { 
                    for (int i = 0; i < table.Length; i++) 
                    { 
                        for (Entry e = table[i]; e != null; e = e.next) 
                        { 
                            IPersistent obj = (IPersistent)e.oref.Target;
                            if (obj != null) 
                            { 
                                if (obj.IsModified()) 
                                { 
                                    e.dirty = 0;
                                    obj.Invalidate();
                                }
                            } 
                            else if (e.dirty != 0) 
                            { 
                                goto waitFinalization;
                            }
                        }
                        table[i] = null;
                    }
                    count = 0;
                    return;
                }
            waitFinalization:
                GC.WaitForPendingFinalizers();
            }
        }

        public void setDirty(IPersistent obj) 
        {
            lock (this) 
            { 
                int oid = obj.Oid;
                Entry[] tab = table;
                int index = (oid & 0x7FFFFFFF) % tab.Length;
                for (Entry e = tab[index] ; e != null ; e = e.next) 
                {
                    if (e.oid == oid) 
                    {
                        e.dirty += 1;
                        return;
                    }
                }
            }
        }

        public void clearDirty(IPersistent obj) 
        {
            lock (this) 
            { 
                int oid = obj.Oid;
                Entry[] tab = table;
                int index = (oid & 0x7FFFFFFF) % tab.Length;
                for (Entry e = tab[index], prev = null; e != null; prev = e, e = e.next)
                {
                    if (e.oid == oid) 
                    {
                        if (e.oref.IsAlive) 
                        { 
                            if (e.dirty > 0) 
                            { 
                                e.dirty -= 1;
                            }
                        } 
                        else 
                        { 
                             if (prev != null)
                            {
                                prev.next = e.next;
                            }
                            else
                            {
                                tab[index] = e.next;
                            }
                            e.clear();
                            count -= 1;
                        }
                        return;
                    }
                }
            }
        }

        public int size()
        {
            return count;
        }

	
        internal class Entry
        {
            internal Entry next;
            internal WeakReference oref;
            internal int oid;
            internal int dirty;
		
            internal void clear() 
            { 
                oref.Target = null;
                oref = null;
                dirty = 0;
                next = null;
            }

            internal Entry(int oid, WeakReference oref, Entry chain)
            {
                next = chain;
                this.oid = oid;
                this.oref = oref;
            }
        }
    }
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -