并行编程实战——TBB框架的应用之三Supra的配置文件管理

一、Supra配置文件

其实这一段和TBB本身的联系并不大,讲它略有些鸡肋。但是不分析它又不好分析后面的节点的动态管理,所以还是拉过来一起分析一下。在前面其实简单介绍过这一个模块,它主要是通过配置文件的读写操作来动态处理节点的参数传递。同时,在Supra中支持实时的对参数的修改,这个显得尤为突出。
其配置管理文件主要为XML类型,在XML的节点中,定义上节点的名称、类型和ID。并且在其子项中定义了相关的参数及参数的值。而在Supra程序内自动通过tinyxml调用来解析这个配置文件获取得相关的信息(包括但不限于上面提到的参数等)。配置文件中还支持定义Supra类型节点的连接状态的定义和相关参数处理,这样就可以直接进行整个项目中节点的数据流向和分析的控制。

二、Supra对配置文件的管理

Supra中对配置文件的管理分成两大块,即节点的管理和配置的动态处理。
1、节点的管理
节点的管理类似于静态的定义节点的名称等用来生成实例和进行节点间的连接。在程序中基本分为普通节点的读写、输入节点的读写和输出节点的读写以及后面的连接控制读写操作。这样就形成了整体认知上的静态管理。
2、配置的动态处理
这个更多的是配置文件选项的自我管理,提供了不同数据类型的处理及相关参数发生变化后动态通知程序进行更新。

三、动态管理配置文件

节点的动态加载这一块基本已经分析过了,如果想要查看更细节的代码可以下载其源码进行分析即可。这里重点分析一下其对配置文件的动态管理这部分。从应用层次上看,其为分三个层次:
1、节点应用

//抽象基类

//This is ugly, but "queueing" and "rejecting" are enum-values in old versions and types in newer versions...
#if TBB_INTERFACE_VERSION_MAJOR >= 9
#define TBB_QUEUE_RESOLVER(__buffering__) typename std::conditional<__buffering__, tbb::flow::queueing, tbb::flow::rejecting>::type
#else
#define TBB_QUEUE_RESOLVER(__buffering__) (__buffering__ ? tbb::flow::queueing : tbb::flow::rejecting)
#endif //TBB_INTERFACE_VERSION_MAJOR >= 9

namespace supra
{
   
   
	class RecordObject;
}

namespace supra
{
   
   
	/*! \brief Abstract interface for a general node (input, output or processing).
	*
	*  This is the common interface for all nodes.
	*/
	class AbstractNode
	{
   
   
......
	public:
		/// Base constructor for all nodes
		AbstractNode(const std::string & nodeID, bool queueing)
			: m_nodeID(nodeID)
			, m_queueing(queueing)
		{
   
   
			m_configurationDictionary.setValueRangeDictionary(&m_valueRangeDictionary);
		}

......

		/// Returns a const pointer to the \see ValueRangeDictionary of this node
		/// The ValueRangeDictionary describes the parameters of the node and
		/// their valid ranges
		const ValueRangeDictionary * getValueRangeDictionary()
		{
   
   
			return &m_valueRangeDictionary;
		}

		/// Returns a const pointer to the \see ConfigurationDictionary of this node
		/// The ConfigurationDictionary contains the parameters currently set
		/// and their values
		const ConfigurationDictionary * getConfigurationDictionary()
		{
   
   
			return &m_configurationDictionary;
		}

		/// Returns the ID of the node.
		/// Node IDs are unique and cannot be changed after creation.
		const std::string& getNodeID()
		{
   
   
			return m_nodeID;
		}

		/// Templated interface to change a node parameter
		/// returns whether the value was valid
		template<typename ValueType>
		bool changeConfig(const std::string& configKey, const ValueType& newValue)
		{
   
   
			if (m_valueRangeDictionary.hasKey(configKey) &&
				m_valueRangeDictionary.isInRange(configKey, newValue))
			{
   
   
				logging::log_parameter("Parameter: ", m_nodeID, ".", configKey, " = ", newValue);
				m_configurationDictionary.set(configKey, newValue);
				configurationEntryChanged(configKey);
				return true;
			}
			return false;
		}
		/// Function to set the whole \see ConfiguraitonDictionary at once
		/// Only parameters whose value is valid are applied
		void changeConfig(const ConfigurationDictionary& newConfig)
		{
   
   
			// trigger callback for major configuration changes in overloaded implementation
			configurationDictionaryChanged(newConfig);

			//validate the configuration entries
			ConfigurationDictionary validConfig = newConfig;
			validConfig.setValueRangeDictionary(&m_valueRangeDictionary);
			validConfig.checkEntriesAndLog(m_nodeID);

			//store all valid entries
			m_configurationDictionary = validConfig;
			configurationChanged();
		}

		/// Returns a string with the timing info (call frequency and run-time)
		/// if the node uses the \see CallFrequency member to monitor itself
		std::string getTimingInfo()
		{
   
   
			return m_callFrequency.getTimingInfo();
		}

	protected:
		/// The collection of node parameters
		ConfigurationDictionary m_configurationDictionary;
		/// The definition of parameters and their respective ranges
		ValueRangeDictionary m_valueRangeDictionary;
		/// \see CallFrequency can be used by the node implementation to monitor its
		/// timings (frequency of activation and run-time)
		CallFrequency m_callFrequency;

		bool m_queueing;

	protected:
		/// Callback for the node implementation to be notified of the change of parameters.
		/// Needs to be overwritten and thread-safe
		virtual void configurationEntryChanged(const std::string& configKey) {
   
   };
		/// Callback for the node implementation to be notified of the change of parameters.
		/// Needs to be overwritten and thread-safe
		virtual void configurationChanged() {
   
   };
		/// Callback for the node implementation to be notified of the change of a full dictionary change.
		/// can be be overwritten but must be thread-safe
		/// dictionary does not contain fail-safe mechanisms yet, thus should be only used to adjust value range changes or add new settings on the fly
		virtual void configurationDictionaryChanged(const ConfigurationDictionary& newConfig) {
   
   };


	private:
		std::string m_nodeID;
	};
}

#endif //!__ABSTRACTNODE_H__

    InputDevice::InputDevice(tbb::flow::graph& graph, const std::string & nodeID)
        : AbstractInput(graph, nodeID,1)
        , m_sequenceIndex(0)
        , m_frameIndex(0)
        , m_numel(0)
        , m_frozen(false)
        , m_lastFrame(false)
        , m_ready(false)
    {
   
   
        m_callFrequency.setName("RawMhd");
        //Setup allowed values for parameters
        m_valueRangeDictionary.set<bool>("singleImage", {
   
    true, false }, false, "Single image");
        m_valueRangeDictionary.set<bool>("streamSequenceOnce", {
   
    true, false }, false, "Emit sequences once");
        m_valueRangeDictionary.set<double>("frequency", 0.001, 100, 5, "Frequency");
        m_valueRangeDictionary.set<std::string>("mhdMetaDataFilename", "", "User
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值