Skip to content
Snippets Groups Projects
ApplicationModule.h 3.67 KiB
Newer Older
/*
 * ApplicationModule.h
 *
 *  Created on: Jun 10, 2016
 *      Author: Martin Hierholzer
 */

#ifndef CHIMERATK_APPLICATION_MODULE_H
#define CHIMERATK_APPLICATION_MODULE_H

  class Application;
  class ModuleGroup;
  struct ConfigReader;

  class ApplicationModule : public ModuleImpl {
   public:
    /** Constructor: Create ApplicationModule by the given name with the given description and register it with its
     *  owner. The hierarchy will be modified according to the hierarchyModifier (when VirtualModules are created e.g.
     *  in findTag()). The specified list of tags will be added to all elements directly or indirectly owned by this
     *  instance.
     *  Note: ApplicationModules may only be owned by ModuleGroups or Applications. */
    ApplicationModule(EntityOwner* owner, const std::string& name, const std::string& description,
        HierarchyModifier hierarchyModifier = HierarchyModifier::none,
        const std::unordered_set<std::string>& tags = {});

    /** Deprecated form of the constructor. Use the new signature instead. */
    ApplicationModule(EntityOwner* owner, const std::string& name, const std::string& description,
        bool eliminateHierarchy, const std::unordered_set<std::string>& tags = {});

    /** Default constructor: Allows late initialisation of modules (e.g. when
     * creating arrays of modules).
     *
     *  This construtor also has to be here to mitigate a bug in gcc. It is needed
     * to allow constructor inheritance of modules owning other modules. This
     * constructor will not actually be called then. See this bug report:
     * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67054 */
    ApplicationModule() {}

    /** Move operation with the move constructor */
    ApplicationModule(ApplicationModule&& other) { operator=(std::move(other)); }

    /** Move assignment */
    ApplicationModule& operator=(ApplicationModule&& other) {
      assert(!moduleThread.joinable()); // if the thread is already running,
                                        // moving is no longer allowed!
      ModuleImpl::operator=(std::move(other));
      return *this;
    }

    /** Destructor */
    virtual ~ApplicationModule();

    /** To be implemented by the user: function called in a separate thread
     * executing the main loop of the module */
    virtual void mainLoop() = 0;

    void run() override;

    void terminate() override;

    ModuleType getModuleType() const override { return ModuleType::ApplicationModule; }

    VersionNumber getCurrentVersionNumber() const override { return currentVersionNumber; }

    DataValidity getDataValidity() const override {
      return faultCounter == 0 ? DataValidity::ok : DataValidity::faulty;
    }

    void incrementDataFaultCounter() override { ++faultCounter; }

    void decrementDataFaultCounter() override {
      assert(faultCounter > 0);
      --faultCounter;
    }

   protected:
    /** Wrapper around mainLoop(), to execute additional tasks in the thread
     * before entering the main loop */
    void mainLoopWrapper();

    /** The thread executing mainLoop() */
    boost::thread moduleThread;

    void setCurrentVersionNumber(VersionNumber versionNumber) override {
      if(versionNumber > currentVersionNumber) currentVersionNumber = versionNumber;
    }

    /** Version number of last push-type read operation - will be passed on to any
     * write operations */
    VersionNumber currentVersionNumber;

    /** Fault counter. If non-zero, getDataValidity() returns a fault, otherwise ok. */
    size_t faultCounter{0};

} /* namespace ChimeraTK */

#endif /* CHIMERATK_APPLICATION_MODULE_H */