Re: making a threadsafe localtime
sorry to flog ol' neddy,
I have the situation where localtime is called from a thread created by a certain class. It's more than likely that an application will have created several instances of that class, and so it's possible that several threads of the same process will call localtime. The structs tm result and time_t clock are local to each thread, and so don't need protecting.
An entirely threadsafe localtime would mean I don't even have to think about what's going on, and the application could have as many instances of that class as they like. However, protecting the call to the existing non-threadsafe localtime ( ie;
Code:
#ifdef Win32
boost::mutex global_mutex;
inline struct tm* localtime_r (const time_t *clock, struct tm *result) {
boost::mutex::scoped_lock lock(global_mutex);
if (!clock || !result) return NULL;
memcpy(result,localtime(clock),sizeof(*result));
return result;
}
#endif
would mean that all instances of that class would wait for global_mutex, and hence the bottleneck.
Is that true? It makes sense to me, but I'd like to be 100% on this...
nik
Re: making a threadsafe localtime
Jumping in late here.... I see a couple of things:
1) Do you really need to use a mutex here? If all you care about is synchronization across threads (vs. across processes), won't a cs do the job for you?
2) Is the function you posted a method to a class?
3) Why lock on a global level? You can lock only on a per-instance level or better yet, on a per-method level. Make the mutex (or cs) an instance member of the class and just lock it for the minimum time needed.
4) Does the const time_t *clock variable need to be passed in to this method? Can it be local instead?
5) Consider swapping the boost lock statement with the parameter check statement. That way, the code only locks when necessary.
Arjay
Re: making a threadsafe localtime
Good points Arjay,
Mutex's are MUCH slower than Critical sections.
Re: making a threadsafe localtime
Both mutexes and critical sections will slow down your code.
Here is some code I have tested which gives the safety of a mutex
without the overhead of using the OS level code.
I found that this improves the performance of my multithreaded server by about 500%!
myfunc() // protects the non-reentrant functions like malloc()
{
static int protector=0;
protector++;
while(protector>1){
protector--;
sleep(1);// sleep for milsec
protector++;
}
protected_function();
protector--;
}
Re: making a threadsafe localtime
it's just a shame then that your code is not thread safe in the slightest....
Re: making a threadsafe localtime
I think it is theoretically threadsafe because the protector variable will
never loose count of the increments and decrements assuming that it is
excuted as a single cpu instruction. I have also done all types of testing to
disprove it.
Re: making a threadsafe localtime
Your increments/decrements are not threadsafe, they are not atomic single instructions, you could use InterlockedIncrement() / InterlockedDecrement() instead though.
Re: making a threadsafe localtime
not even that would make the code thread safe though as you have no idea which thread acquired the lock, if you need a high speed locking mechanism, have a look at spin counts, or even "Jeffery Richters" COptex class, which is a high speed cross process critical section.
regards,
Re: making a threadsafe localtime
In my application which runs on Windows,linux,os/2 I have found that this works.
I think I will have to analyse it futher as this was tested only on single cpu machines.
I believe that if you have increments/decrements as atomic single instructions
(which you can ensure by using assembly) this works, as long as it is
not important which thread has aquired the lock.
I am probably mistaken in this.
Thanks darka for pointing out other possibilities.
Re: making a threadsafe localtime
In any case I needed a mechanism that is not platform dependent.
That is the reason I am so keen on this.
Thanks for replies
Re: making a threadsafe localtime
You can't have platform independence when you use assembler - and I can't see why your so keen on your idea when it is not thread safe ?
Re: making a threadsafe localtime
May be I am so dense I cant see where my code fails .. Can you explain?
Re: making a threadsafe localtime
You are not dense (multithread programming can be a git) but the problem is in that you increments/decrements are not atomic.
Changing this to assembly language breaks the platform independence that you would like, I assume that Linux or whatever other OS you are working with has interlocked increment/decrement functions too (probably called something else).
Only by using Interlocked versions of increment / decrement are you making them atomic.
You could simply use a critical section (and you can get cross platform versions) instead though. Critical sections are pretty fast, especially when compared with Mutexes.
regards,
Re: making a threadsafe localtime
I got it now - the increment/decrement operations may not be compiled into
single instructions so it breaks my code.
Initially I was using critical sections for this, but since porting to linux
could not find something equivalent. So started using mutexes and looking
for alternatives.
Thanks!
Re: making a threadsafe localtime
Hi Kdv,
Quote:
I got it now - the increment/decrement operations may not be compiled into
exactly..
I don't write cross platform code so cannot advise on that.
regards,