From 5602d991aae26ae6770c25462c19bbfb8b29a01e Mon Sep 17 00:00:00 2001 From: "Mark A. Tsuchida" Date: Wed, 6 Dec 2023 11:22:14 -0600 Subject: [PATCH 1/2] MMDevice: Add ActionLambda This is like CPropertyAction[Ex], but takes an arbitrary copyable callable (such as a lambda). Defining a property action using a lambda allows one to put all the code related to a single property in one place. --- MMDevice/Property.h | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/MMDevice/Property.h b/MMDevice/Property.h index 39e865be8..cbc669822 100644 --- a/MMDevice/Property.h +++ b/MMDevice/Property.h @@ -24,11 +24,13 @@ #define _MMPROPERTY_H_ #include "MMDeviceConstants.h" -#include -#include + #include -#include +#include +#include #include +#include +#include namespace MM { @@ -120,6 +122,24 @@ class ActionEx : public ActionFunctor { return (*pObj_.*fpt_)(pProp, eAct, param_);}; }; +/** + * Action implementation using std::function to wrap arbitrary callables. + * + * (It is named "lambda" after its intended use, but can wrap any C++ + * callable.) + */ +class ActionLambda final : public ActionFunctor +{ + std::function func_; + +public: + template explicit ActionLambda(F func) : func_(func) {} + + int Execute(PropertyBase* pProp, ActionType eAct) final { + return func_(pProp, eAct); + } +}; + /** * Property API with most of the Property mechanism implemented. */ From 8459a7c920f6808c52e963698bf48fff4ecdae65 Mon Sep 17 00:00:00 2001 From: "Mark A. Tsuchida" Date: Wed, 6 Dec 2023 11:24:18 -0600 Subject: [PATCH 2/2] BH_DCC_DCU: Use ActionLambda from MMDevice --- DeviceAdapters/BH_DCC_DCU/DCCDCUDevices.h | 51 ++++++++++------------- 1 file changed, 21 insertions(+), 30 deletions(-) diff --git a/DeviceAdapters/BH_DCC_DCU/DCCDCUDevices.h b/DeviceAdapters/BH_DCC_DCU/DCCDCUDevices.h index 99c94222a..4c9656805 100644 --- a/DeviceAdapters/BH_DCC_DCU/DCCDCUDevices.h +++ b/DeviceAdapters/BH_DCC_DCU/DCCDCUDevices.h @@ -27,18 +27,6 @@ #include #include -// This can be moved to DeviceBase.h to make available generally. -class ActionLambda final : public MM::ActionFunctor { - std::function f_; - - public: - template explicit ActionLambda(F f) : f_(f) {} - - auto Execute(MM::PropertyBase* pProp, MM::ActionType eAct) -> int { - return f_(pProp, eAct); - } -}; - template inline auto ModelName() -> std::string { if (Model == DCCOrDCU::DCC) { return "DCC"; @@ -426,8 +414,9 @@ class DCCDCUModuleDevice : public CGenericBase> { const std::string& name) { this->CreateStringProperty( name.c_str(), "Off", false, - new ActionLambda([this, connNo, feature, name]( - MM::PropertyBase* pProp, MM::ActionType eAct) { + new MM::ActionLambda([this, connNo, feature, + name](MM::PropertyBase* pProp, + MM::ActionType eAct) { if (eAct == MM::BeforeGet) { short err{}; const bool flag = @@ -467,8 +456,9 @@ class DCCDCUModuleDevice : public CGenericBase> { float maxValue) { this->CreateFloatProperty( name.c_str(), minValue, false, - new ActionLambda([this, connNo, feature, name]( - MM::PropertyBase* pProp, MM::ActionType eAct) { + new MM::ActionLambda([this, connNo, feature, + name](MM::PropertyBase* pProp, + MM::ActionType eAct) { if (eAct == MM::BeforeGet) { short err{}; const float value = @@ -506,8 +496,9 @@ class DCCDCUModuleDevice : public CGenericBase> { const std::string& name) { this->CreateIntegerProperty( name.c_str(), 0, false, - new ActionLambda([this, connNo, feature, name]( - MM::PropertyBase* pProp, MM::ActionType eAct) { + new MM::ActionLambda([this, connNo, feature, + name](MM::PropertyBase* pProp, + MM::ActionType eAct) { if (eAct == MM::BeforeGet) { short err{}; const unsigned value = @@ -547,8 +538,8 @@ class DCCDCUModuleDevice : public CGenericBase> { const std::string& name) { this->CreateStringProperty( name.c_str(), "Off", false, - new ActionLambda([this, connNo](MM::PropertyBase* pProp, - MM::ActionType eAct) { + new MM::ActionLambda([this, connNo](MM::PropertyBase* pProp, + MM::ActionType eAct) { // There is no readout for enable_outputs, so we rely on the // last-set value. if (eAct == MM::AfterSet) { @@ -577,8 +568,8 @@ class DCCDCUModuleDevice : public CGenericBase> { void CreateEnableAllOutputsProperty() { this->CreateStringProperty( "EnableOutputs", "Off", false, - new ActionLambda([this](MM::PropertyBase* pProp, - MM::ActionType eAct) { + new MM::ActionLambda([this](MM::PropertyBase* pProp, + MM::ActionType eAct) { // There is no readout for enable_outputs, so we rely on the // last-set value. if (eAct == MM::AfterSet) { @@ -609,8 +600,8 @@ class DCCDCUModuleDevice : public CGenericBase> { const std::string& name) { this->CreateStringProperty( name.c_str(), "", false, - new ActionLambda([this, connNo](MM::PropertyBase* pProp, - MM::ActionType eAct) { + new MM::ActionLambda([this, connNo](MM::PropertyBase* pProp, + MM::ActionType eAct) { if (eAct == MM::AfterSet) { std::string propVal; pProp->Get(propVal); @@ -634,8 +625,8 @@ class DCCDCUModuleDevice : public CGenericBase> { void CreateClearAllOverloadsProperty() { this->CreateStringProperty( "ClearOverloads", "", false, - new ActionLambda([this](MM::PropertyBase* pProp, - MM::ActionType eAct) { + new MM::ActionLambda([this](MM::PropertyBase* pProp, + MM::ActionType eAct) { if (eAct == MM::AfterSet) { std::string propVal; pProp->Get(propVal); @@ -660,8 +651,8 @@ class DCCDCUModuleDevice : public CGenericBase> { const std::string& name) { this->CreateStringProperty( name.c_str(), "No", true, - new ActionLambda([this, connNo](MM::PropertyBase* pProp, - MM::ActionType eAct) { + new MM::ActionLambda([this, connNo](MM::PropertyBase* pProp, + MM::ActionType eAct) { if (eAct == MM::BeforeGet) { short err{}; const bool flag = module_->IsOverloaded(connNo, err); @@ -691,8 +682,8 @@ class DCCDCUModuleDevice : public CGenericBase> { const std::string& name) { this->CreateStringProperty( name.c_str(), "No", true, - new ActionLambda([this, connNo](MM::PropertyBase* pProp, - MM::ActionType eAct) { + new MM::ActionLambda([this, connNo](MM::PropertyBase* pProp, + MM::ActionType eAct) { if (eAct == MM::BeforeGet) { short err{}; const bool flag =