/*********************************************************************/ /* */ /* AgentService Framework */ /* www.agentservice.it */ /* */ /* Copyright (C) 2007 l.i.d.o. - DIST, University of Genoa, Italy */ /* GNU Lesser General Public License */ /* */ /* This library is free software; you can redistribute it and/or */ /* modify it under the terms of the GNU Lesser General Public */ /* License as published by the Free Software Foundation, */ /* version 2.1 of the License. */ /* */ /* This library 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 */ /* Lesser General Public License for more details. */ /* */ /* You should have received a copy of the GNU Lesser General Public */ /* License along with this library; if not, write to the */ /* Free Software Foundation, Inc., 59 Temple Place - Suite 330, */ /* Boston, MA 02111-1307, USA. */ /* */ /*********************************************************************/ using System; using System.Threading; namespace AgentService.Agent.Behaviour { /// /// Class WaitingBehaviour. Defines a behaviour that is waiting for /// an event to continue. It merely represents an integer semaphore /// that when reaches the "go" resumes the thread associated with the /// behaviour /// public class WaitingBehaviour { /// /// waiting behaviour hash code /// private int hashCode; /// /// Gets the waiting behaviour's hash code /// public int BehaviourHashCode { get { return this.hashCode; } } /// /// integer semaphore, do you rememeber Djkstra? /// private int semaphore; /// /// Gets the waiting handle for the behaviour /// public bool IsBusy { get { return (this.semaphore > 0); } } /// /// Constructs a WaitingBehaviour object associated to the given thread with the /// given initial value of the semaphore /// /// hashcode of the behaviour that is waiting /// integer value representing the initial value of the semaphore public WaitingBehaviour(int hashCode, int semaphore) { // TODO: check consistent values of parameters? // thread null? // sempahore > 0? this.hashCode = hashCode; this.semaphore = semaphore; } /// /// Signal primitive, decrements the value of the semaphore if not zero /// public void Signal() { // the integer semaphore is idempotent, if // the value has reached zero nothing happens // anymore try { Monitor.Enter(this); if (this.semaphore > 0) { this.semaphore--; // ok if zero... go! if (this.semaphore == 0) { // this.waitingThread.Resume(); Monitor.PulseAll(this); } } } finally { Monitor.Exit(this); } } /// /// Wait primitive, increments the value of the semaphore if not zero /// public void Wait() { try { Monitor.Enter(this); if (this.semaphore > 0) { this.semaphore++; } } finally { Monitor.Exit(this); } } /// /// Executes a multiple wait, if the semaphore is equal to 0 /// it does nothing /// /// numer of wait ot execute public void MultipleWait(int timesToWait) { try { Monitor.Enter(this); if ((this.semaphore > 0) && (timesToWait > 0)) { this.semaphore += timesToWait; } } finally { Monitor.Exit(this); } } } }