refactor orb: uORB::Manager is responsible for the DeviceMaster objects

This has the following benefits:
- Manager can ensure that there is at most one instance of DeviceMaster
  per Flavor
- The Manager needs access to (static) data of DeviceMaster already.
  This will make it easier to access this data in a non-static way, and
  does not introduce new dependencies.
This commit is contained in:
Beat Küng 2016-04-29 13:01:01 +02:00 committed by Lorenz Meier
parent 2dd29ec4a1
commit 45a0a7c5ab
6 changed files with 59 additions and 12 deletions

View File

@ -52,8 +52,10 @@ static const unsigned orb_maxpath = 64;
const int ERROR = -1;
enum Flavor {
PUBSUB,
PARAM
PUBSUB = 0,
PARAM,
Flavor_count
};
struct orb_advertdata {

View File

@ -45,6 +45,7 @@ namespace uORB
{
class DeviceNode;
class DeviceMaster;
class Manager;
}
/**
@ -259,6 +260,8 @@ public:
DeviceMaster(Flavor f);
virtual ~DeviceMaster();
friend class uORB::Manager;
static uORB::DeviceNode *GetDeviceNode(const char *node_name);
virtual int ioctl(struct file *filp, int cmd, unsigned long arg);
private:

View File

@ -43,6 +43,7 @@ namespace uORB
{
class DeviceNode;
class DeviceMaster;
class Manager;
}
class uORB::DeviceNode : public device::VDev
@ -193,6 +194,8 @@ public:
DeviceMaster(Flavor f);
virtual ~DeviceMaster();
friend class uORB::Manager;
static uORB::DeviceNode *GetDeviceNode(const char *node_name);
virtual int ioctl(device::file_t *filp, int cmd, unsigned long arg);

View File

@ -72,18 +72,10 @@ uorb_main(int argc, char *argv[])
}
/* create the driver */
g_dev = new uORB::DeviceMaster(uORB::PUBSUB);
g_dev = uORB::Manager::get_instance()->get_device_master(uORB::PUBSUB);
if (g_dev == nullptr) {
PX4_ERR("driver alloc failed");
return -ENOMEM;
}
if (OK != g_dev->init()) {
PX4_ERR("driver init failed");
delete g_dev;
g_dev = nullptr;
return -EIO;
return -errno;
}
return OK;

View File

@ -64,6 +64,9 @@ bool uORB::Manager::initialize()
uORB::Manager::Manager()
: _comm_channel(nullptr)
{
for (int i = 0; i < Flavor_count; ++i) {
_device_masters[i] = nullptr;
}
#ifdef ORB_USE_PUBLISHER_RULES
const char *file_name = "./rootfs/orb_publisher.rules";
@ -81,6 +84,39 @@ uORB::Manager::Manager()
}
uORB::Manager::~Manager()
{
for (int i = 0; i < Flavor_count; ++i) {
if (_device_masters[i]) {
delete _device_masters[i];
}
}
}
uORB::DeviceMaster *uORB::Manager::get_device_master(Flavor flavor)
{
if (!_device_masters[flavor]) {
_device_masters[flavor] = new DeviceMaster(flavor);
if (_device_masters[flavor]) {
int ret = _device_masters[flavor]->init();
if (ret != PX4_OK) {
PX4_ERR("Initialization of DeviceMaster failed (%i)", ret);
errno = -ret;
delete _device_masters[flavor];
_device_masters[flavor] = nullptr;
}
} else {
PX4_ERR("Failed to allocate DeviceMaster");
errno = ENOMEM;
}
}
return _device_masters[flavor];
}
int uORB::Manager::orb_exists(const struct orb_metadata *meta, int instance)
{
/*

View File

@ -78,6 +78,14 @@ public:
return _Instance;
}
/**
* Get the DeviceMaster for a given Flavor. If it does not exist,
* it will be created and initialized.
* Note: the first call to this is not thread-safe.
* @return nullptr if initialization failed (and errno will be set)
*/
uORB::DeviceMaster *get_device_master(Flavor flavor);
// ==== uORB interface methods ====
/**
* Advertise as the publisher of a topic.
@ -399,8 +407,11 @@ private: // data members
uORBCommunicator::IChannel *_comm_channel;
ORBSet _remote_subscriber_topics;
DeviceMaster *_device_masters[Flavor_count]; ///< Allow at most one DeviceMaster per Flavor
private: //class methods
Manager();
~Manager();
/**
* Interface to process a received AddSubscription from remote.