Atomic function calls c/c++

#include <thread>
#include <cstdio>
using namespace std;

void foo()
 {
 printf("Goodbye world.\r\n");
 }

int main()
 {
 thread t1(foo);
 thread t2(foo);
 t1.join();
 t2.join();
 }

Very simple. You would expect
Goodbye world.
Goodbye world.
and it did work in YOUR pc, but in your customer's PC this is what happened:
Goodbye woGoodbyrld.
e world.
The reason of course is that the calls to printf() were simultaneous. How to make them atomic?

Template Solution

#include <thread>
#include <cstdio>
using namespace std;

static std::recursive_mutex InterlockedCallMutex;
template <typename R,typename... Args>
R InterlockedCall(void* pfoo,Args... args)
    {
    std::lock_guard<std::recursive_mutex> lock(InterlockedCallMutex);
    typedef R(__stdcall * function_pointer)(Args...);
    function_pointer P = (function_pointer)pfoo;
    const auto return_value = (*P)(std::forward<Args>(args)...);
    return (R)return_value;
    }


void foo()
 {
 InterlockedCall<int,const char*>(printf,"Goodbye world.\r\n");
 }

int main()
 {
 thread t1(foo);
 thread t2(foo);
 t1.join();
 t2.join();
 }

This also works with a void-returning function, for return (void)return_value is valid.
Perhaps for integer-returning functions, which are the most common, you might want to specialize:
template <typename... Args>
size_t InterlockedCall(void* pfoo,Args... args)
    {
    std::lock_guard<std::recursive_mutex> lock(InterlockedCallMutex);
    typedef size_t(__stdcall * function_pointer)(Args...);
    function_pointer P = (function_pointer)pfoo;
    const auto return_value = (*P)(std::forward<Args>(args)...);
    return (size_t)return_value;
    }
Now you can call without the types in the <>, because they are automatically deduced:
void foo()
 {
 InterlockedCall<>(printf,"Goodbye world.\r\n");
 }

A catch

It works only for __cdecl calling convention. You must create another template for  __stdcall or other conventions.

No comments:

Post a Comment

Genuine websites to earn money.

If you are interested in PTC sites then this article is for you. I have personally tried many of the sites and found that the best thing ...