Main Page | Namespace List | Alphabetical List | Class List | Directories | File List | Class Members | File Members

NeuronTaskHolder.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   SpikeStream Simulation                                                *
00003  *   Copyright (C) 2007 by David Gamez                                     *
00004  *   david@davidgamez.eu                                                   *
00005  *   Version 0.1                                                           *
00006  *                                                                         *
00007  *   This program is free software; you can redistribute it and/or modify  *
00008  *   it under the terms of the GNU General Public License as published by  *
00009  *   the Free Software Foundation; either version 2 of the License, or     *
00010  *   (at your option) any later version.                                   *
00011  *                                                                         *
00012  *   This program is distributed in the hope that it will be useful,       *
00013  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00014  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00015  *   GNU General Public License for more details.                          *
00016  *                                                                         *
00017  *   You should have received a copy of the GNU General Public License     *
00018  *   along with this program; if not, write to the                         *
00019  *   Free Software Foundation, Inc.,                                       *
00020  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
00021  ***************************************************************************/
00022 
00023 //SpikeStream includes
00024 #include "NeuronTaskHolder.h"
00025 #include "Debug.h"
00026 #include "GlobalVariables.h"
00027 #include "PVMMessages.h"
00028 #include "SpikeStreamSimulation.h"
00029 
00030 //Other includes
00031 #include "pvm3.h"
00032 #include <iostream>
00033 using namespace std;
00034 
00035 
00036 /*! Constructor. */
00037 NeuronTaskHolder::NeuronTaskHolder(int myTID, unsigned int maxNumberOfNeurons){
00038         //Store this task id for error messages
00039         thisTaskID = myTID;
00040 
00041         //Allocate memory for the vector to improve performance
00042         firingNeuronVector.reserve(maxNumberOfNeurons);
00043 
00044         //Initialise variables
00045         numberOfTasks = 0;
00046 }
00047 
00048 
00049 /*! Destructor. */
00050 NeuronTaskHolder::~NeuronTaskHolder(){
00051         #ifdef MEMORY_DEBUG
00052                 cout<<"DESTROYING NEURONTASKHOLDER"<<endl;
00053         #endif//MEMORY_DEBUG
00054 
00055         if(numberOfTasks > 0)
00056                 delete [] destinationTaskIDs;
00057 }
00058 
00059 
00060 //----------------------------------------------------------------------------
00061 //--------------------------- PUBLIC METHODS ---------------------------------
00062 //----------------------------------------------------------------------------
00063 
00064 /*! Adds a receiving task to the task array.
00065         Done in this clunky way because the broadcast message function in pvm 
00066         needs an integer array, not a vector, as one of its arguments. */
00067 void NeuronTaskHolder::addReceivingTask(int newTaskID){
00068         // Store a reference to the old array
00069         int *oldArray = destinationTaskIDs;
00070         
00071         //Create a new array to hold taskIDs
00072         destinationTaskIDs = new int[numberOfTasks + 1];
00073         
00074         //Copy old array into new array
00075         for(int i=0; i<numberOfTasks; i++)
00076                 destinationTaskIDs[i] = oldArray[i];
00077                 
00078         //Add new task to array
00079         destinationTaskIDs[numberOfTasks] = newTaskID;
00080         
00081         //Remove the old array and increase the number of tasks.
00082         if(numberOfTasks > 0)
00083                 delete [] oldArray;
00084         ++numberOfTasks;
00085 }
00086 
00087 
00088 /*! Removes a receiving task from the task holder. */
00089 void NeuronTaskHolder::removeReceivingTask(int taskID){
00090         //Check that task ID is in receivingTaskIDs
00091         bool taskIDFound = false;
00092         for(int i=0; i<numberOfTasks; ++i)
00093                 if(destinationTaskIDs[i] == taskID)
00094                         taskIDFound = true;
00095         
00096         if(!taskIDFound){
00097                 cerr<<"NeuronTaskHolder: TRYING TO REMOVE RECEIVING TASK. TASK ID CANNOT BE FOUND. TID: "<<taskID<<endl;
00098                 return;
00099         }
00100 
00101         // Store a reference to the old array
00102         int *oldArray = destinationTaskIDs;
00103         
00104         //Create a new array to hold taskIDs
00105         destinationTaskIDs = new int[numberOfTasks - 1];
00106         
00107         //Copy old array into new array
00108         int counter = 0;
00109         for(int i=0; i<numberOfTasks; ++i)
00110                 if(destinationTaskIDs[i] != taskID){
00111                         destinationTaskIDs[counter] = oldArray[i];
00112                         ++counter;
00113                 }
00114         
00115         //Remove the old array and decrease the number of tasks.
00116         delete [] oldArray;
00117         --numberOfTasks;
00118 }
00119 
00120 
00121 /*! Sends the list of firing neurons to the receiving tasks. */
00122 bool NeuronTaskHolder::sendFiringNeuronMessages(){
00123         unsigned int numberOfNeurons = firingNeuronVector.size();
00124 
00125         //Keep track of the total number of neurons in statistics mode
00126         #ifdef RECORD_STATISTICS
00127                 SpikeStreamSimulation::statistics.neuronFireTotal += numberOfNeurons;
00128         #endif//RECORD_STATISTICS
00129 
00130         //Reset vector and return if there are no recipients of messages
00131         if(numberOfTasks == 0){
00132                 firingNeuronVector.clear();
00133                 return true;
00134         }
00135 
00136         //Initialise the send buffer
00137         int info = pvm_initsend( PvmDataDefault);
00138         #ifdef PVM_DEBUG
00139                 if(info < 0){
00140                         cerr<<"NeuronTaskHolder: ERROR INITIALISING BUFFER; TASK ID = "<<thisTaskID<<endl;
00141                         return false;
00142                 }
00143         #endif//PVM_DEBUG
00144          
00145         //Add timestep to message
00146         unsigned int messageTimeStep = SpikeStreamSimulation::simulationClock->getTimeStep(); 
00147         info = pvm_pkuint(&messageTimeStep, 1, 1);
00148         #ifdef PVM_DEBUG
00149                 if(info < 0){
00150                         cerr<<"NeuronTaskHolder: ERROR PACKING TIME STEP INTO MESSAGE; TASK ID = "<<thisTaskID<<endl;
00151                         return false;
00152                 }
00153         #endif//PVM_DEBUG
00154 
00155          //Add number specifying number of neurons that will be in message
00156         info = pvm_pkuint(&numberOfNeurons, 1, 1);
00157         #ifdef PVM_DEBUG
00158                 if(info < 0){
00159                         cerr<<"NeuronTaskHolder: ERROR PACKING NEURON COUNT INTO MESSAGE; TASK ID = "<<thisTaskID<<endl;
00160                         return false;
00161                 }
00162         #endif//PVM_DEBUG
00163 
00164         //Add the firing neuron ids to the message
00165         for(vector<unsigned int>::iterator iter = firingNeuronVector.begin(); iter != firingNeuronVector.end(); ++iter){
00166                 info = pvm_pkuint(&(*iter), 1, 1);
00167                 #ifdef PVM_DEBUG
00168                         if(info < 0){
00169                                 cerr<<"NeuronTaskHolder: ERROR PACKING NEURON IDS INTO MESSAGE; TASK ID = "<<thisTaskID<<endl;
00170                                 return false;
00171                         }
00172                 #endif//PVM_DEBUG
00173         }
00174         
00175         //Output debugging information if required
00176         #ifdef NEURON_TASK_DEBUG
00177                 //Print destinations for the messages
00178                 cout<<"NeuronTaskHolder: Destination task IDS (number of tasks = "<<numberOfTasks<<"): ";
00179                 for(int i=0; i<numberOfTasks; i++)
00180                         cout<<destinationTaskIDs[i]<<", ";
00181                 cout<<endl;
00182 
00183                 //Print contents of the messages.
00184                 cout<<"Timestep = "<<SpikeStreamSimulation::simulationClock->getTimeStep()<<"; Number of neurons = "<<numberOfNeurons<<endl;
00185                 for(vector<unsigned int>::iterator iter = firingNeuronVector.begin(); iter != firingNeuronVector.end(); ++iter)
00186                         cout<<"NEURON ID = "<<(*iter)<<", ";
00187                 cout<<endl;
00188         #endif//NEURON_TASK_DEBUG
00189 
00190 
00191         /* Send message to other tasks
00192                 Might be more than 1 task ID Use multicast to send the message to all of the task IDs */
00193         info = pvm_mcast( destinationTaskIDs, numberOfTasks, FIRING_NEURON_LIST_MSG);
00194         #ifdef PVM_DEBUG
00195                 if(info < 0){
00196                         cerr<<"NeuronTaskHolder: ERROR SENDING MESSAGE; TASK ID = "<<thisTaskID<<endl;
00197                         return false;
00198                 }
00199         #endif//PVM_DEBUG
00200         
00201         // Reset firingNeuronVector
00202         firingNeuronVector.clear();
00203         
00204         //If we have reached this point everything should be ok.
00205         return true;
00206 }
00207 
00208 
00209 
00210 

Generated on Mon Sep 3 22:24:34 2007 for SpikeStream Simulation by  doxygen 1.4.4