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
81 template<typename SDS_T> class Parameter {
82
83 private:
84
85 /*
86 * Pointer to the DRAMA task this parameter is part of.
87 */
88 std::weak_ptr<Task> _theTask;
89 const std::string _name;
90 public:
103 Parameter(std::weak_ptr<Task> task,
104 const std::string &name,
105 const SDS_T &initVal) : _theTask(task), _name(name) {
106 //SdsCodeType code = SdsTypes::CodeForType<SDS_T>();
107
108 /*
109 * Access the parameter system and insert the value.
110 */
112 parSys.Put(name, initVal);
113 }
122
123 // Parameter updates trigger monitors and possible entry to
124 // task, so must take lock.
125 Task::guardType DramaLock(std::shared_ptr<Task>(_theTask)->Lock());
126
127 // Fill in code to set value.
129 Sdp::Put(_name, val, &status);
131 if (status != STATUS__OK)
132 DramaTHROW_S(status,"Failed setting parameter %",
133 _name);
134
135 return *this;
136 }
141 operator SDS_T() const {
142 SDS_T val;
144 Sdp::Get(_name, &val, &status);
145
146 if (status != STATUS__OK)
147 DramaTHROW_S(status,"Failed fetching parameter %",
148 _name);
149
150 return val;
151 }
158 virtual ~Parameter() {
159 }
160
170 template<typename T>
171 friend bool operator==(T&& lhs, const Parameter& p)
172 {
173 return (p.operator SDS_T() == lhs);
174 }
175
183 template<typename T>
184 bool operator==(T&& rhs) const
186 return (this->operator SDS_T() == rhs);
187 }
188
198 template<typename T>
199 friend bool operator!=(T&& lhs, const Parameter& p)
200 {
201 return (p.operator SDS_T() != lhs);
202 }
203
212 template<typename T>
213 bool operator!=(T&& rhs) const
214 {
215 return (this->operator SDS_T() != rhs);
216 }
217
218
219 };
220
221
256 /*
257 * Most of this specialization is implemented in parameters.cpp, mainly
258 * to avoid this file getting to large for a rarely used feature.
259 */
260
261 template<> class Parameter<drama::sds::Id> {
262
263 private:
264 /*
265 * Pointer to the DRAMA task this parameter is part of.
266 */
267 std::weak_ptr<Task> _theTask;
268 const std::string _name; // Name of this parameter.
269 sds::Id _parSys; // Reference to task parameter system.
270 public:
273 typedef Parameter<drama::sds::Id> class_type;
285 Parameter(std::weak_ptr<Task> task,
286 const std::string &name,
287 const sds::IdPtr &initVal,
288 bool copy = true);
289
310 void Set(const sds::IdPtr &newVal,
311 bool copy = true,
312 bool create = false);
313
327 sds::Id Get() const;
328
336 void UpdateMonitors() const;
344 virtual ~Parameter();
345 };
346
381 template<typename SDS_T> class ArrayParameter {
382
383 private:
384
385 /*
386 * Pointer to the DRAMA task this parameter is part of.
387 */
388 std::weak_ptr<Task> _theTask;
389 const std::string _name;
390 sds::Id _parSys;
391 public:
407 ArrayParameter(std::weak_ptr<Task> task,
408 const std::string &name,
409 unsigned nElements,
410 const SDS_T initVal) : _theTask(task), _name(name) {
411 /*
412 * Access the parameter system
413 */
414 _parSys = sds::Id::CreateFromSdsIdType((long)(DitsGetParId()));
415 /*
416 * Create and insert the new parameter
417 *
418 * We don't bother keeping ID about, because it could be changed
419 * by other access to the parameter - we find it each time we want it.
420 */
421 _parSys.CreateChildArray(_name, sds::CodeForType<SDS_T>(), nElements);
422
423 /*
424 * Fill the array with the initial value. Don't update monitors, there
425 * can't be any at this point.
426 */
427 Fill(initVal, false);
428 }
439 template <typename F>
440 void Fill(const F filler, bool updateMonitors=true) {
441 // Need to find the parameter.
442 auto id = _parSys.Find(_name);
443
444 // Use the SDS array write helper to access the array.
446 id.ArrayAccess(&array);
447
448 auto count = array.Size();
449 for (unsigned i = 0 ; i < count ; ++i)
450 {
451 array[i] = filler;
452 }
453
454 if (updateMonitors)
455 {
456 /*
457 *Parameter updates trigger monitors and possible entry to
458 * task, so must take lock.
459 */
460 Task::guardType DramaLock(std::shared_ptr<Task>(_theTask)->Lock());
461
463 DitsMonitor(_name.c_str(),DITS_MON_TRUST,(SdsIdType)(id),&status);
464 if (status != STATUS__OK)
465 {
467 "Error filling array parameter %, DitsMonitor() failed",
468 _name);
469 }
470 }
471
472 }
487 template <class ContainerType>
488 void Set(const ContainerType &vals) {
489
490
491 // Need to find the parameter.
492 auto id = _parSys.Find(_name);
493
494 // Use the SDS array write helper to access the array.
495 sds::ArrayWriteHelper<SDS_T> array;
496 id.ArrayAccess(&array);
497
498 /*
499 * Get the parameter array size and then ensure we
500 * don't index past the container size.
501 */
502 auto count = array.Size();
503
504 if (vals.size() < count)
505 count = vals.size();
506
507 /*
508 * Assign the values
509 */
510 for (unsigned i = 0 ; i < count ; ++i)
511 {
512 array[i] = vals[i];
513 }
514
515 /*
516 *Parameter updates trigger monitors and possible entry to
517 * task, so must take lock.
518 */
519 Task::guardType DramaLock(std::shared_ptr<Task>(_theTask)->Lock());
520
522 DitsMonitor(_name.c_str(),DITS_MON_TRUST,(SdsIdType)(id),&status);
523 if (status != STATUS__OK)
524 {
526 "Error setting array parameter %, DitsMonitor() failed",
527 _name);
528 }
529 }
530
531 /*
532 * Return the value of an array parameter.
533 *
534 * @return A vector containing the values. The type of the vector
535 * elements will be SDS_T.
536 */
537 std::vector<SDS_T> Get() const {
538
539
540 // Need to find the parameter.
541 auto id = _parSys.Find(_name);
542
543 // Access the SDS array for read.
544 sds::ArrayReadHelper<SDS_T> array;
545 id.ArrayAccess(&array);
546
547 auto count = array.Size();
548 std::vector<SDS_T> result;
549 result.resize(count);
550 /*
551 * copy the values.
552 */
553 for (unsigned i = 0; i < count ; ++i)
554 {
555 result[i] = array[i];
556 }
557 return result;
558
559 }
560
578 void Set(size_t index, SDS_T val, bool updateMonitors = true) {
579
580
581 // Need to find the parameter.
582 auto id = _parSys.Find(_name);
583
584 // Use the SDS array write helper to access the array.
585 sds::ArrayWriteHelper<SDS_T> array;
586 id.ArrayAccess(&array);
587
588 if (index >= array.Size())
589 {
591 "Tired to set index % in array parameter is size %",
592 index, array.Size());
593
594 }
595 array[index] = val;
596
597 /*
598 * If requested, update any parameter monitors.
599 */
600 if (updateMonitors)
601 {
602 /*
603 *Parameter updates trigger monitors and possible entry to
604 * task, so must take lock.
605 */
606 Task::guardType DramaLock(std::shared_ptr<Task>(_theTask)->Lock());
607
609 DitsMonitor(_name.c_str(),DITS_MON_TRUST,(SdsIdType)(id),&status);
610 if (status != STATUS__OK)
611 {
613 "Error setting array parameter %, DitsMonitor() failed",
614 _name);
615 }
616 }
617 }
618
629 SDS_T Get(size_t index) const {
630
631
632 // Need to find the parameter.
633 auto id = _parSys.Find(_name);
634
635 // Access the SDS array for read.
636 sds::ArrayReadHelper<SDS_T> array;
637 id.ArrayAccess(&array);
638
639 if (index >= array.Size())
640 {
642 "Tired to set index % in array parameter is size %",
643 index, array.Size());
644
645 }
646 return array[index];
647 }
648
649
650
651 /* Return the size of the array
652 *
653 * @warning Not very efficient since it must presume the parameter
654 * has changed in various ways and hence finds the parameter
655 * ID and does a full inquiry for every call.
657 * @return The size of the array.
658 */
659 unsigned Size() const {
660
661 // Need to find the parameter.
662 auto id = _parSys.Find(_name);
663
664 std::vector<unsigned> dims;
665 id.GetDims(&dims);
666
667 if (dims.size() != 1)
668 {
670 "Dimensions of array parameter is NOT 1. Can only use drama::ArrayParameter for single dimension array parameters");
671 }
672 return dims[0];
673
674 }
675
682 virtual ~ArrayParameter() {
683
684
685
686
687 }
688
703 SDS_T operator[](size_t index) const {
704
705 return Get(index);
706
707 }
708
709 }; // class ArrayParameter
710
744 /*
745 * Most of this specialization is implemented in parameters.cpp, mainly
746 * to avoid this file getting to large for a rarely used feature.
747 */
748 template<> class ArrayParameter<std::string> {
749
750 private:
751
752 /*
753 * Pointer to the DRAMA task this parameter is part of.
754 */
755 std::weak_ptr<Task> _theTask;
756 const std::string _name;
757 sds::Id _parSys;
758 public:
775 ArrayParameter(std::weak_ptr<Task> task,
776 const std::string &name,
777 unsigned nElements,
778 unsigned strLen=100,
779 const std::string initVal="");
787 void Fill(const std::string &filler, bool updateMonitors=true);
805 template <class ContainerType,
806 /*
807 * This complicated bit of code is about ensuring that only containers containing
808 * a sub-class of std::string are considered when trying to determine if
809 * this template function is a valid specialization to use.
810 *
811 * A relevant reference is SFINAE ("Substitution Failure Is Not An Error")
812 * E.g. http://en.cppreference.com/w/cpp/language/sfinae
813 *
814 * The problem we are tying to solve is that without this, any type
815 * could trigger this specialization. If for example var.Set(2, "ten"); was
816 * invoked, without this, it would try to specialize this template to see
817 * if it was a possible overload for the other Set method below. Compilation
818 * would then fail when .size() is invoked.
819 *
820 * std::enable_if is being used to this template is only used when the
821 * ContainerType value is a sub-class of std::string. The following
822 * references will help explain this:
823 * http://www.cplusplus.com/reference/type_traits/enable_if/?kw=enable_if
824 * http://www.boost.org/doc/libs/1_45_0/libs/utility/enable_if.html
825 *
826 * In addition, the use of "typename ContainerType::value_type" to ensure
827 * we refer to the actual type of the ContainerType template argument.
828 * This should also trigger a failure if the container does not have a
829 * value_type member. Here typename can be used to declare that a
830 * dependent name is a type.
831 */
832 typename std::enable_if<std::is_base_of<std::string,
833 typename ContainerType::value_type>::value>::type* = nullptr>
834
835 void Set(const ContainerType &vals, bool updateMonitors=true) {
836
837 // Need to find the parameter.
838 auto id = _parSys.Find(_name);
839
840 // Access data for write.
841 std::vector<unsigned long> dims;
843 id.ArrayAccess(&array, 2, &dims);
844
845 /*
846 * Validate we have a two dimensional array
847 */
848 if (dims.size() != 2)
849 {
851 "Dimensions of string array parameter is NOT 2. Can only use drama::ArrayParameter<std::string> for two dimension array parameters");
852 }
853
854 /*
855 * Get the parameter array size and then ensure we
856 * do not index past the container size.
857 */
858 auto count = dims[1];
859 if (vals.size() < count)
860 count = vals.size();
861 /*
862 * Access the parameter raw data array of the parameter so we
863 * can copy it in.
864 */
865 char *parData = (char *)array.DataAddress();
866 /*
867 * Length of each individual string parameter.
868 */
869 unsigned sLen = dims[0];
870 /*
871 * Number of values to transfer, the min of the parameter or
872 * what was supplied.
873 */
874 unsigned nVals = dims[1];
875
876 if (nVals > vals.size())
877 nVals = vals.size();
878
879 /*
880 * Assign the values to the elements.
881 */
882 for (unsigned i = 0 ; i < nVals ; ++i)
883 {
884 char *thisElement = (&parData[i*sLen]);
885 // Copy the new value. Must limit the length to the space available.
887 // Ensure null termination.
888 thisElement[sLen-1] = '\0';
889 }
890 if (updateMonitors)
891 {
892 /*
893 *Parameter updates trigger monitors and possible entry to
894 * task, so must take lock.
895 */
896 Task::guardType DramaLock(std::shared_ptr<Task>(_theTask)->Lock());
897
899 DitsMonitor(_name.c_str(),DITS_MON_TRUST,(SdsIdType)(id),&status);
900 if (status != STATUS__OK)
901 {
903 "Error setting array parameter %, DitsMonitor() failed",
904 _name);
905 }
906 }
907 }
908
909 /*
910 * Return the value of an array parameter.
911 *
912 * @return A vector containing the values. The type of the vector
913 * elements will be SDS_T.
914 */
915 std::vector<std::string> Get() const;
916
934 void Set(size_t index, const std::string &val, bool updateMonitors = true);
945 std::string Get(size_t index) const;
946
947
948 /* Return the size of the array
949 *
950 * This returns the number of elements, does not provide the
951 * length of each element.
952 *
953 * @warning Not very efficient since it must presume the parameter
954 * has changed in various ways and hence finds the parameter
955 * ID and does a full inquiry for every call.
956 *
957 * @return The size of the array.
958 */
959 virtual unsigned Size() const;
960
961 /* Return the maximum size of each string in the array.
962 *
963 * This returns the size of each string.
964 *
965 * @warning Not very efficient since it must presume the parameter
966 * has changed in various ways and hence finds the parameter
967 * ID and does a full inquiry for every call.
968 *
969 * @return The maximum size of each string within the array, including
970 * a null terminator.
971 */
972 virtual unsigned Strlen() const;
973
980 virtual ~ArrayParameter();
981
996 virtual std::string operator[](size_t index) const {
997
998 return Get(index);
999
1000 }
1001
1002 }; // class ArrayParameter<std::string>
1003
1004
1005 /*
1006 * Support writing to streams.
1008 template<typename SDS_T> std::ostream& operator<<(std::ostream& os, const Parameter<SDS_T>& p) {
1009 os << p.operator SDS_T();
1010 return os;
1011 }
1012
1013 template<> std::ostream& operator<<(std::ostream& os, const Parameter<sds::Id>& p) ;
1014
1015
1016 template<> std::ostream& operator<<(std::ostream& os, const Parameter<std::string>& p);
1017
1018
1019
1020} // namespace drama
1021
1022#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:862
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:1023
virtual ~ArrayParameter()
Array Parameter Destructor.
Definition parameter.hh:709
void Set(const ContainerType &vals)
Set the value of the parameter to the specified value.
Definition parameter.hh:515
void Fill(const F filler, bool updateMonitors=true)
Fill the array parameter value with a fixed value for all elements.
Definition parameter.hh:467
SDS_T operator[](size_t index) const
Return a single item from the Array parameter.
Definition parameter.hh:730
SDS_T Get(size_t index) const
Return a single value from an array parameter.
Definition parameter.hh:656
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:434
void Set(size_t index, SDS_T val, bool updateMonitors=true)
Set the value of the parameter to the specified value.
Definition parameter.hh:605
The class ArrayParameter is used to implement DRAMA parameters containing arrays of primitive items (...
Definition parameter.hh:408
virtual ~Parameter()
Parameter Destructor.
Parameter< drama::sds::Id > class_type
The type of this template instantiation.
Definition parameter.hh:300
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:148
bool operator==(T &&rhs) const
Overload the == operator.
Definition parameter.hh:211
virtual ~Parameter()
Parameter Destructor.
Definition parameter.hh:185
friend bool operator==(T &&lhs, const Parameter &p)
Overload the == operator.
Definition parameter.hh:198
Parameter< SDS_T > class_type
The type of this template instantiation.
Definition parameter.hh:120
bool operator!=(T &&rhs) const
Overload the != operator.
Definition parameter.hh:240
Parameter(std::weak_ptr< Task > task, const std::string &name, const SDS_T &initVal)
Construct a parameter of a given name.
Definition parameter.hh:130
friend bool operator!=(T &&lhs, const Parameter &p)
Overload the != operator.
Definition parameter.hh:226
The class Parameter is used to implement DRAMA parameters containing primitive items.
Definition parameter.hh:108
std::lock_guard< mutexType > guardType
Defines the type of a lock guard using our mutex type.
Definition task.hh:460
unsigned long Size() const
Return the number of elements in the array.
Definition sdsarray.hh:267
Helper class for reading data from SDS Scalar Arrays.
Definition sdsarray.hh:385
T * DataAddress()
Access the data directly.
Definition sdsarray.hh:350
Helper class for writing data to SDS Scalar Arrays.
Definition sdsarray.hh:303
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:2506
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:1705
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:940
A C++ Interface to the handling SDS structures.
Definition sds.hh:428
#define DramaTHROW_S(status_, format_,...)
Throw a Drama exception with safe string formatting.
Definition exception.hh:114
std::ostream & operator<<(std::ostream &strm, const drama::Exception &e)
drama::Exception stream output operator
Definition exception.hh:617
#define DramaTHROW(status_, message_)
Throw a Drama exception.
Definition exception.hh:93
std::shared_ptr< Id > IdPtr
A shared pointer for sds::Id items.
Definition sds.hh:3318
void CreateRunDramaTask()
Create and run a DRAMA task, with standard exception handling.
Definition task.hh:1322
The drama namespace contains all the classes, types etc of the DRAMA 2 implementation.
Definition drama.hh:93
DRAMA 2 include file - Sds class definition.
DRAMA 2 include file - Task class definition.