www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Event struct via registers

reply Vitaliy Fadeev <vital.fadeev gmail.com> writes:


Pass the structure through registers ?



Wrap the registries in a structure ?



I need to pass different events: `Draw_Event`, 
`Mouse_Move_Event`, `...`
I need to pass an event to many objects: `foreach (o; world) 
o.event (e);`
I need speed.
I want to pass the structure in registers: (like __fastcall 
callin convention): `void _event (REG r1, REG r2, REG r3, REG 
r4);`. But it's hard to read.
I want comfortable use: (like a wrap registers in struct):
```
void
event (Event e) {
     writeln (e.type);
     writeln (e.code);
     writeln (e.value);
     switch (e.type) {
       case Type.REL: _rel_event (e); break;
       case Type.GUI: _gui_event (e); break;
       case Type.APP: _app_event (e); break;
       default:
     }
}
```

The problem is that the size of the structure is larger than the 
size of the register.

```
struct
Event {          //  64 bit
   ushort type;   //  16 bit
   ushort code;   //  16 bit
   uint   value;  //  32 bit
}
```

But the event size can be > 64 bit. More than register size.

```
struct
Mouse_Event {    // 128 bit
   ushort type;   //  16 bit
   ushort code;   //  16 bit
   uint   value;  //  32 bit
   float  x;      //  32 bit
   float  y;      //  32 bit
}

struct
Draw_Event {     // 192 bit
   ushort type;   //  16 bit
   ushort code;   //  16 bit
   uint   value;  //  32 bit
   float  x;      //  32 bit
   float  y;      //  32 bit
   float  w;      //  32 bit
   float  h;      //  32 bit
}
```

How to implement on D?
Aug 10
next sibling parent reply Vitaliy Fadeev <vital.fadeev gmail.com> writes:
On Saturday, 10 August 2024 at 07:46:46 UTC, Vitaliy Fadeev wrote:


 Pass the structure through registers ?



 Wrap the registries in a structure ?
 How to implement on D?
I try: ``` import std.stdio; void main() { Event_1 event_1; event (event_1); Event_2 event_2; event (event_2); } struct Event_1 { ushort type = 1; ushort code = 2; uint value = 3; } struct Event_2 { ushort type = 1; ushort code = 2; uint value = 3; float x = 4.0; float y = 5.0; } void event (EVENT) (/* R this, */ EVENT e) { enum REG_SIZE = (void*).sizeof; // Bytes pragma (msg, EVENT, " : ", EVENT.sizeof); pragma (msg, "REG_SIZE: ", REG_SIZE); static if (EVENT.sizeof == 0) { // } else static if (EVENT.sizeof <= REG_SIZE) { // 64 bit _event (/* this, */ * cast (REG*) &e, //* cast (REG*) cast (ubyte*) &e, //cast (REG) *( // (cast (ubyte*) &e)[0..EVENT.sizeof].ptr //), 0, 0); } else static if (EVENT.sizeof <= 2*REG_SIZE) { // 128 bit _event (/* this, */ cast (REG) *( (cast (ubyte*) &e)[0..REG_SIZE].ptr ), cast (REG) *( (cast (ubyte*) &e)[REG_SIZE..EVENT.sizeof].ptr ), 0); } else static assert (0, "Event sizeof too much"); } alias REG = ulong; void _event (/* REG this, */ REG type_code_value, REG r3, REG r4) { //switch (type_code_value.type) { // case Event.Type.GUI: gui.event (type_code_value, r3, r4); break; // default: //} writeln ("type_code_value: ", type_code_value); writeln ("r3: ", r3); writeln ("r4: ", r4); Event_1 event_1; event_1 = * cast (Event_1*) &type_code_value; writeln (" event_1 :", event_1); if (r3 != 0) { writeln (" event_2 :", r3); } } ``` But i have 0 in r3. I need help converting the structure `Event_2` into 2 `ulong` parameters `type_code_value`, `r3`.
Aug 10
parent reply Vitaliy Fadeev <vital.fadeev gmail.com> writes:
On Saturday, 10 August 2024 at 08:04:10 UTC, Vitaliy Fadeev wrote:
 On Saturday, 10 August 2024 at 07:46:46 UTC, Vitaliy Fadeev 
 wrote:


 Pass the structure through registers ?



 Wrap the registries in a structure ?
 How to implement on D?
I try: ... But i have 0 in r3. I need help converting the structure `Event_2` into 2 `ulong` parameters `type_code_value`, `r3`.
D online editor: https://run.dlang.io/gist/vitalfadeev/38ffcd289bb87c7e02a4992f698090d0?compiler=dmd
Aug 10
parent reply Vitaliy Fadeev <vital.fadeev gmail.com> writes:
On Saturday, 10 August 2024 at 08:10:10 UTC, Vitaliy Fadeev wrote:
 On Saturday, 10 August 2024 at 08:04:10 UTC, Vitaliy Fadeev 
 wrote:
 On Saturday, 10 August 2024 at 07:46:46 UTC, Vitaliy Fadeev 
 wrote:


 Pass the structure through registers ?



 Wrap the registries in a structure ?
 How to implement on D?
I try: ... But i have 0 in r3. I need help converting the structure `Event_2` into 2 `ulong` parameters `type_code_value`, `r3`.
D online editor: https://run.dlang.io/gist/vitalfadeev/38ffcd289bb87c7e02a4992f698090d0?compiler=dmd
May be `union` ?
Aug 10
parent Vitaliy Fadeev <vital.fadeev gmail.com> writes:
On Saturday, 10 August 2024 at 08:29:20 UTC, Vitaliy Fadeev wrote:
 On Saturday, 10 August 2024 at 08:10:10 UTC, Vitaliy Fadeev 
 wrote:
 On Saturday, 10 August 2024 at 08:04:10 UTC, Vitaliy Fadeev 
 wrote:
 On Saturday, 10 August 2024 at 07:46:46 UTC, Vitaliy Fadeev 
 wrote:


 Pass the structure through registers ?



 Wrap the registries in a structure ?
 How to implement on D?
I try: ... But i have 0 in r3. I need help converting the structure `Event_2` into 2 `ulong` parameters `type_code_value`, `r3`.
D online editor: https://run.dlang.io/gist/vitalfadeev/38ffcd289bb87c7e02a4992f698090d0?compiler=dmd
May be `union` ?
Thanks, all, for energy! I do it with `union`: ``` struct Convertor (T) { union { T from; struct { REG r1; REG r2; REG r3; REG r4; } } } ``` ``` auto convertor = Convertor!(EVENT) (e); _event (/* this, */ convertor.r1, convertor.r2, convertor.r3); ```
Aug 10
prev sibling next sibling parent reply IchorDev <zxinsworld gmail.com> writes:
On Saturday, 10 August 2024 at 07:46:46 UTC, Vitaliy Fadeev wrote:


 Pass the structure through registers ?



 Wrap the registries in a structure ?



 I need to pass different events: `Draw_Event`, 
 `Mouse_Move_Event`, `...`
 I need to pass an event to many objects: `foreach (o; world) 
 o.event (e);`
 I need speed.
 I want to pass the structure in registers: (like __fastcall 
 callin convention): `void _event (REG r1, REG r2, REG r3, REG 
 r4);`. But it's hard to read.
 I want comfortable use: (like a wrap registers in struct):
 ```
 void
 event (Event e) {
     writeln (e.type);
     writeln (e.code);
     writeln (e.value);
     switch (e.type) {
       case Type.REL: _rel_event (e); break;
       case Type.GUI: _gui_event (e); break;
       case Type.APP: _app_event (e); break;
       default:
     }
 }
 ```

 The problem is that the size of the structure is larger than 
 the size of the register.

 ```
 struct
 Event {          //  64 bit
   ushort type;   //  16 bit
   ushort code;   //  16 bit
   uint   value;  //  32 bit
 }
 ```

 But the event size can be > 64 bit. More than register size.

 ```
 struct
 Mouse_Event {    // 128 bit
   ushort type;   //  16 bit
   ushort code;   //  16 bit
   uint   value;  //  32 bit
   float  x;      //  32 bit
   float  y;      //  32 bit
 }

 struct
 Draw_Event {     // 192 bit
   ushort type;   //  16 bit
   ushort code;   //  16 bit
   uint   value;  //  32 bit
   float  x;      //  32 bit
   float  y;      //  32 bit
   float  w;      //  32 bit
   float  h;      //  32 bit
 }
 ```

 How to implement on D?
This depends on the calling convention used by your compiler and on your CPU architecture. 64 bits is already 2 data registers on a 32-bit CPU. There are also many calling conventions that allow multiple data registers to be used when passing structs around. Do you really need to avoid them being passed on the stack though? Is your application highly performance critical? (i.e. kernel code) You could also use `ref const` to avoid the copying, but your data will probably always be on the stack that way.
Aug 10
parent reply Vitaliy Fadeev <vital.fadeev gmail.com> writes:
On Saturday, 10 August 2024 at 08:06:42 UTC, IchorDev wrote:
 On Saturday, 10 August 2024 at 07:46:46 UTC, Vitaliy Fadeev 
 wrote:
 [...]
This depends on the calling convention used by your compiler and on your CPU architecture. 64 bits is already 2 data registers on a 32-bit CPU. There are also many calling conventions that allow multiple data registers to be used when passing structs around. Do you really need to avoid them being passed on the stack though?
Yes.
 Is your application highly performance critical?
Many input event + many internal ui events -> many calls * many objects. Yes, I like the fast, responsive interface on old hardware (as B970 CPU).
Aug 10
parent claptrap <clap trap.com> writes:
On Saturday, 10 August 2024 at 08:18:54 UTC, Vitaliy Fadeev wrote:
 On Saturday, 10 August 2024 at 08:06:42 UTC, IchorDev wrote:

 Is your application highly performance critical?
Many input event + many internal ui events -> many calls * many objects. Yes, I like the fast, responsive interface on old hardware (as B970 CPU).
Lets say you get mouse events 100 times a second and and you have 10 function calls to filter through the gui tree, and your overhead for passing on the stack is 20 cycles. (100*10*20) = 20,000 And your CPU is 2Ghz, so... 2,000,000,000 / 20,000 = 100,000 So what you're optimizing for is like 0.001% of your cpu time. It's utterly irrelevant.
Aug 10
prev sibling parent Basile B. <b2.temp gmx.com> writes:
On Saturday, 10 August 2024 at 07:46:46 UTC, Vitaliy Fadeev wrote:


 Pass the structure through registers ?

 [...]

 How to implement on D?
You dont need to pass whole event. The obvious design for this kind of things is that you declare a local event that's an union of all possible things then in the low level event loop you dispatch the members of interest to the high level consumer. This is for example how this worked in kheops: 1. low level event loop with the big local union (an XEvent): https://gitlab.com/basile.b/kheops/-/blob/master/src/kheops/control.d?ref_type=heads#L2770 2. example of dispatching where only the usefull things are passed: https://gitlab.com/basile.b/kheops/-/blob/master/src/kheops/control.d?ref_type=heads#L2863 3. then the high level consumers just receive the useful parameters: https://gitlab.com/basile.b/kheops/-/blob/master/src/kheops/control.d?ref_type=heads#L752 That's always 3 or 4 parameters, always passed in general purpose registers. I've never seen these kind of things done differently because it would indeed be slow to pass the whole event.
Aug 10