package com.planet_ink.coffee_mud.core.threads; import com.planet_ink.coffee_mud.core.interfaces.*; import com.planet_ink.coffee_mud.core.*; import com.planet_ink.coffee_mud.core.collections.*; import com.planet_ink.coffee_mud.Abilities.interfaces.*; import com.planet_ink.coffee_mud.Areas.interfaces.*; import com.planet_ink.coffee_mud.Behaviors.interfaces.*; import com.planet_ink.coffee_mud.CharClasses.interfaces.*; import com.planet_ink.coffee_mud.Commands.interfaces.*; import com.planet_ink.coffee_mud.Common.interfaces.*; import com.planet_ink.coffee_mud.Exits.interfaces.*; import com.planet_ink.coffee_mud.Items.interfaces.*; import com.planet_ink.coffee_mud.Locales.interfaces.*; import com.planet_ink.coffee_mud.MOBS.interfaces.*; import com.planet_ink.coffee_mud.Races.interfaces.*; import com.planet_ink.coffee_mud.Libraries.interfaces.*; import java.sql.*; import java.net.*; import java.util.*; /* Copyright 2013-2016 Bo Zimmerman Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ public class StdTickGroup implements TickableGroup, Cloneable { private final ThreadEngine myEngine; private final long tickTime; private final int tickObjectCounter; private final String name; private final String threadGroupName; private final boolean solitaryTicker; private volatile long nextTickTime; private volatile long lastStart=0; private volatile long lastStop=0; private volatile long milliTotal=0; private volatile int tickTotal=0; private volatile TickClient lastClient=null; private volatile Thread currentThread = null; private static volatile int tickObjReference=0; private final STreeSet<TickClient> tickers=new STreeSet<TickClient>(); public StdTickGroup(long sleep, String threadGroupName, boolean isSolitary) { name = "Tick."+(tickObjReference+1); tickObjectCounter=tickObjReference++; tickTime=sleep; nextTickTime=System.currentTimeMillis() + tickTime; myEngine=null; solitaryTicker=isSolitary; this.threadGroupName=threadGroupName; } public StdTickGroup(String a_name, long sleep, String threadGroupName, boolean isSolitary) { name = "Tick."+ a_name + "." +(tickObjReference+1); tickObjectCounter=tickObjReference++; tickTime=sleep; nextTickTime=System.currentTimeMillis() + tickTime; myEngine=null; solitaryTicker=isSolitary; this.threadGroupName=threadGroupName; } public StdTickGroup(ThreadEngine theEngine, long sleep, String threadGroupName, boolean isSolitary) { name = "Tick."+(tickObjReference+1); tickObjectCounter=tickObjReference++; myEngine=theEngine; tickTime=sleep; nextTickTime=System.currentTimeMillis() + tickTime; solitaryTicker=isSolitary; this.threadGroupName=threadGroupName; } public StdTickGroup copyOf() { try { final StdTickGroup T=(StdTickGroup)this.clone(); T.tickers.clear(); T.tickers.addAll(tickers); return T; } catch(final Exception e){} return this; } @Override public long getStartTime() { return lastStart; } @Override public int getGroupID() { return threadGroupName.charAt(0); } @Override public TickClient fetchTickerByIndex(int i) { int x=0; for(final TickClient C : tickers) if(i==(x++)) return C; return null; } @Override public Thread getCurrentThread() { return currentThread; } @Override public String getThreadGroupName() { return threadGroupName; } @Override public long getLastStartTime() { return lastStart;} @Override public long getLastStopTime() { return lastStop; } @Override public long getMilliTotal() { return milliTotal; } @Override public long getTickTotal() { return tickTotal; } @Override public boolean isSolitaryTicker() { return solitaryTicker; } @Override public boolean isAwake() { return currentThread != null; } @Override public Iterator<TickClient> tickers(){return tickers.iterator();} @Override public int numTickers(){return tickers.size();} @Override public Iterator<TickClient> getTickSet(final Tickable T, final int tickID) { final LinkedList<TickClient> subSet = new LinkedList<TickClient>(); if(tickID < 0) subSet.addAll(tickers.subSet(new StdTickClient(T,0,0), true, new StdTickClient(T,0,Integer.MAX_VALUE), true)); else subSet.addAll(tickers.subSet(new StdTickClient(T,0,tickID), true, new StdTickClient(T,0,tickID), true)); return subSet.iterator(); } @Override public Iterator<TickClient> getLocalItems(int itemTypes, Room R) { LinkedList<TickClient> localItems=null; for (TickClient C : tickers) { switch(itemTypes) { case 0: if(C.getClientObject() instanceof MOB) { if(((MOB)C.getClientObject()).getStartRoom()==R) { if(localItems==null) localItems=new LinkedList<TickClient>(); localItems.add(C); } } else if((C.getClientObject() instanceof ItemTicker) &&((((ItemTicker)C.getClientObject()).properLocation()==R))) { if(localItems==null) localItems=new LinkedList<TickClient>(); localItems.add(C); } break; case 1: if((C.getClientObject() instanceof ItemTicker) &&((((ItemTicker)C.getClientObject()).properLocation()==R))) { if(localItems==null) localItems=new LinkedList<TickClient>(); localItems.add(C); } break; case 2: if((C.getClientObject() instanceof MOB) &&(((MOB)C.getClientObject()).getStartRoom()==R)) { if(localItems==null) localItems=new LinkedList<TickClient>(); localItems.add(C); } break; } } if(localItems == null) return null; return localItems.iterator(); } @Override public String getName() { return name; } @Override public long getTickInterval() { return tickTime; } @Override public long getNextTickTime() { return nextTickTime; } @Override public boolean contains(final Tickable T, final int tickID) { if(tickID >= 0) return tickers.contains(new StdTickClient(T,0,tickID)); return tickers.subSet(new StdTickClient(T,0,-1), true, new StdTickClient(T,0,Integer.MAX_VALUE), true).size()>0; } public int getCounter(){return tickObjectCounter;} @Override public void delTicker(TickClient C) { tickers.remove(C); } @Override public void addTicker(TickClient C) { if(!tickers.contains(C)) tickers.add(C); } @Override public TickClient getLastTicked() { return lastClient; } @Override public String getStatus() { final TickClient lastTicked = getLastTicked(); if(!isAwake()) return "Sleeping"; if((lastTicked==null)||(lastTicked.getClientObject()==null)) return "Shutdown"; final Tickable ticker = lastTicked.getClientObject(); return ticker.ID()+": "+ticker.name()+": "+((myEngine!=null)?myEngine.getTickStatusSummary(ticker):"null"); } @Override public void shutdown() { tickers.clear(); if(CMLib.threads() instanceof ServiceEngine) ((ServiceEngine)CMLib.threads()).delTickGroup(this); } @Override public void run() { nextTickTime=System.currentTimeMillis() + tickTime; //final String oldThreadName=Thread.currentThread().getName(); try { currentThread=Thread.currentThread(); lastStart=System.currentTimeMillis(); lastClient=null; final boolean allSuspended=CMLib.threads().isAllSuspended(); if((CMProps.getBoolVar(CMProps.Bool.MUDSTARTED)) &&(!allSuspended)) { for(final Iterator<TickClient> i=tickers();i.hasNext();) { final TickClient client=i.next(); lastClient=client; //if(client.getCurrentTickDown()<=1) currentThread.setName(oldThreadName+":"+getName()+":"+client.getName()); if(client.tickTicker(false)) { delTicker(client); // cant do i.remove, its an streeset } } } } finally { lastStop=System.currentTimeMillis(); milliTotal+=(lastStop-lastStart); tickTotal++; currentThread=null; //Thread.currentThread().setName(oldThreadName); } if(tickers.size()==0) { if(CMLib.threads() instanceof ServiceEngine) ((ServiceEngine)CMLib.threads()).delTickGroup(this); } } @Override public long activeTimeMillis() { if(this.isAwake()) return System.currentTimeMillis()-this.lastStart; return 0; } }