#108 [WIP] Created new ThreadPool class with a static ScheduledThreadExecutor that is now shared by all components. Removed ThreadPoolManager from all classes. Consolidating into 1 pool seems to have reduced CPU usage by ~15-20%. Overall memory usage is also reduced.

This commit is contained in:
Denny
2017-01-22 09:33:47 -05:00
parent 523ac0314e
commit 6e94d9ce51
39 changed files with 8822 additions and 9118 deletions

View File

@@ -1,32 +1,33 @@
/*******************************************************************************
* SDR Trunk
* Copyright (C) 2014-2016 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
* sdrtrunk
* Copyright (C) 2014-2017 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
package alias.action;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.bind.annotation.XmlTransient;
import message.Message;
import alias.Alias;
import alias.action.beep.BeepAction;
import alias.action.clip.ClipAction;
import alias.action.script.ScriptAction;
import controller.ThreadPoolManager;
import message.Message;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.bind.annotation.XmlTransient;
import java.util.concurrent.ScheduledExecutorService;
/**
* Alias action defines an action to execute when an alias is detected active.
@@ -48,9 +49,7 @@ public abstract class AliasAction
* action attached. The alias argument is the parent alias containing the
* alias action.
*/
public abstract void execute( ThreadPoolManager threadPoolManager,
Alias alias,
Message message );
public abstract void execute( ScheduledExecutorService scheduledExecutorService, Alias alias, Message message );
/**
* Dismiss a persistent alias action

View File

@@ -1,54 +1,69 @@
/*******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2017 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
package alias.action;
import java.util.List;
import alias.Alias;
import message.Message;
import sample.Listener;
import alias.Alias;
import controller.ThreadPoolManager;
import util.ThreadPool;
import java.util.List;
/**
* Manages all alias action events. Each received message is interrogated for
* any alias entries and then each alias is interrogated for any alias actions.
*
* Each alias action is executed and provided a copy of the source message so
*
* Each alias action is executed and provided a copy of the source message so
* that the contents of the message can be used as part of the action.
*/
public class AliasActionManager implements Listener<Message>
{
private ThreadPoolManager mThreadPoolManager;
public AliasActionManager( ThreadPoolManager threadPoolManager )
{
mThreadPoolManager = threadPoolManager;
}
@Override
public void receive( Message message )
{
if( message.isValid() )
{
List<Alias> aliases = message.getAliases();
if( aliases != null )
{
for( Alias alias: aliases )
{
if( alias.hasActions() )
{
List<AliasAction> actions = alias.getAction();
for( AliasAction action: actions )
{
/* Provide access to the thread pool manager in case the
public AliasActionManager()
{
}
@Override
public void receive(Message message)
{
if(message.isValid())
{
List<Alias> aliases = message.getAliases();
if(aliases != null)
{
for(Alias alias : aliases)
{
if(alias.hasActions())
{
List<AliasAction> actions = alias.getAction();
for(AliasAction action : actions)
{
/* Provide access to the thread pool manager in case the
* action needs to setup a timer, and provide the original
* message to be used as part of the action (e.g. sending
* the message as a text message to a cell phone */
action.execute( mThreadPoolManager, alias, message );
}
}
}
}
}
}
action.execute(ThreadPool.SCHEDULED, alias, message);
}
}
}
}
}
}
}

View File

@@ -1,188 +1,181 @@
package alias.action;
import java.awt.EventQueue;
import alias.Alias;
import message.Message;
import javax.swing.*;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlTransient;
import java.awt.*;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.swing.JOptionPane;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlTransient;
import message.Message;
import alias.Alias;
import controller.ThreadPoolManager;
import controller.ThreadPoolManager.ThreadType;
public abstract class RecurringAction extends AliasAction
{
@XmlTransient
protected AtomicBoolean mRunning = new AtomicBoolean( false );
@XmlTransient
private ScheduledFuture<?> mPerpetualAction;
protected Interval mInterval = Interval.ONCE;
protected int mPeriod = 5;
protected ThreadPoolManager mThreadPoolManager;
public abstract void performAction( Alias alias, Message message );
@XmlTransient
protected AtomicBoolean mRunning = new AtomicBoolean(false);
@XmlTransient
private ScheduledFuture<?> mPerpetualAction;
@XmlTransient
protected ScheduledExecutorService mScheduledExecutorService;
@Override
public void execute( ThreadPoolManager threadPoolManager,
Alias alias,
Message message )
{
mThreadPoolManager = threadPoolManager;
protected Interval mInterval = Interval.ONCE;
protected int mPeriod = 5;
if( mRunning.compareAndSet( false, true ) )
{
switch( mInterval )
{
case ONCE:
performThreadedAction( alias, message );
/* Don't reset */
break;
case DELAYED_RESET:
performThreadedAction( alias, message );
mThreadPoolManager.scheduleOnce( new ResetTask(),
mPeriod, TimeUnit.SECONDS );
break;
case UNTIL_DISMISSED:
mPerpetualAction = mThreadPoolManager
.scheduleFixedRate( ThreadType.DECODER,
new PerformActionTask( alias, message ),
mPeriod, TimeUnit.SECONDS );
public abstract void performAction(Alias alias, Message message);
StringBuilder sb = new StringBuilder();
sb.append( "<html><div width='250'>Alias [" );
sb.append( alias.getName() );
sb.append( "] is active in message [" );
sb.append( message.toString() );
sb.append( "]</div></html>" );
final String text = sb.toString();
EventQueue.invokeLater( new Runnable()
{
@Override
public void run()
{
JOptionPane.showMessageDialog( null, text,
"Alias Alert", JOptionPane.INFORMATION_MESSAGE );
dismiss( false );
mThreadPoolManager.scheduleOnce( new ResetTask(),
15, TimeUnit.SECONDS );
}
} );
break;
default:
}
}
}
@Override
public void execute(ScheduledExecutorService scheduledExecutorService, Alias alias, Message message)
{
mScheduledExecutorService = scheduledExecutorService;
/**
* Spawns the performAction() event into a new thread so that it doesn't
* delay any decoder actions.
*/
private void performThreadedAction( final Alias alias, final Message message )
{
mThreadPoolManager.scheduleOnce( new Runnable() {
if(mRunning.compareAndSet(false, true))
{
switch(mInterval)
{
case ONCE:
performThreadedAction(alias, message);
/* Don't reset */
break;
case DELAYED_RESET:
performThreadedAction(alias, message);
mScheduledExecutorService.schedule(new ResetTask(), mPeriod, TimeUnit.SECONDS);
break;
case UNTIL_DISMISSED:
mPerpetualAction = mScheduledExecutorService.scheduleAtFixedRate(
new PerformActionTask(alias, message), mPeriod, mPeriod, TimeUnit.SECONDS);
@Override
public void run()
{
performAction( alias, message );
}}, 0, TimeUnit.SECONDS );
}
@Override
public void dismiss( boolean reset )
{
if( mPerpetualAction != null )
{
mPerpetualAction.cancel( true );
mPerpetualAction = null;
}
if( reset )
{
mRunning.set( false );
}
}
@XmlAttribute
public int getPeriod()
{
return mPeriod;
}
public void setPeriod( int period )
{
mPeriod = period;
}
@XmlAttribute
public Interval getInterval()
{
return mInterval;
}
public void setInterval( Interval interval )
{
mInterval = interval;
mRunning.set( false );
}
public enum Interval
{
ONCE( "Once" ),
DELAYED_RESET( "Once, Reset After Delay" ),
UNTIL_DISMISSED( "Until Dismissed" );
private String mLabel;
private Interval( String label )
{
mLabel = label;
}
public String toString()
{
return mLabel;
}
}
public class PerformActionTask implements Runnable
{
private Alias mAlias;
private Message mMessage;
StringBuilder sb = new StringBuilder();
sb.append("<html><div width='250'>Alias [");
sb.append(alias.getName());
sb.append("] is active in message [");
sb.append(message.toString());
sb.append("]</div></html>");
public PerformActionTask( Alias alias, Message message )
{
mAlias = alias;
mMessage = message;
}
@Override
public void run()
{
final String text = sb.toString();
EventQueue.invokeLater(new Runnable()
{
@Override
public void run()
{
JOptionPane.showMessageDialog(null, text,
"Alias Alert", JOptionPane.INFORMATION_MESSAGE);
dismiss(false);
mScheduledExecutorService.schedule(new ResetTask(), 15, TimeUnit.SECONDS);
}
});
break;
default:
}
}
}
/**
* Spawns the performAction() event into a new thread so that it doesn't
* delay any decoder actions.
*/
private void performThreadedAction(final Alias alias, final Message message)
{
mScheduledExecutorService.schedule(new Runnable()
{
@Override
public void run()
{
performAction(alias, message);
}
}, 0, TimeUnit.SECONDS);
}
@Override
public void dismiss(boolean reset)
{
if(mPerpetualAction != null)
{
mPerpetualAction.cancel(true);
mPerpetualAction = null;
}
if(reset)
{
mRunning.set(false);
}
}
@XmlAttribute
public int getPeriod()
{
return mPeriod;
}
public void setPeriod(int period)
{
mPeriod = period;
}
@XmlAttribute
public Interval getInterval()
{
return mInterval;
}
public void setInterval(Interval interval)
{
mInterval = interval;
mRunning.set(false);
}
public enum Interval
{
ONCE("Once"),
DELAYED_RESET("Once, Reset After Delay"),
UNTIL_DISMISSED("Until Dismissed");
private String mLabel;
private Interval(String label)
{
mLabel = label;
}
public String toString()
{
return mLabel;
}
}
public class PerformActionTask implements Runnable
{
private Alias mAlias;
private Message mMessage;
public PerformActionTask(Alias alias, Message message)
{
mAlias = alias;
mMessage = message;
}
@Override
public void run()
{
/* Don't use the performThreadedAction() method, since this is
* already running in a separate thread */
performAction( mAlias, mMessage );
}
}
public class ResetTask implements Runnable
{
@Override
public void run()
{
mRunning.set( false );
}
}
performAction(mAlias, mMessage);
}
}
public class ResetTask implements Runnable
{
@Override
public void run()
{
mRunning.set(false);
}
}
}