Now you can download a copy of these docs so you can use them offline! Download now
Scheduler.cpp
00001 /*----------------------------------------------------------------------------*/ 00002 /* Copyright (c) FIRST 2011. All Rights Reserved. */ 00003 /* Open Source Software - may be modified and shared by FRC teams. The code */ 00004 /* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */ 00005 /*----------------------------------------------------------------------------*/ 00006 00007 #include "Commands/Scheduler.h" 00008 00009 #include "Buttons/ButtonScheduler.h" 00010 #include "Commands/Subsystem.h" 00011 #include "NetworkTables/NetworkTable.h" 00012 #include "Synchronized.h" 00013 #include "WPIErrors.h" 00014 #include <iostream> 00015 #include <set> 00016 #include <semLib.h> 00017 00018 Scheduler *Scheduler::_instance = NULL; 00019 00020 Scheduler::Scheduler() : 00021 m_tableLock(NULL), 00022 m_table(NULL), 00023 m_buttonsLock(NULL), 00024 m_additionsLock(NULL), 00025 m_adding(false) 00026 { 00027 m_tableLock = semMCreate(SEM_Q_PRIORITY | SEM_INVERSION_SAFE | SEM_DELETE_SAFE); 00028 m_buttonsLock = semMCreate(SEM_Q_PRIORITY | SEM_INVERSION_SAFE | SEM_DELETE_SAFE); 00029 m_additionsLock = semMCreate(SEM_Q_PRIORITY | SEM_INVERSION_SAFE | SEM_DELETE_SAFE); 00030 } 00031 00032 Scheduler::~Scheduler() 00033 { 00034 semTake(m_additionsLock, WAIT_FOREVER); 00035 semDelete(m_additionsLock); 00036 00037 semTake(m_buttonsLock, WAIT_FOREVER); 00038 semDelete(m_buttonsLock); 00039 00040 semTake(m_tableLock, WAIT_FOREVER); 00041 semDelete(m_tableLock); 00042 } 00043 00048 Scheduler *Scheduler::GetInstance() 00049 { 00050 if (_instance == NULL) 00051 _instance = new Scheduler(); 00052 return _instance; 00053 } 00054 00055 void Scheduler::AddCommand(Command *command) 00056 { 00057 Synchronized sync(m_additionsLock); 00058 m_additions.push_back(command); 00059 } 00060 00061 void Scheduler::AddButton(ButtonScheduler *button) 00062 { 00063 Synchronized sync(m_buttonsLock); 00064 m_buttons.push_back(button); 00065 } 00066 00067 void Scheduler::ProcessCommandAddition(Command *command) 00068 { 00069 if (command == NULL) 00070 return; 00071 00072 // Check to make sure no adding during adding 00073 if (m_adding) 00074 { 00075 wpi_setWPIErrorWithContext(IncompatibleState, "Can not start command from cancel method"); 00076 return; 00077 } 00078 00079 // Only add if not already in 00080 CommandSet::iterator found = m_commands.find(command); 00081 if (found == m_commands.end()) 00082 { 00083 // Check that the requirements can be had 00084 Command::SubsystemSet requirements = command->GetRequirements(); 00085 Command::SubsystemSet::iterator iter; 00086 for (iter = requirements.begin(); iter != requirements.end(); iter++) 00087 { 00088 Subsystem *lock = *iter; 00089 if (lock->GetCurrentCommand() != NULL && !lock->GetCurrentCommand()->IsInterruptible()) 00090 return; 00091 } 00092 00093 // Give it the requirements 00094 m_adding = true; 00095 for (iter = requirements.begin(); iter != requirements.end(); iter++) 00096 { 00097 Subsystem *lock = *iter; 00098 if (lock->GetCurrentCommand() != NULL) 00099 { 00100 lock->GetCurrentCommand()->Cancel(); 00101 Remove(lock->GetCurrentCommand()); 00102 } 00103 lock->SetCurrentCommand(command); 00104 } 00105 m_adding = false; 00106 00107 m_commands.insert(command); 00108 00109 command->StartRunning(); 00110 } 00111 } 00112 00125 void Scheduler::Run() 00126 { 00127 // Get button input (going backwards preserves button priority) 00128 { 00129 Synchronized sync(m_buttonsLock); 00130 ButtonVector::reverse_iterator rButtonIter = m_buttons.rbegin(); 00131 for (; rButtonIter != m_buttons.rend(); rButtonIter++) 00132 { 00133 (*rButtonIter)->Execute(); 00134 } 00135 } 00136 00137 // Loop through the commands 00138 CommandSet::iterator commandIter = m_commands.begin(); 00139 for (; commandIter != m_commands.end();) 00140 { 00141 Command *command = *commandIter; 00142 // Increment before potentially removing to keep the iterator valid 00143 commandIter++; 00144 if (!command->Run()) 00145 { 00146 Remove(command); 00147 } 00148 } 00149 00150 // Send the value over the table 00151 if (m_table != NULL) { 00152 int count = 0; 00153 Synchronized sync(m_tableLock); 00154 m_table->BeginTransaction(); 00155 commandIter = m_commands.begin(); 00156 for (; commandIter != m_commands.end(); commandIter++) 00157 { 00158 char buf[10]; 00159 snprintf(buf, 10, "%d", ++count); 00160 m_table->PutSubTable(buf, (*commandIter)->GetTable()); 00161 } 00162 m_table->PutInt("count", count); 00163 m_table->EndTransaction(); 00164 } 00165 00166 // Add the new things 00167 { 00168 Synchronized sync(m_additionsLock); 00169 CommandVector::iterator additionsIter = m_additions.begin(); 00170 for (; additionsIter != m_additions.end(); additionsIter++) 00171 { 00172 ProcessCommandAddition(*additionsIter); 00173 } 00174 m_additions.clear(); 00175 } 00176 00177 // Add in the defaults 00178 Command::SubsystemSet::iterator subsystemIter = m_subsystems.begin(); 00179 for (; subsystemIter != m_subsystems.end(); subsystemIter++) 00180 { 00181 Subsystem *lock = *subsystemIter; 00182 if (lock->GetCurrentCommand() == NULL) 00183 { 00184 ProcessCommandAddition(lock->GetDefaultCommand()); 00185 } 00186 lock->ConfirmCommand(); 00187 } 00188 } 00189 00195 void Scheduler::RegisterSubsystem(Subsystem *subsystem) 00196 { 00197 if (subsystem == NULL) 00198 { 00199 wpi_setWPIErrorWithContext(NullParameter, "subsystem"); 00200 return; 00201 } 00202 m_subsystems.insert(subsystem); 00203 } 00204 00209 void Scheduler::Remove(Command *command) 00210 { 00211 if (command == NULL) 00212 { 00213 wpi_setWPIErrorWithContext(NullParameter, "command"); 00214 return; 00215 } 00216 00217 if (!m_commands.erase(command)) 00218 return; 00219 00220 Command::SubsystemSet requirements = command->GetRequirements(); 00221 Command::SubsystemSet::iterator iter = requirements.begin(); 00222 for (; iter != requirements.end(); iter++) 00223 { 00224 Subsystem *lock = *iter; 00225 lock->SetCurrentCommand(NULL); 00226 } 00227 00228 command->Removed(); 00229 } 00230 00231 std::string Scheduler::GetName() 00232 { 00233 return "Scheduler"; 00234 } 00235 00236 std::string Scheduler::GetType() 00237 { 00238 return "Scheduler"; 00239 } 00240 00241 NetworkTable *Scheduler::GetTable() 00242 { 00243 if (m_table == NULL) 00244 { 00245 m_table = new NetworkTable(); 00246 m_table->PutInt("count", 0); 00247 } 00248 return m_table; 00249 }
Generated on Thu Jan 12 2012 22:35:23 for WPILibC++ by
1.7.1