-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add optional thread-safety #6
Comments
So you are saying that compiler might be smart enough to find that in all the occurrences of the calling of function usdf_functions, use_lock is either input as 0 or 1, and they are compile time constants, so that compiler actually generates two functions usdf_function_thread_safe and usdf_function_thread_unsafe by removing all these if statements? I think this is probably a long shot. I tried to compile a source file like this with gcc 4.9.1 and use objdump to look at the assemble. Looks like there is still a usdf_fuction there, and there are jump instructions based on the parameter value. Although I am not sure the assemble code generated by objdump is exactly the same as in the executable. BTW, the 'const' quantifier for use_lock has no use. As use_lock is passed by value, the function won't change the variable that passed as use_lock. |
Did you compile with -O[high_level], like -O9? |
Reese is correct. I don't know what went wrong so that I got the wrong conclusion. Now I recompiled the code I have and did objdump again, I can see compiler actually remove the conditional jump instruction. C source code static inline int usdf_function(use_lock)
{
int i = 0;
if (use_lock) {
i = 1;
printf("%s, use lock\n", __func__);
}
else {
printf("%s, don't use lock\n", __func__);
}
return i;
}
int
usdf_function_thread_safe(void)
{
int ret;
ret = usdf_function(1);
printf("%d\n", ret);
}
int
usdf_function_thread_unsafe(void)
{
int ret = usdf_function(0);
printf("%d\n", ret);
}
int main()
{
usdf_function_thread_safe();
usdf_function_thread_unsafe();
} Corresponding assembly
|
More complete example. struct usdf_data_t {
int protected;
pthread_spinlock_t lock;
};
static inline int usdf_function(struct usdf_data_t* usdt, int use_lock)
{
int i = 0;
if (use_lock) {
pthread_spin_lock(&usdt->lock);
i = 1;
usdt->protected = 100;
printf("%s, use lock\n", __func__);
pthread_spin_unlock(&usdt->lock);
}
else {
printf("%s, don't use lock\n", __func__);
}
return i;
}
int
usdf_function_thread_safe(struct usdf_data_t* usdt)
{
int ret;
ret = usdf_function(usdt, 1);
printf("%d\n", ret);
}
int
usdf_function_thread_unsafe(struct usdf_data_t* usdt)
{
int ret = usdf_function(usdt, 0);
printf("%d\n", ret);
}
int main()
{
struct usdf_data_t usd;
pthread_spin_init(&usd.lock, PTHREAD_PROCESS_PRIVATE);
usdf_function_thread_safe(&usd);
usdf_function_thread_unsafe(&usd);
pthread_spin_destroy(&usd.lock);
}
|
I am hoping that we can get clean-looking code to provide both thread-safe and non-threadsafe functions by writing like this:
The hope here is that the compiler completely removes the conditional on the constant "use_lock" so that there is no performance penalty in the non-locking case. Otherwise, we may have to resort to nasty tricky with #ifdefs and compiling the same source multiple ways.
The text was updated successfully, but these errors were encountered: