All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jclarion.clarion.primative.ActiveThreadMap Maven / Gradle / Ivy

package org.jclarion.clarion.primative;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.TimerTask;

import org.jclarion.clarion.runtime.ClarionTaskManager;

public class ActiveThreadMap 
{
    private static final int SIZE=8;
    private static final int AND=7;
    
    private static class Entry
    {
        //private long   lastAccessed;

        private Entry(Thread key,V value)
        {
            this._key=key;
            this._value=value;
        }

        private Thread _key;
        private V _value;
        
        public boolean isAlive()
        {
            return _key.isAlive();
        }
        
        public V getValue()
        {
            return _value;
        }
        
        public Thread getKey()
        {
            return _key;
        }
        
        public void setValue(V value)
        {
            this._value=value;
        }
        
        public void setValue(Thread key,V value)
        {
            this._value=value;
            this._key=key;
        }
    }
    
    private Entry[][] hash;
    
    @SuppressWarnings("unchecked")
	public ActiveThreadMap()
    {
        hash=new Entry[SIZE][];
    }
    
    @SuppressWarnings("unchecked")
	public void put(Thread thread,V value)
    {
        List cleanup=null;
        
        synchronized(this) {

            int indx = ((int) thread.getId()) & AND;
            Entry[] bucket = hash[indx];
            if (bucket == null) {
                bucket = new Entry[1];
                hash[indx] = bucket;
                bucket[0] = new Entry(thread, value);
                return;
            }

            int slot = -1;
            boolean empty = true;
            for (int scan = 0; scan < bucket.length; scan++) {

                Entry e = bucket[scan];

                if (e != null && e.getKey() == thread) {
                    e.setValue(value);
                    return;
                }

                if (e == null || !e.isAlive()) {
                    slot = scan;
                    continue;
                }

                empty = false;
            }

            if (empty && slot > 0) {

                for (Entry e : bucket) {
                    cleanup = addToCleanup(cleanup, e);
                }

                bucket = new Entry[1];
                hash[indx] = bucket;
                slot = 0;
            }

            if (slot == -1) {
                Entry[] newBucket = new Entry[bucket.length << 1];
                System.arraycopy(bucket, 0, newBucket, 0, bucket.length);
                slot = bucket.length;
                bucket = newBucket;
                hash[indx] = bucket;
            }

            Entry e = bucket[slot];
            if (e != null) {
                if (e.getKey() != thread) {
                    cleanup = addToCleanup(cleanup, e);
                }
                e.setValue(thread,value);
            } else {
                bucket[slot] = new Entry(thread, value);
            }
        }
        cleanup(cleanup);
    }
    
    @SuppressWarnings("unchecked")
    public synchronized V get(Thread thread)
    {
        int indx = ((int)thread.getId())&AND;
        Entry[] bucket = hash[indx];
        if (bucket==null) return null;
        for (int scan=0;scan[] scan : hash ) {
            if (scan!=null) {
                count+=scan.length;
            }
        }
        return count;
    }

    @SuppressWarnings("unchecked")
    public void clear() 
    {
        Entry[][] old;
        synchronized(this) {
            old=hash;
            hash=new Entry[SIZE][];
        }
        
        for (Entry ea[] : old ) 
        {
            if (ea==null) continue;
            for (Entry e : ea ) {
                if (e!=null) {
                    cleanup(e.getValue());
                }
            }
        }
    }
    
    private static class ScheduledPack extends TimerTask
    {
        final WeakReference> wr_atm;
        
        public ScheduledPack(ActiveThreadMap base)
        {
            wr_atm = new WeakReference>(base);
        }
        
        public void run()
        {
            ActiveThreadMap atm = wr_atm.get();
            if (atm==null) {
                cancel();
            } else {
                atm.pack();
            }
        }
    }
        
    public void schedulePack(int delay)
    {
        ClarionTaskManager.getInstance().getTimer().schedule(
            new ScheduledPack(this),
            new java.util.Date(),delay);
    }
    
    @SuppressWarnings("unchecked")
    public void pack()
    {
        List cleanup=new ArrayList();
        synchronized(this) {
            for (int s1 =0;s1 e = ea[s2];
                    if (e==null) continue;
                    if (e.isAlive()) {
                        empty=false;
                        continue;
                    }
                    cleanup.add(e.getValue());
                    ea[s2]=null;
                }
                if (empty) {
                    hash[s1]=null;
                }
            }
        }
        
        cleanup(cleanup);
    }
    
    public void cleanup(V object)
    {
        if (object==null) return;
        if (object instanceof Cleanup) {
            ((Cleanup) object).cleanup();
        }
    }

    private void cleanup(List l)
    {
        if (l==null) return;
        for (V val : l ) {
            cleanup(val);
        }
    }
    
    @SuppressWarnings("unchecked")
    private List addToCleanup(List l,Entry e)
    {
        if (e==null) return l;
        if (e.isAlive()) return l;
        if (l==null) l =new ArrayList();
        l.add((V)e.getValue());
        return l;
    }

	public Iterable keys() {
		return new KeyIterable(this);
	}

	public Iterable values() {
		return new ValueIterable(this);
	}

	private static class KeyIterable implements Iterable
	{
		private ActiveThreadMap map;

		public KeyIterable(ActiveThreadMap map) {
			this.map=map;
		}

		@Override
		public Iterator iterator() {
			return new KeyIterator(map);
		}		
	}
	
	private static class KeyIterator extends EntryIterator
	{
		public KeyIterator(ActiveThreadMap map) {
			super(map);
		}

		@Override
		protected Thread getNext(Entry next) {
			return next.getKey();
		}
	}

	private static class ValueIterable implements Iterable
	{
		private ActiveThreadMap map;

		public ValueIterable(ActiveThreadMap map) {
			this.map=map;
		}

		@Override
		public Iterator iterator() {
			return new ValueIterator(map);
		}		
	}
	
	private static class ValueIterator extends EntryIterator
	{
		public ValueIterator(ActiveThreadMap map) {
			super(map);
		}

		@Override
		protected V getNext(Entry next) {
			return next.getValue();
		}
	}
	
	
	private static abstract class EntryIterator implements Iterator
	{
		private int 		bucketPos=0;
		private int 		hashPos=0;
		private Entry	next=null;
		private Entry	remove=null;
		private ActiveThreadMap map;
		
		public EntryIterator(ActiveThreadMap map)
		{
			this.map=map;
		}

		@Override
		public boolean hasNext() {
			synchronized(this) {
				while (next==null) {
					if (hashPos>=map.hash.length) return false;
					if (map.hash[hashPos]==null) {
						hashPos++;
						continue;
					}
					if (bucketPos>=map.hash[hashPos].length) {
						hashPos++;
						bucketPos=0;
						continue;
					}
					next=map.hash[hashPos][bucketPos++];
					if (next!=null && !next.isAlive()) { next=null; }
				}
				return true;
			}
		}

		@Override
		public final K next() {
			if (!hasNext()) throw new RuntimeException("Exhausted");
			remove=next;
			next=null;
			return getNext(remove);
		}
		
		protected abstract K getNext(Entry next);

		@Override
		public void remove() {
			map.remove(remove.getKey());
		}
	}
	
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy