/**
* Catroid: An on-device visual programming system for Android devices
* Copyright (C) 2010-2014 The Catrobat Team
* (<http://developer.catrobat.org/credits>)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* An additional term exception under section 7 of the GNU Affero
* General Public License, version 3, is available at
* http://developer.catrobat.org/license_additional_term
*
* 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.catrobat.html5player.client.threading;
import java.util.ArrayList;
import org.catrobat.html5player.client.CatrobatDebug;
public class CatThread {
public final static int READY = 1;
public final static int SLEEPING = 2;
public final static int DESTROY = 3;
private String name;
private Callable task;
private int status;
private ArrayList<WaitCount> waitingSignalers;
private WaitCount resumeSignaler = null;
//##########################################################################
/**
*
* @param name
* @param task
*/
public CatThread(String name, Callable task) {
this.name = name;
this.task = task;
this.status = READY;
CatrobatDebug.debug("new thread with name: " + this.name);
this.task.setExecutorName(this.name);
this.waitingSignalers = new ArrayList<WaitCount>();
}
//##########################################################################
public void run() {
// CatrobatDebug.debug("Thread '" + this.name + "' running...");
//work
task.run();
//still work to do
if(!task.isWorkDone())
return;
//work is done
// thread is supposed to be still sleeping
if(this.status==CatThread.SLEEPING){
return;
}
//but resume signal has not yet arrived
if(resumeSignaler != null)
return;
//if there are waiting threads
if(numberOfWaitingSignalers() != 0)
this.signalFinishedExecution();
this.status = DESTROY;
}
//##########################################################################
/**
* sets the status to READY if the current status is SLEEPING
*/
public void wake() {
if(this.status == SLEEPING)
this.status = READY;
}
/**
* sets the status to SLEEPING
*/
public void sleep() {
this.status = SLEEPING;
}
/**
* sets the status to DESTROY
*/
public void kill() {
this.status = DESTROY;
}
//##########################################################################
public String getName() {
return this.name;
}
public int getStatus() {
return this.status;
}
public Callable getTask() {
return this.task;
}
//##########################################################################
/**
* the thread sets its status to SLEEP and waits until the signaler calls
* the function resumeSignal()
* @param signaler Signaler who wakes the thread up
*/
public void awaitSignal(WaitCount signaler) {
this.resumeSignaler = signaler;
sleep();
resumeSignaler.await();
}
/**
* the thread sets its status to READY and removes the current signaler
*/
public void resumeSignal() {
this.resumeSignaler = null;
wake();
}
/**
* adds an waiting signaler to the threads signalers list and counts the
* counter of the WaitCount up
* @param waitingSignaler
*/
public void signalFinishedExecution(WaitCount waitingSignaler) {
if(!this.waitingSignalers.contains(waitingSignaler)) {
waitingSignaler.countUp();
this.waitingSignalers.add(waitingSignaler);
}
}
/**
* counts for all waiting signalers the counter of the WaitCount down and
* clears the signalers list
*/
private void signalFinishedExecution() {
for(WaitCount signaler : this.waitingSignalers) {
signaler.countDown();
}
this.waitingSignalers.clear();
}
/**
* @return returns the number of the actual waiting signalers
*/
public int numberOfWaitingSignalers() {
return this.waitingSignalers.size();
}
//##########################################################################
}