Cleaned up robot startup and cleanup/shutdown code (#77)

Cleaned up RobotBase, removed singleton list from SensorBase, and removed unused typedefs and NULL_TASK macro from HAL's Task.hpp. Making the robot class instance static fixed non-POD statics used by the instance during destruction from being destroyed first.
This commit is contained in:
Tyler Veness
2016-06-19 00:13:18 -07:00
committed by Peter Johnson
parent ecc210f99a
commit d66c61a36e
10 changed files with 16 additions and 184 deletions

View File

@@ -10,16 +10,6 @@
#include <pthread.h>
#include <stdint.h>
#ifndef _FUNCPTR_DEFINED
#define _FUNCPTR_DEFINED
#ifdef __cplusplus
typedef int (*FUNCPTR)(...);
/* ptr to function returning int */
#else
typedef int (*FUNCPTR)(); /* ptr to function returning int */
#endif /* __cplusplus */
#endif /* _FUNCPTR_DEFINED */
#ifndef _STATUS_DEFINED
#define _STATUS_DEFINED
typedef int STATUS;
@@ -32,7 +22,6 @@ typedef int STATUS;
#define ERROR (-1)
#endif /* ERROR */
#define NULL_TASK NULL
typedef pthread_t* TASK;
extern "C" {

View File

@@ -7,8 +7,10 @@
#pragma once
#include <cstdio>
#include <iostream>
#include "Base.h"
#include "Task.h"
class DriverStation;
@@ -20,9 +22,9 @@ class DriverStation;
} \
HALReport(HALUsageReporting::kResourceType_Language, \
HALUsageReporting::kLanguage_CPlusPlus); \
_ClassName_* robot = new _ClassName_(); \
RobotBase::robotSetup(robot); \
return 0; \
static _ClassName_ robot; \
std::printf("\n********** Robot program starting **********\n"); \
robot.StartCompetition(); \
}
/**
@@ -35,34 +37,21 @@ class DriverStation;
* then killed at the end of the Autonomous period.
*/
class RobotBase {
friend class RobotDeleter;
public:
static RobotBase& getInstance();
static void setInstance(RobotBase* robot);
bool IsEnabled() const;
bool IsDisabled() const;
bool IsAutonomous() const;
bool IsOperatorControl() const;
bool IsTest() const;
bool IsNewDataAvailable() const;
static void startRobotTask(FUNCPTR factory);
static void robotTask(FUNCPTR factory, Task* task);
virtual void StartCompetition() = 0;
static void robotSetup(RobotBase* robot);
protected:
RobotBase();
virtual ~RobotBase();
virtual ~RobotBase() = default;
RobotBase(const RobotBase&) = delete;
RobotBase& operator=(const RobotBase&) = delete;
Task* m_task = nullptr;
DriverStation& m_ds;
private:
static RobotBase* m_instance;
};

View File

@@ -58,8 +58,6 @@ DriverStation::DriverStation() {
// It will signal when new packet data is available.
HALSetNewDataSem(&m_packetDataAvailableCond);
AddToSingletonList();
m_task = Task("DriverStation", &DriverStation::Run, this);
}
@@ -104,8 +102,8 @@ void DriverStation::Run() {
* @return Pointer to the DS instance
*/
DriverStation& DriverStation::GetInstance() {
static DriverStation* instance = new DriverStation();
return *instance;
static DriverStation instance;
return instance;
}
/**

View File

@@ -17,20 +17,6 @@
#include "Utility.h"
#include "networktables/NetworkTable.h"
RobotBase* RobotBase::m_instance = nullptr;
void RobotBase::setInstance(RobotBase* robot) {
wpi_assert(m_instance == nullptr);
m_instance = robot;
}
RobotBase& RobotBase::getInstance() { return *m_instance; }
void RobotBase::robotSetup(RobotBase* robot) {
std::printf("\n********** Robot program starting **********\n");
robot->StartCompetition();
}
/**
* Constructor for a generic robot program.
*
@@ -46,8 +32,6 @@ RobotBase::RobotBase() : m_ds(DriverStation::GetInstance()) {
RobotState::SetImplementation(DriverStation::GetInstance());
HLUsageReporting::SetImplementation(new HardwareHLReporting());
RobotBase::setInstance(this);
NetworkTable::SetNetworkIdentity("Robot");
NetworkTable::SetPersistentFilename("/home/lvuser/networktables.ini");
@@ -60,18 +44,6 @@ RobotBase::RobotBase() : m_ds(DriverStation::GetInstance()) {
}
}
/**
* Free the resources for a RobotBase class.
* This includes deleting all classes that might have been allocated as
* Singletons to they would never be deleted except here.
*/
RobotBase::~RobotBase() {
SensorBase::DeleteSingletons();
delete m_task;
m_task = nullptr;
m_instance = nullptr;
}
/**
* Determine if the Robot is currently enabled.
* @return True if the Robot is currently enabled by the field controls.
@@ -111,17 +83,3 @@ bool RobotBase::IsTest() const { return m_ds.IsTest(); }
* function was called?
*/
bool RobotBase::IsNewDataAvailable() const { return m_ds.IsNewControlData(); }
/**
* This class exists for the sole purpose of getting its destructor called when
* the module unloads.
* Before the module is done unloading, we need to delete the RobotBase derived
* singleton. This should delete the other remaining singletons that were
* registered. This should also stop all tasks that are using the Task class.
*/
class RobotDeleter {
public:
RobotDeleter() {}
~RobotDeleter() { delete &RobotBase::getInstance(); }
};
static RobotDeleter g_robotDeleter;

View File

@@ -19,7 +19,6 @@ const uint32_t SensorBase::kPwmChannels;
const uint32_t SensorBase::kRelayChannels;
const uint32_t SensorBase::kPDPChannels;
const uint32_t SensorBase::kChassisSlots;
SensorBase* SensorBase::m_singletonList = nullptr;
static bool portsInitialized = false;
void* SensorBase::m_digital_ports[kDigitalChannels];
@@ -57,37 +56,6 @@ SensorBase::SensorBase() {
}
}
/**
* Add sensor to the singleton list.
*
* Add this sensor to the list of singletons that need to be deleted when
* the robot program exits. Each of the sensors on this list are singletons,
* that is they aren't allocated directly with new, but instead are allocated
* by the static GetInstance method. As a result, they are never deleted when
* the program exits. Consequently these sensors may still be holding onto
* resources and need to have their destructors called at the end of the
* program.
*/
void SensorBase::AddToSingletonList() {
m_nextSingleton = m_singletonList;
m_singletonList = this;
}
/**
* Delete all the singleton classes on the list.
*
* All the classes that were allocated as singletons need to be deleted so
* their resources can be freed.
*/
void SensorBase::DeleteSingletons() {
for (SensorBase* next = m_singletonList; next != nullptr;) {
SensorBase* tmp = next;
next = next->m_nextSingleton;
delete tmp;
}
m_singletonList = nullptr;
}
/**
* Check that the solenoid module number is valid.
*

View File

@@ -25,8 +25,6 @@ class SensorBase : public ErrorBase {
SensorBase(const SensorBase&) = delete;
SensorBase& operator=(const SensorBase&) = delete;
static void DeleteSingletons();
static uint32_t GetDefaultSolenoidModule() { return 0; }
static bool CheckSolenoidModule(uint8_t moduleNumber);
@@ -49,13 +47,7 @@ class SensorBase : public ErrorBase {
static const uint32_t kChassisSlots = 8;
protected:
void AddToSingletonList();
static void* m_digital_ports[kDigitalChannels];
static void* m_relay_ports[kRelayChannels];
static void* m_pwm_ports[kPwmChannels];
private:
static SensorBase* m_singletonList;
SensorBase* m_nextSingleton = nullptr;
};

View File

@@ -7,15 +7,18 @@
#pragma once
#include <cstdio>
#include "Base.h"
#include "DriverStation.h"
#include "simulation/MainNode.h"
#include "simulation/simTime.h"
#define START_ROBOT_CLASS(_ClassName_) \
int main() { \
(new _ClassName_())->StartCompetition(); \
return 0; \
#define START_ROBOT_CLASS(_ClassName_) \
int main() { \
static _ClassName_ robot; \
std::printf("\n********** Robot program starting **********\n"); \
robot.StartCompetition(); \
}
/**
@@ -29,12 +32,7 @@
* then killed at the end of the Autonomous period.
*/
class RobotBase {
friend class RobotDeleter;
public:
static RobotBase& getInstance();
static void setInstance(RobotBase* robot);
bool IsEnabled() const;
bool IsDisabled() const;
bool IsAutonomous() const;
@@ -51,7 +49,4 @@ class RobotBase {
DriverStation& m_ds;
transport::SubscriberPtr time_sub;
private:
static RobotBase* m_instance;
};

View File

@@ -51,8 +51,6 @@ DriverStation::DriverStation() {
joysticks[5] = msgs::FRCJoystickPtr(new msgs::FRCJoystick());
joysticksSub[5] = MainNode::Subscribe(
"~/ds/joysticks/5", &DriverStation::joystickCallback5, this);
AddToSingletonList();
}
/**

View File

@@ -11,15 +11,6 @@
#include <string.h>
RobotBase* RobotBase::m_instance = nullptr;
void RobotBase::setInstance(RobotBase* robot) {
wpi_assert(m_instance == nullptr);
m_instance = robot;
}
RobotBase& RobotBase::getInstance() { return *m_instance; }
/**
* Constructor for a generic robot program.
*
@@ -73,17 +64,3 @@ bool RobotBase::IsOperatorControl() const { return m_ds.IsOperatorControl(); }
* field controls.
*/
bool RobotBase::IsTest() const { return m_ds.IsTest(); }
/**
* This class exists for the sole purpose of getting its destructor called when
* the module unloads.
*
* Before the module is done unloading, we need to delete the RobotBase derived
* singleton. This should delete the other remaining singletons that were
* registered. This should also stop all tasks that are using the Task class.
*/
class RobotDeleter {
public:
~RobotDeleter() { delete &RobotBase::getInstance(); }
};
static RobotDeleter g_robotDeleter;

View File

@@ -17,44 +17,12 @@ const uint32_t SensorBase::kPwmChannels;
const uint32_t SensorBase::kRelayChannels;
const uint32_t SensorBase::kPDPChannels;
const uint32_t SensorBase::kChassisSlots;
SensorBase* SensorBase::m_singletonList = nullptr;
/**
* Creates an instance of the sensor base and gets an FPGA handle
*/
SensorBase::SensorBase() {}
/**
* Add sensor to the singleton list.
*
* Add this sensor to the list of singletons that need to be deleted when
* the robot program exits. Each of the sensors on this list are singletons,
* that is they aren't allocated directly with new, but instead are allocated
* by the static GetInstance method. As a result, they are never deleted when
* the program exits. Consequently these sensors may still be holding onto
* resources and need to have their destructors called at the end of the
* program.
*/
void SensorBase::AddToSingletonList() {
m_nextSingleton = m_singletonList;
m_singletonList = this;
}
/**
* Delete all the singleton classes on the list.
*
* All the classes that were allocated as singletons need to be deleted so
* their resources can be freed.
*/
void SensorBase::DeleteSingletons() {
for (SensorBase* next = m_singletonList; next != nullptr;) {
SensorBase* tmp = next;
next = next->m_nextSingleton;
delete tmp;
}
m_singletonList = nullptr;
}
/**
* Check that the solenoid module number is valid.
*