feature request: an atomicAdd() function included

2020-03-30 07:42发布

问题:

In the G-WAN KV options, KV_INCR_KEY will use the 1st field as the primary key.

That means there is a function which increments atomically already built in the G-WAN core to make this primary index work.

It would be good to make this function opened to be used by servlets, i.e. included in gwan.h.

By doing so, ANSI C newbies like me could benefit from it.

回答1:

There was ample discussion about this on the old G-WAN forum, and people were invited to share their experiences with atomic operations in order to build a rich list of documented functions, platform by platform.

Atomic operations are not portable because they address the CPU directly. It means that the code for Intel x86 (32-bit) and Intel AMD64 (64-bit) is different. Each platform (ARM, Power7, Cell, Motorola, etc.) has its own atomic instruction sets.

Such a list was not published in the gwan.h file so far because basic operations are easy to find (the GCC compiler offers several atomic intrinsics as C extensions) but more sophisticated operations are less obvious (needs asm skills) and people will build them as they need - for very specific uses in their code.

Software Engineering is always a balance between what can be made available at the lowest possible cost to entry (like the G-WAN KV store, which uses a small number of functions) and how it actually works (which is far less simple to follow).

So, beyond the obvious (incr/decr, set/get), to learn more about atomic operations, use Google, find CPU instruction sets manuals, and arm yourself with courage!



回答2:

Thanks for Gil's helpful guidance.
Now, I can do it by myself.
I change the code in persistence.c, as below:
firstly, i changed the definition of val in data to volatile.

//data[0]->val++;  
//xbuf_xcat(reply, "Value: %d", data[0]->val);  
int new_count, loops=50000000, time1, time2, time;  

time1=getus();
for(int i; i<loops; i++){
    new_count = __sync_add_and_fetch(&data[0]->val, 1);
}
time2=getus();

time=loops/(time2-time1);
time=time*1000;

xbuf_xcat(reply, "Value: %d, time: %d incr_ops/msec", new_count, time);

I got 52,000 incr_operations/msec with my old E2180 CPU.
So, with GCC compiler I can do it by myself.
thanks again.