Re: Is this C style function well written and thread safe?
On Sep 12, 5:10 pm, jeff_j_dun...@yahoo.com wrote:
I alwasy use std::string and avoid char buffers but last night I
wanted to see if I could make a C style function that would be thread
safe.
For me, it was a good learning experience since my C/C++ knowledge is
limited but I do understand threading issues due to prior Delphi
experience.
In the following function, please assume that the Date object is well
written.
It's not. It's missing the most essential part of thread
safety: documentation as to the guarantees it offers:-).
In practice, it's what I'd call thread neutral. Threads are
completely irrelevant to it, since it owns and manages no data
of its own. It's up to the user to ensure thread safety when
using it. (For example, if the user passes the address of a
static buffer to buff, it isn't thread safe.) In a
multi-threaded environment, this is what I would consider the
"default guarantee": if a function is documented as being usable
in a multithreaded environment, and provides no other documented
guarantees with regards to threading, this is probably what one
should assume.
What I really want to know is if my char buff is being
handled safely.
What do you mean by "safely"? It's not being handled at all
safely, since you don't guarantee adequate length (and you don't
even tell the user how to ensure adequate length). As far as
threading is concerned, there is no problem if your guarantee is
that the function be thread neutral; it's an out argument, which
you explicitly write, and it is up to the user to ensure that it
isn't accessed from any other thread while you are writing it.
Similar issues concern Date: you only read it, so other threads
should be able to read it simultaneously, but it's up to the
user to ensure that no other thread makes a modifying access
while you are reading it.
void fbDateToStr( const IBPP::Date &d, char *buff )
{
if ( d < IBPP::MinDate || d > IBPP::MaxDate )
{
strcpy(buff, "");
}
else
{
int iMonth=0, iDay=0, iYear=0;
d.GetDate(iYear, iMonth, iDay);
sprintf(buff, "%d/%d/%d", iMonth, iDay, iYear);
}
}
USAGE:
char buffer[15];
fbDateToStr(dtInitialContactDt, buffer);
RETURNS:
MM/DD/YYYY or if date is invalid, a blank string
NOTES:
Initially, I thought of creating a static buffer within the
function instead of passing a buffer as this function
currently is doing, but doing so would have been thread-unsafe
since the buffer would now be visible/editable by all threads.
It's no more thread safe or thread unsafe than what you are
doing. It just presents a different guarantee. Since it isn't
the "default" guarantee, you would have to document the
requirements, but documenting that the user must ensure
synchronization is also a means of achieving thread safety.
Note that thread safety really concerns data, and not functions,
and is relevant to functions only in so far as they might use
data which the user doesn't know about, or in ways which the
user cannot anticipate. When I speak of a function being
"thread neutral", I mean that it doesn't read any data not
passed as an argument, and doesn't write any data not passed as
a documented out argument.
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S=E9mard, 78210 St.-Cyr-l'=C9cole, France, +33 (0)1 30 23 00 34