Add template functions assign_set/return_if_changed

Message ID 20230523071912.2197-1-tdevries@suse.de
State Superseded
Headers
Series Add template functions assign_set/return_if_changed |

Commit Message

Tom de Vries May 23, 2023, 7:19 a.m. UTC
  Add template function assign_set_if_changed in gdb/utils.h:
...
template<typename T>
void
assign_set_if_changed (T &lval, T val, bool &changed)
{
  if (lval == val)
    return;

  lval = val;
  changed = true;
}
...

This allows us to rewrite code like this:
...
  if (tui_border_attrs != entry->value)
    {
      tui_border_attrs = entry->value;
      need_redraw = true;
    }
...
into this:
...
  assign_set_if_changed<int> (tui_border_attrs, entry->value, need_redraw);
...

The name is a composition of its functionality:
- it assigns val to lval, and
- is sets changed to true if the assignment changed lval.

I've initially considered using assign_return_if_changed for the rewrite:
...
template<typename T>
bool
assign_return_if_changed (T &lval, T val)
{
  if (lval == val)
    return false;

  lval = val;
  changed = true;
}
...
but liked the resulting bitwise operator on the boolean a bit less:
...
  need_redraw |= assign_return_if_changed<int> (tui_border_attrs, entry->value);
...

I've included it anyway, it may be the preferred choice in other cases.

Tested on x86_64-linux.
---
 gdb/utils.c | 39 +++++++++++++++++++++++++++++++++++++++
 gdb/utils.h | 27 +++++++++++++++++++++++++++
 2 files changed, 66 insertions(+)


base-commit: e1eecd81cc6a40b3547a7c5d456919275a0b4a27
  

Comments

Lancelot SIX May 23, 2023, 9:57 a.m. UTC | #1
Hi Tom,

> I've initially considered using assign_return_if_changed for the rewrite:
> ...
> template<typename T>
> bool
> assign_return_if_changed (T &lval, T val)
> {
>   if (lval == val)
>     return false;
> 
>   lval = val;
>   changed = true;

This line should be "return true" (only the commit comment is affected,
the actual implementation is OK).

> }
> ...
> but liked the resulting bitwise operator on the boolean a bit less:
> ...
>   need_redraw |= assign_return_if_changed<int> (tui_border_attrs, entry->value);
> ...

I think I like it a bit more (not by far though), but I guess that is
just a personal preference ^_^.

> 
> I've included it anyway, it may be the preferred choice in other cases.
> 

Best,
Lancelot.
  
Tom de Vries May 23, 2023, 4:20 p.m. UTC | #2
On 5/23/23 11:57, Lancelot SIX wrote:
> Hi Tom,
> 
>> I've initially considered using assign_return_if_changed for the rewrite:
>> ...
>> template<typename T>
>> bool
>> assign_return_if_changed (T &lval, T val)
>> {
>>    if (lval == val)
>>      return false;
>>
>>    lval = val;
>>    changed = true;
> 
> This line should be "return true" (only the commit comment is affected,
> the actual implementation is OK).
> 

Thanks for spotting that, I've updated my patch.

>> }
>> ...
>> but liked the resulting bitwise operator on the boolean a bit less:
>> ...
>>    need_redraw |= assign_return_if_changed<int> (tui_border_attrs, entry->value);
>> ...
> 
> I think I like it a bit more (not by far though), but I guess that is
> just a personal preference ^_^.
> 

Thanks for that feedback, that's good to know, and I'm curious about 
opinions of other as well.

- Tom

>>
>> I've included it anyway, it may be the preferred choice in other cases.
>>
> 
> Best,
> Lancelot.
  
Tom de Vries June 8, 2023, 9:26 a.m. UTC | #3
On 5/23/23 18:20, Tom de Vries via Gdb-patches wrote:
> On 5/23/23 11:57, Lancelot SIX wrote:
>> Hi Tom,
>>
>>> I've initially considered using assign_return_if_changed for the 
>>> rewrite:
>>> ...
>>> template<typename T>
>>> bool
>>> assign_return_if_changed (T &lval, T val)
>>> {
>>>    if (lval == val)
>>>      return false;
>>>
>>>    lval = val;
>>>    changed = true;
>>
>> This line should be "return true" (only the commit comment is affected,
>> the actual implementation is OK).
>>
> 
> Thanks for spotting that, I've updated my patch.
> 
>>> }
>>> ...
>>> but liked the resulting bitwise operator on the boolean a bit less:
>>> ...
>>>    need_redraw |= assign_return_if_changed<int> (tui_border_attrs, 
>>> entry->value);
>>> ...
>>
>> I think I like it a bit more (not by far though), but I guess that is
>> just a personal preference ^_^.
>>
> 
> Thanks for that feedback, that's good to know, and I'm curious about 
> opinions of other as well.
> 

I've submitted a v2 ( 
https://sourceware.org/pipermail/gdb-patches/2023-June/200148.html ):
- now as patch series, also including a patch implementing the proposed
   rewrite in tui_update_variables
- it uses assign_return_if_changed, I've changed my mind about
   preferring assign_set_if_changed
- the commit message of the first patch has been updated to be more
   neutral
- I've dropped the actual implementation from the commit message.

Thanks,
- Tom
  

Patch

diff --git a/gdb/utils.c b/gdb/utils.c
index f18228d1086..46bfd9a5bbb 100644
--- a/gdb/utils.c
+++ b/gdb/utils.c
@@ -3631,6 +3631,43 @@  copy_bitwise (gdb_byte *dest, ULONGEST dest_offset,
     }
 }
 
+#if GDB_SELF_TEST
+static void
+test_assign_set_return_if_changed ()
+{
+  bool changed;
+  int a;
+
+  for (bool initial : { false, true })
+    {
+      changed = initial;
+      a = 1;
+      assign_set_if_changed (a, 1, changed);
+      SELF_CHECK (a == 1);
+      SELF_CHECK (changed == initial);
+    }
+
+  for (bool initial : { false, true })
+    {
+      changed = initial;
+      a = 1;
+      assign_set_if_changed (a, 2, changed);
+      SELF_CHECK (a == 2);
+      SELF_CHECK (changed == true);
+    }
+
+  a = 1;
+  changed = assign_return_if_changed (a, 1);
+  SELF_CHECK (a == 1);
+  SELF_CHECK (changed == false);
+
+  a = 1;
+  assign_set_if_changed (a, 2, changed);
+  SELF_CHECK (a == 2);
+  SELF_CHECK (changed == true);
+}
+#endif
+
 void _initialize_utils ();
 void
 _initialize_utils ()
@@ -3695,5 +3732,7 @@  When set, debugging messages will be marked with seconds and microseconds."),
   selftests::register_test ("strncmp_iw_with_mode",
 			    strncmp_iw_with_mode_tests);
   selftests::register_test ("pager", test_pager);
+  selftests::register_test ("assign_set_return_if_changed",
+			    test_assign_set_return_if_changed);
 #endif
 }
diff --git a/gdb/utils.h b/gdb/utils.h
index 00b123e6117..d78d54911bf 100644
--- a/gdb/utils.h
+++ b/gdb/utils.h
@@ -337,4 +337,31 @@  extern void copy_bitwise (gdb_byte *dest, ULONGEST dest_offset,
 
 extern int readline_hidden_cols;
 
+/* Assign VAL to LVAL, and set CHANGED to true if the assignment changed
+   LVAL.  */
+
+template<typename T>
+void
+assign_set_if_changed (T &lval, T val, bool &changed)
+{
+  if (lval == val)
+    return;
+
+  lval = val;
+  changed = true;
+}
+
+/* Assign VAL to LVAL, and return true if the assignment changed LVAL.  */
+
+template<typename T>
+bool
+assign_return_if_changed (T &lval, T val)
+{
+  if (lval == val)
+    return false;
+
+  lval = val;
+  return true;
+}
+
 #endif /* UTILS_H */