AAO DRAMA/DRAMA2 C++ Interface
DRAMA C++11 and later interface
parameter.hh
Go to the documentation of this file.
1#ifndef _DRAMA2_PARAMETER_INC
2#define _DRAMA2_PARAMETER_INC
3
20/*
21 * History:
22 * 07-Jan-2014 - TJF - Original version'
23 * 21-Jun-2015 - TJF - the examples in the comments should use "TaskPtr()"
24 * rather then "this".
25 * 09-Dec-2016 - TJF - Code from Minh for ostream<< operator and equality
26 * operators.
27 *
28 * The above ID is for Doxygen, this one has the format ACMM i`s looking for.
29 * "@(#) $Id$"
30*/
31
32#include "drama/task.hh"
33#include "drama/sds.hh"
34#include <string>
35#include "Sdp.h"
36#include "DitsParam.h"
37#include "DitsMonitor.h"
38
39#include <iostream>
40#include <type_traits> // for enable_if and is_base_of.
41
42namespace drama {
43
44
80 template<typename SDS_T> class Parameter {
81
82 private:
83
84 /*
85 * Pointer to the DRAMA task this parameter is part of.
86 */
87 std::weak_ptr<Task> _theTask;
88 const std::string _name;
89 public:
102 Parameter(std::weak_ptr<Task> task,
103 const std::string &name,
104 const SDS_T &initVal) : _theTask(task), _name(name) {
105 //SdsCodeType code = SdsTypes::CodeForType<SDS_T>();
106
107 /*
108 * Access the parameter system and insert the value.
109 */
111 parSys.Put(name, initVal);
112 }
121
122 // Parameter updates trigger monitors and possible entry to
123 // task, so must take lock.
124 Task::guardType DramaLock(std::shared_ptr<Task>(_theTask)->Lock());
125
126 // Fill in code to set value.
128 Sdp::Put(_name, val, &status);
130 if (status != STATUS__OK)
131 DramaTHROW_F(status,"Failed setting parameter {0}",
132 _name);
133
134 return *this;
135 }
140 operator SDS_T() const {
141 SDS_T val;
143 Sdp::Get(_name, &val, &status);
144
145 if (status != STATUS__OK)
146 DramaTHROW_F(status,"Failed fetching parameter {0}",
147 _name);
148
149 return val;
150 }
157 virtual ~Parameter() {
158 }
159
169 template<typename T>
170 friend bool operator==(T&& lhs, const Parameter& p)
171 {
172 return (p.operator SDS_T() == lhs);
173 }
174
182 template<typename T>
183 bool operator==(T&& rhs) const
185 return (this->operator SDS_T() == rhs);
186 }
187
197 template<typename T>
198 friend bool operator!=(T&& lhs, const Parameter& p)
199 {
200 return (p.operator SDS_T() != lhs);
201 }
202
211 template<typename T>
212 bool operator!=(T&& rhs) const
213 {
214 return (this->operator SDS_T() != rhs);
215 }
216
217
218 }; //template<typename SDS_T> class Parameter
219
220 /*
221 * @brief Support formatting a Parameter as per the underlying type - Scalar/string types.
222 *
223 * This function Allows fmt::format to work with the Scalar/String Parameter type items.
224 *
225 * You can use any of the fmt::format specifiers that are allowed for
226 * the underlying type.
227 *
228 * @param[in] t The Parameter item you wish to format.
229 *
230 * @tparam SDS_T Underlying SDS scalar type or string.
231 *
232 * @return t converted to to the underling thype.
233 */
234 template <typename SDS_T>
235 auto format_as(Parameter<SDS_T> t) { return static_cast<SDS_T>(t); }
236
271 /*
272 * Most of this specialization is implemented in parameters.cpp, mainly
273 * to avoid this file getting to large for a rarely used feature.
274 */
275
276 template<> class Parameter<drama::sds::Id> {
277
278 private:
279 /*
280 * Pointer to the DRAMA task this parameter is part of.
281 */
282 std::weak_ptr<Task> _theTask;
283 const std::string _name; // Name of this parameter.
284 sds::Id _parSys; // Reference to task parameter system.
285 public:
300 Parameter(std::weak_ptr<Task> task,
301 const std::string &name,
302 const sds::IdPtr &initVal,
303 bool copy = true);
304
325 void Set(const sds::IdPtr &newVal,
326 bool copy = true,
327 bool create = false);
328
342 sds::Id Get() const;
343
351 void UpdateMonitors() const;
359 virtual ~Parameter();
360 }; // template<> class Parameter<drama::sds::Id>
361
394 template<typename SDS_T> class ArrayParameter {
395
396 private:
397
398 /*
399 * Pointer to the DRAMA task this parameter is part of.
400 */
401 std::weak_ptr<Task> _theTask;
402 const std::string _name;
403 sds::Id _parSys;
404 public:
420 ArrayParameter(std::weak_ptr<Task> task,
421 const std::string &name,
422 unsigned nElements,
423 const SDS_T initVal) : _theTask(task), _name(name) {
424 /*
425 * Access the parameter system
426 */
427 _parSys = sds::Id::CreateFromSdsIdType((long)(DitsGetParId()));
428 /*
429 * Create and insert the new parameter
430 *
431 * We don't bother keeping ID about, because it could be changed
432 * by other access to the parameter - we find it each time we want it.
433 */
434 _parSys.CreateChildArray(_name, sds::CodeForType<SDS_T>(), nElements);
435
436 /*
437 * Fill the array with the initial value. Don't update monitors, there
438 * can't be any at this point.
439 */
440 Fill(initVal, false);
441 }
452 template <typename F>
453 void Fill(const F filler, bool updateMonitors=true) {
454 // Need to find the parameter.
455 auto id = _parSys.Find(_name);
456
457 // Use the SDS array write helper to access the array.
459 id.ArrayAccess(&array);
460
461 auto count = array.Size();
462 for (unsigned i = 0 ; i < count ; ++i)
463 {
464 array[i] = filler;
465 }
466
467 if (updateMonitors)
468 {
469 /*
470 *Parameter updates trigger monitors and possible entry to
471 * task, so must take lock.
472 */
473 Task::guardType DramaLock(std::shared_ptr<Task>(_theTask)->Lock());
474
476 DitsMonitor(_name.c_str(),DITS_MON_TRUST,(SdsIdType)(id),&status);
477 if (status != STATUS__OK)
478 {
480 "Error filling array parameter {0}, DitsMonitor() failed",
481 _name);
482 }
483 }
484
485 }
500 template <class ContainerType>
501 void Set(const ContainerType &vals) {
502
503
504 // Need to find the parameter.
505 auto id = _parSys.Find(_name);
506
507 // Use the SDS array write helper to access the array.
508 sds::ArrayWriteHelper<SDS_T> array;
509 id.ArrayAccess(&array);
510
511 /*
512 * Get the parameter array size and then ensure we
513 * don't index past the container size.
514 */
515 auto count = array.Size();
516
517 if (vals.size() < count)
518 count = vals.size();
519
520 /*
521 * Assign the values
522 */
523 for (unsigned i = 0 ; i < count ; ++i)
524 {
525 array[i] = vals[i];
526 }
527
528 /*
529 *Parameter updates trigger monitors and possible entry to
530 * task, so must take lock.
531 */
532 Task::guardType DramaLock(std::shared_ptr<Task>(_theTask)->Lock());
533
535 DitsMonitor(_name.c_str(),DITS_MON_TRUST,(SdsIdType)(id),&status);
536 if (status != STATUS__OK)
537 {
539 "Error setting array parameter {0}, DitsMonitor() failed",
540 _name);
541 }
542 }
543
544 /*
545 * Return the value of an array parameter.
546 *
547 * @return A vector containing the values. The type of the vector
548 * elements will be SDS_T.
549 */
550 std::vector<SDS_T> Get() const {
551
552
553 // Need to find the parameter.
554 auto id = _parSys.Find(_name);
555
556 // Access the SDS array for read.
557 sds::ArrayReadHelper<SDS_T> array;
558 id.ArrayAccess(&array);
559
560 auto count = array.Size();
561 std::vector<SDS_T> result;
562 result.resize(count);
563 /*
564 * copy the values.
565 */
566 for (unsigned i = 0; i < count ; ++i)
567 {
568 result[i] = array[i];
569 }
570 return result;
571
572 }
573
591 void Set(size_t index, SDS_T val, bool updateMonitors = true) {
592
593
594 // Need to find the parameter.
595 auto id = _parSys.Find(_name);
596
597 // Use the SDS array write helper to access the array.
598 sds::ArrayWriteHelper<SDS_T> array;
599 id.ArrayAccess(&array);
600
601 if (index >= array.Size())
602 {
604 "Tired to set index {0} in array parameter is size {1}",
605 index, array.Size());
606
607 }
608 array[index] = val;
609
610 /*
611 * If requested, update any parameter monitors.
612 */
613 if (updateMonitors)
614 {
615 /*
616 *Parameter updates trigger monitors and possible entry to
617 * task, so must take lock.
618 */
619 Task::guardType DramaLock(std::shared_ptr<Task>(_theTask)->Lock());
620
622 DitsMonitor(_name.c_str(),DITS_MON_TRUST,(SdsIdType)(id),&status);
623 if (status != STATUS__OK)
624 {
626 "Error setting array parameter {0}, DitsMonitor() failed",
627 _name);
628 }
629 }
630 }
631
642 SDS_T Get(size_t index) const {
643
644
645 // Need to find the parameter.
646 auto id = _parSys.Find(_name);
647
648 // Access the SDS array for read.
649 sds::ArrayReadHelper<SDS_T> array;
650 id.ArrayAccess(&array);
651
652 if (index >= array.Size())
653 {
655 "Tired to set index {0} in array parameter is size {1}",
656 index, array.Size());
657
658 }
659 return array[index];
660 }
661
662
663
664 /* Return the size of the array
665 *
666 * @warning Not very efficient since it must presume the parameter
667 * has changed in various ways and hence finds the parameter
668 * ID and does a full inquiry for every call.
670 * @return The size of the array.
671 */
672 unsigned Size() const {
673
674 // Need to find the parameter.
675 auto id = _parSys.Find(_name);
676
677 std::vector<unsigned> dims;
678 id.GetDims(&dims);
679
680 if (dims.size() != 1)
681 {
683 "Dimensions of array parameter is NOT 1. Can only use drama::ArrayParameter for single dimension array parameters");
684 }
685 return dims[0];
686
687 }
688
695 virtual ~ArrayParameter() {
696 }
697
712 SDS_T operator[](size_t index) const {
713
714 return Get(index);
715
716 }
717
718 }; // template<typename SDS_T> class ArrayParameter
719
753 /*
754 * Most of this specialization is implemented in parameters.cpp, mainly
755 * to avoid this file getting to large for a rarely used feature.
756 */
757 template<> class ArrayParameter<std::string> {
758
759 private:
760
761 /*
762 * Pointer to the DRAMA task this parameter is part of.
763 */
764 std::weak_ptr<Task> _theTask;
765 const std::string _name;
766 sds::Id _parSys;
767 public:
784 ArrayParameter(std::weak_ptr<Task> task,
785 const std::string &name,
786 unsigned nElements,
787 unsigned strLen=100,
788 const std::string initVal="");
796 void Fill(const std::string &filler, bool updateMonitors=true);
814 template <class ContainerType,
815 /*
816 * This complicated bit of code is about ensuring that only containers containing
817 * a sub-class of std::string are considered when trying to determine if
818 * this template function is a valid specialization to use.
819 *
820 * A relevant reference is SFINAE ("Substitution Failure Is Not An Error")
821 * E.g. http://en.cppreference.com/w/cpp/language/sfinae
822 *
823 * The problem we are tying to solve is that without this, any type
824 * could trigger this specialization. If for example var.Set(2, "ten"); was
825 * invoked, without this, it would try to specialize this template to see
826 * if it was a possible overload for the other Set method below. Compilation
827 * would then fail when .size() is invoked.
828 *
829 * std::enable_if is being used to this template is only used when the
830 * ContainerType value is a sub-class of std::string. The following
831 * references will help explain this:
832 * http://www.cplusplus.com/reference/type_traits/enable_if/?kw=enable_if
833 * http://www.boost.org/doc/libs/1_45_0/libs/utility/enable_if.html
834 *
835 * In addition, the use of "typename ContainerType::value_type" to ensure
836 * we refer to the actual type of the ContainerType template argument.
837 * This should also trigger a failure if the container does not have a
838 * value_type member. Here typename can be used to declare that a
839 * dependent name is a type.
840 */
841 typename std::enable_if<std::is_base_of<std::string,
842 typename ContainerType::value_type>::value>::type* = nullptr>
843
844 void Set(const ContainerType &vals, bool updateMonitors=true) {
845
846 // Need to find the parameter.
847 auto id = _parSys.Find(_name);
848
849 // Access data for write.
850 std::vector<unsigned long> dims;
852 id.ArrayAccess(&array, 2, &dims);
853
854 /*
855 * Validate we have a two dimensional array
856 */
857 if (dims.size() != 2)
858 {
860 "Dimensions of string array parameter is NOT 2. Can only use drama::ArrayParameter<std::string> for two dimension array parameters");
861 }
862
863 /*
864 * Get the parameter array size and then ensure we
865 * do not index past the container size.
866 */
867 auto count = dims[1];
868 if (vals.size() < count)
869 count = vals.size();
870 /*
871 * Access the parameter raw data array of the parameter so we
872 * can copy it in.
873 */
874 char *parData = (char *)array.DataAddress();
875 /*
876 * Length of each individual string parameter.
877 */
878 unsigned sLen = dims[0];
879 /*
880 * Number of values to transfer, the min of the parameter or
881 * what was supplied.
882 */
883 unsigned nVals = dims[1];
884
885 if (nVals > vals.size())
886 nVals = vals.size();
887
888 /*
889 * Assign the values to the elements.
890 */
891 for (unsigned i = 0 ; i < nVals ; ++i)
892 {
893 char *thisElement = (&parData[i*sLen]);
894 // Copy the new value. Must limit the length to the space available.
896 // Ensure null termination.
897 thisElement[sLen-1] = '\0';
898 }
899 if (updateMonitors)
900 {
901 /*
902 *Parameter updates trigger monitors and possible entry to
903 * task, so must take lock.
904 */
905 Task::guardType DramaLock(std::shared_ptr<Task>(_theTask)->Lock());
906
908 DitsMonitor(_name.c_str(),DITS_MON_TRUST,(SdsIdType)(id),&status);
909 if (status != STATUS__OK)
910 {
912 "Error setting array parameter {0}, DitsMonitor() failed",
913 _name);
914 }
915 }
916 }
917
918 /*
919 * Return the value of an array parameter.
920 *
921 * @return A vector containing the values. The type of the vector
922 * elements will be SDS_T.
923 */
924 std::vector<std::string> Get() const;
925
943 void Set(size_t index, const std::string &val, bool updateMonitors = true);
954 std::string Get(size_t index) const;
955
956
957 /* Return the size of the array
958 *
959 * This returns the number of elements, does not provide the
960 * length of each element.
961 *
962 * @warning Not very efficient since it must presume the parameter
963 * has changed in various ways and hence finds the parameter
964 * ID and does a full inquiry for every call.
965 *
966 * @return The size of the array.
967 */
968 virtual unsigned Size() const;
969
970 /* Return the maximum size of each string in the array.
971 *
972 * This returns the size of each string.
973 *
974 * @warning Not very efficient since it must presume the parameter
975 * has changed in various ways and hence finds the parameter
976 * ID and does a full inquiry for every call.
977 *
978 * @return The maximum size of each string within the array, including
979 * a null terminator.
980 */
981 virtual unsigned Strlen() const;
982
989 virtual ~ArrayParameter();
990
1005 virtual std::string operator[](size_t index) const {
1006
1007 return Get(index);
1008
1009 }
1010
1011 }; // class ArrayParameter<std::string>
1012
1013
1014 /*
1015 * Support writing to streams.
1017 template<typename SDS_T> std::ostream& operator<<(std::ostream& os, const Parameter<SDS_T>& p) {
1018 os << p.operator SDS_T();
1019 return os;
1020 }
1021
1022 template<> std::ostream& operator<<(std::ostream& os, const Parameter<sds::Id>& p) ;
1023
1024
1025 template<> std::ostream& operator<<(std::ostream& os, const Parameter<std::string>& p);
1026
1027
1028
1029} // namespace drama
1030
1031#endif
std::string Get(size_t index) const
Return a single value from an array parameter.
virtual ~ArrayParameter()
Array Parameter Destructor.
void Set(const ContainerType &vals, bool updateMonitors=true)
Set the value of the parameter to the specified value.
Definition parameter.hh:871
ArrayParameter(std::weak_ptr< Task > task, const std::string &name, unsigned nElements, unsigned strLen=100, const std::string initVal="")
Construct a parameter of a given name which is an array of scalar items.
void Set(size_t index, const std::string &val, bool updateMonitors=true)
Set the value of the parameter to the specified value.
void Fill(const std::string &filler, bool updateMonitors=true)
Fill the array parameter value with a fixed value for all elements.
virtual std::string operator[](size_t index) const
Return a single item from the Array parameter.
Definition parameter.hh:1032
virtual ~ArrayParameter()
Array Parameter Destructor.
Definition parameter.hh:722
void Set(const ContainerType &vals)
Set the value of the parameter to the specified value.
Definition parameter.hh:528
void Fill(const F filler, bool updateMonitors=true)
Fill the array parameter value with a fixed value for all elements.
Definition parameter.hh:480
SDS_T operator[](size_t index) const
Return a single item from the Array parameter.
Definition parameter.hh:739
SDS_T Get(size_t index) const
Return a single value from an array parameter.
Definition parameter.hh:669
ArrayParameter(std::weak_ptr< Task > task, const std::string &name, unsigned nElements, const SDS_T initVal)
Construct a parameter of a given name which is an array of scalar items.
Definition parameter.hh:447
void Set(size_t index, SDS_T val, bool updateMonitors=true)
Set the value of the parameter to the specified value.
Definition parameter.hh:618
The class ArrayParameter is used to implement DRAMA parameters containing arrays of primitive items (...
Definition parameter.hh:421
virtual ~Parameter()
Parameter Destructor.
Parameter< drama::sds::Id > class_type
The type of this template instantiation.
Definition parameter.hh:315
void UpdateMonitors() const
Trigger any monitors of this parameter.
void Set(const sds::IdPtr &newVal, bool copy=true, bool create=false)
Set the value of this parameter.
Parameter(std::weak_ptr< Task > task, const std::string &name, const sds::IdPtr &initVal, bool copy=true)
Construct a parameter of a given name.
sds::Id Get() const
Access the parameter.
class_type & operator=(SDS_T val)
Set the value of the parameter to the specified value.
Definition parameter.hh:147
bool operator==(T &&rhs) const
Overload the == operator.
Definition parameter.hh:210
virtual ~Parameter()
Parameter Destructor.
Definition parameter.hh:184
friend bool operator==(T &&lhs, const Parameter &p)
Overload the == operator.
Definition parameter.hh:197
Parameter< SDS_T > class_type
The type of this template instantiation.
Definition parameter.hh:119
bool operator!=(T &&rhs) const
Overload the != operator.
Definition parameter.hh:239
Parameter(std::weak_ptr< Task > task, const std::string &name, const SDS_T &initVal)
Construct a parameter of a given name.
Definition parameter.hh:129
friend bool operator!=(T &&lhs, const Parameter &p)
Overload the != operator.
Definition parameter.hh:225
The class Parameter is used to implement DRAMA parameters.
Definition parameter.hh:107
std::lock_guard< mutexType > guardType
Defines the type of a lock guard using our mutex type.
Definition task.hh:471
unsigned long Size() const
Return the number of elements in the array.
Definition sdsarray.hh:269
Helper class for reading data from SDS Scalar Arrays.
Definition sdsarray.hh:387
T * DataAddress()
Access the data directly.
Definition sdsarray.hh:352
Helper class for writing data to SDS Scalar Arrays.
Definition sdsarray.hh:305
void ArrayAccess(ArrayAccessHelper< T > *const data) const
Access the data of a single dimensional SDS primitive array item of a specified number of elements.
Definition sds.hh:2673
virtual Id Find(const std::string &name, bool throwOnNotFound=true) const
Factory constructor method Constructor which returns a reference to a named item.
void GetDims(ContainerType *dims) const
Return the dimensions of the SDS item.
Definition sds.hh:1846
static Id CreateFromSdsIdType(const SdsIdType item, const bool free=false, const bool del=false, const bool readfree=false)
Factory constructor method that constructs an sds::Id item from an existing C language SDS id.
Id CreateChildArray(const std::string &name, const SdsCodeType code, const ContainerType &dims, const std::string &extra="") const
Factory constructor method Constructor which creates a new child item which is an multi-dimensional a...
Definition sds.hh:953
A C++ Interface to the handling SDS structures.
Definition sds.hh:428
#define DramaTHROW_F(status_, format_,...)
Throw a Drama exception with fmt::format string formatting.
Definition exception.hh:129
std::ostream & operator<<(std::ostream &strm, const drama::Exception &e)
drama::Exception stream output operator
Definition exception.hh:726
#define DramaTHROW(status_, message_)
Throw a Drama exception.
Definition exception.hh:90
std::shared_ptr< Id > IdPtr
A shared pointer for sds::Id items.
Definition sds.hh:3613
void CreateRunDramaTask()
Create and run a DRAMA task, with standard exception handling.
Definition task.hh:1339
The drama namespace contains all the classes, types etc of the DRAMA 2 implementation.
Definition drama.hh:99
DRAMA 2 include file - Sds class definition.
DRAMA 2 include file - Task class definition.