From 45a0a7c5abe533793f56685310fd175e98ae973e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beat=20K=C3=BCng?= Date: Fri, 29 Apr 2016 13:01:01 +0200 Subject: [PATCH] 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. --- src/modules/uORB/uORBCommon.hpp | 6 +++-- src/modules/uORB/uORBDevices_nuttx.hpp | 3 +++ src/modules/uORB/uORBDevices_posix.hpp | 3 +++ src/modules/uORB/uORBMain.cpp | 12 ++------- src/modules/uORB/uORBManager.cpp | 36 ++++++++++++++++++++++++++ src/modules/uORB/uORBManager.hpp | 11 ++++++++ 6 files changed, 59 insertions(+), 12 deletions(-) diff --git a/src/modules/uORB/uORBCommon.hpp b/src/modules/uORB/uORBCommon.hpp index be2ad8a89d..aba7dbdf5e 100644 --- a/src/modules/uORB/uORBCommon.hpp +++ b/src/modules/uORB/uORBCommon.hpp @@ -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 { diff --git a/src/modules/uORB/uORBDevices_nuttx.hpp b/src/modules/uORB/uORBDevices_nuttx.hpp index 2ad16ee3c7..2a92a5ad16 100644 --- a/src/modules/uORB/uORBDevices_nuttx.hpp +++ b/src/modules/uORB/uORBDevices_nuttx.hpp @@ -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: diff --git a/src/modules/uORB/uORBDevices_posix.hpp b/src/modules/uORB/uORBDevices_posix.hpp index 7fad8b5e7f..a129bd7905 100644 --- a/src/modules/uORB/uORBDevices_posix.hpp +++ b/src/modules/uORB/uORBDevices_posix.hpp @@ -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); diff --git a/src/modules/uORB/uORBMain.cpp b/src/modules/uORB/uORBMain.cpp index 66b98debf2..c86d7caa26 100644 --- a/src/modules/uORB/uORBMain.cpp +++ b/src/modules/uORB/uORBMain.cpp @@ -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; diff --git a/src/modules/uORB/uORBManager.cpp b/src/modules/uORB/uORBManager.cpp index 05f88dd6f2..b73dcb6e43 100644 --- a/src/modules/uORB/uORBManager.cpp +++ b/src/modules/uORB/uORBManager.cpp @@ -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) { /* diff --git a/src/modules/uORB/uORBManager.hpp b/src/modules/uORB/uORBManager.hpp index d0e82caa76..f64231747d 100644 --- a/src/modules/uORB/uORBManager.hpp +++ b/src/modules/uORB/uORBManager.hpp @@ -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.