SVGHMI: Add inhibition to widget's apply_hmi_value() so that it does not change variable more frquently than given widget's frequency. This prevents flooding network with many update if browser is producing events at high rate, as for exemple when dragging ScrollBar's cursor. svghmi
authorEdouard Tisserant <edouard.tisserant@gmail.com>
Sun, 14 Feb 2021 05:22:30 +0100
branchsvghmi
changeset 3139 1f5ca646ce6e
parent 3138 1d724e8d5592
child 3140 cae53fe54cf2
SVGHMI: Add inhibition to widget's apply_hmi_value() so that it does not change variable more frquently than given widget's frequency. This prevents flooding network with many update if browser is producing events at high rate, as for exemple when dragging ScrollBar's cursor.
svghmi/widget_scrollbar.ysl2
svghmi/widgets_common.ysl2
--- a/svghmi/widget_scrollbar.ysl2	Sun Feb 14 05:17:25 2021 +0100
+++ b/svghmi/widget_scrollbar.ysl2	Sun Feb 14 05:22:30 2021 +0100
@@ -3,7 +3,7 @@
 template "widget[@type='ScrollBar']", mode="widget_class"{
     ||
     class ScrollBarWidget extends Widget{
-        frequency = 5;
+        frequency = 10;
         position = undefined;
         range = undefined;
         size = undefined;
--- a/svghmi/widgets_common.ysl2	Sun Feb 14 05:17:25 2021 +0100
+++ b/svghmi/widgets_common.ysl2	Sun Feb 14 05:22:30 2021 +0100
@@ -144,12 +144,23 @@
             this.indexes = indexes;
             this.minmaxes = minmaxes;
             Object.keys(members).forEach(prop => this[prop]=members[prop]);
+            this.lastapply = indexes.map(() => undefined);
+            this.inhibit = indexes.map(() => undefined);
+            this.pending = indexes.map(() => undefined);
+            this.bound_unhinibit = this.unhinibit.bind(this);
         }
 
         unsub(){
             /* remove subsribers */
             if(!this.unsubscribable)
                 for(let i = 0; i < this.indexes.length; i++) {
+                    /* flush updates pending because of inhibition */
+                    let inhibition = this.inhibit[index];
+                    if(inhibition != undefined){
+                        clearTimeout(inhibition);
+                        this.lastapply[index] = undefined;
+                        this.unhinibit(index);
+                    }
                     let index = this.indexes[i];
                     if(this.relativeness[i])
                         index += this.offset;
@@ -227,13 +238,41 @@
             return apply_hmi_value(realindex, new_val);
         }
 
-        apply_hmi_value(index, new_val) {
+        _apply_hmi_value(index, new_val) {
             let realindex = this.get_variable_index(index);
             if(realindex == undefined) return undefined;
             new_val = this.clip_min_max(index, new_val);
             return apply_hmi_value(realindex, new_val);
         }
 
+        unhinibit(index){
+            this.inhibit[index] = undefined;
+            let new_val = this.pending[index];
+            this.pending[index] = undefined;
+            return this.apply_hmi_value(index, new_val);
+        }
+
+        apply_hmi_value(index, new_val) {
+            if(this.inhibit[index] == undefined){
+                let now = Date.now();
+                let min_interval = 1000/this.frequency;
+                let lastapply = this.lastapply[index];
+                if(lastapply == undefined || now > lastapply + min_interval){
+                    this.lastapply[index] = now;
+                    return this._apply_hmi_value(index, new_val);
+                }
+                else {
+                    let elapsed = now - lastapply;
+                    this.pending[index] = new_val;
+                    this.inhibit[index] = setTimeout(this.bound_unhinibit, min_interval - elapsed, index);
+                }
+            }
+            else {
+                this.pending[index] = new_val;
+                return new_val;
+            }
+        }
+
         new_hmi_value(index, value, oldval) {
             // TODO avoid searching, store index at sub()
             for(let i = 0; i < this.indexes.length; i++) {