Library globals

Source frame_utils.nas

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
#---------------------------------------------------------------------------
#
#	Title                : Frame Utils
#
#	File Type            : Implementation File
#
#	Description          : Objects related to frame processing
#
#	Author               : Richard Harrison (richard@zaretto.com)
#
#	Creation Date        : 05-05-2019
#
#	Version              : 1.0
#
#  Copyright (C) 2019 Richard Harrison           Released under GPL V2
#
#---------------------------------------------------------------------------*/


#---------------------------------------------------------------------------*/
# Partition data and process
#
#    This manages the processing of data in a manner suitable for real time
#    operations.  Given a data array [0..size] this will process a number
#    of array elements each time it is called This allows for a simple way
#    to split up intensive processing across multiple frames.
#    
#    The limit is the number of elements to process per invocation or
#    a specific amount of time. 
#
#    To limit the amount of time requires a timestamp object to be set using 
#    the set_timestamp method and then to set the maximum amount of 
#    time (in microseconds) by calling set_max_time_usec. A value of 500us is
#    a good value to use - but it is upto the implementor to choose a value that
#    is suited to their environment
#
#    Usually one of more instances of this class will be contained within 
#    another object, however this will work equally well in global space.
#
# example usage (object);
# 
# var VSD_Device =
# {
#     new : func(designation, model_element, target_module_id, root_node)
#     {
# ...
#        obj.process_targets = PartitionProcessor.new("VSD-targets", 20, nil);
#        obj.process_targets.set_max_time_usec(500);
# ...
#      me.process_targets.set_timestamp(notification.Timestamp);
#
# then invoke.
#      me.process_targets.process(me, awg_9.tgts_list, 
#                                 func(pp, obj, data){
#                                     # initialisation; called before processing element[0]
#                                     # params
#                                     #  pp is the partition processor that called this
#                                     #  obj is the reference object (first argument in the .process)
#                                     #  data is the entire data array.
#                                 }
#                                 ,
#                                 func(pp, obj, element){
#                                     # proces individual element; 
#                                     # params
#                                     #  pp is the partition processor that called this
#                                     #  obj is the reference object (first argument in the .process)
#                                     #  element is the element data[pp.data_index]
#                                     # return 0 to stop processing any more elements and call the completed method
#                                     # return 1 to continue processing.
#                                 },
#                                 func(pp, obj, data)
#                                 {
#                                     # completed; called after the last element processed
#                                     # params
#                                     #  pp is the partition processor that called this
#                                     #  obj is the reference object (first argument in the .process)
#                                     #  data is the entire data array.
#                                 });

var PartitionProcessor = 
{
    debug_output : 0,

    new : func(_name, _size, _timestamp=nil){
        var obj = {
                   parents : [PartitionProcessor],
                   data_index : 0,
                   ppos : 0,
                   name : _name,
                   end : 0,
                   partition_size : _size,
                   timestamp : _timestamp,
                   max_time_usec : 0,
                  };
        return obj;
    },
    set_max_time_usec : func(_maxTimeUsec){
        me.max_time_usec = _maxTimeUsec;
    },
    set_timestamp : func(_timestamp){
        me.timestamp = _timestamp;
    },  
    process : func (object, data, init_method, process_method, complete_method){

        if (me.end != size(data)) {
            # data changed during processing restart at the beginning.
            me.data_index = 0;
        }

        if (me.data_index == 0) {
            me.end = size(data);
            init_method(me, object, data);
        }

        if (me.end == 0)
            return;

        me.start_pos = me.data_index;
        if (me.timestamp != nil and me.max_time_usec > 0) {
            me.start_time = me.timestamp.elapsedUSec();
            me.end_time = me.start_time + me.max_time_usec;
        } else {
            me.start_time = 0;
            me.end_time = 0;
        }

        for (me.ppos=0;me.ppos < me.partition_size; me.ppos  += 1) {
            if (me.data_index >= me.end) {
                complete_method(me, object, data);
                me.data_index = 0;
                return;
            }
            if (!process_method(me, object, data[me.data_index])) {
                complete_method(me, object, data);
                me.data_index = 0;
                return;            # halt processing requested.
            } else
                me.data_index += 1;

            if (me.data_index == me.start_pos) {
                complete_method(me, object, data);
                return;
            }

            if (me.end_time > 0 and me.timestamp.elapsedUSec() > me.end_time) {
                if (PartitionProcessor.debug_output)
                    printf("PartitionProcessor: [%s] out of time %dus (processed# %d)",me.name, me.timestamp.elapsedUSec() - me.start_time, me.ppos);
                return;
            }
        }
    },
};