473,657 Members | 2,733 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Reentrant code

I am modifying some legacy code, to make the functions reentrant. I use
lots of global data (large nested structs) to pass data around quicky.
The global structures are far too large (in size) for each of my
functions to maintain copies.

Any suggestions on the best way to write a reentrant version of my
library? - bearing in mind that my global vars are mostly, pointers to
*HUGE* structures.
Jun 27 '08 #1
12 3482
On Jun 17, 12:10 pm, Bit Byte <r...@yourbox.c omwrote:
I am modifying some legacy code, to make the functions reentrant. I use
lots of global data (large nested structs) to pass data around quicky.
The global structures are far too large (in size) for each of my
functions to maintain copies.

Any suggestions on the best way to write a reentrant version of my
library? - bearing in mind that my global vars are mostly, pointers to
*HUGE* structures.

Your question is off-topic as C does not say anything about multi-
threading.

<off-topic>
That greatly depends on the function you are trying to make re-
entrant. A general approach is to use some sort of mutex to prevent
the global data from being altered in two place in the same places
leaving the result in an inconsistent state.
<just-curious>
You say your code uses a lot of globals. I think that's a bad idea
and may be you should do a design review.
</just-curious>
One thing to mention here is mutex uses co-operative locking. To
elaborate, mutex is a door through which only one person can enter at
a time and threads are standing in a queue. If the threads are
maintaining the queue, everything is great but the door does not stop
you from jumping out of the window.

Its not the running code that is to be made re-entrant. The access to
the shared data is to be synchronized. Lock the mutex before
modification and unlock it when you are done. Depending on your
problem, you may even have to use condition variables.
</off-topic>
Jun 27 '08 #2
On Jun 17, 11:33 am, rahul <rahulsin...@gm ail.comwrote:
On Jun 17, 12:10 pm, Bit Byte <r...@yourbox.c omwrote:
I am modifying some legacy code, to make the functions reentrant. I use
lots of global data (large nested structs) to pass data around quicky.
The global structures are far too large (in size) for each of my
functions to maintain copies.
Any suggestions on the best way to write a reentrant version of my
library? - bearing in mind that my global vars are mostly, pointers to
*HUGE* structures.

Your question is off-topic as C does not say anything about multi-
threading.
Re-entrancy doesn't have to do anything with threads or thread safety,
but indeed ISO C doesn't mention thing such as 'reentrancy', 'threads'
etc.
"Bit Byte", if you are programming for windows, try a windows
newsgroup. If you are programming for unix, try comp.unix.progr ammer.
<snip rahul's off-topic reply>
Jun 27 '08 #3
vi******@gmail. com writes:
[...]
Re-entrancy doesn't have to do anything with threads or thread safety,
but indeed ISO C doesn't mention thing such as 'reentrancy', 'threads'
etc.
[...]

It does, but only briefly.

C99 7.1.4p4:

The functions in the standard library are not guaranteed to be
reentrant and may modify objects with static storage duration.

footnote:

Thus, a signal handler cannot, in general, call standard library
functions.

There's also an index entry for "reentrancy ", pointing to 5.1.2.3
(Program execution) and 5.2.3 (Signals an interrupts) as well as
7.1.4.

--
Keith Thompson (The_Other_Keit h) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jun 27 '08 #4
Bit Byte wrote:
I am modifying some legacy code, to make the functions reentrant. I use
lots of global data (large nested structs) to pass data around quicky.
The global structures are far too large (in size) for each of my
functions to maintain copies.

Any suggestions on the best way to write a reentrant version of my
library? - bearing in mind that my global vars are mostly, pointers to
*HUGE* structures.
You will have to protect your global data structures so that
only a single thread access them at any given moment.

There are no "miracle" solutions, sorry.

--
jacob navia
jacob at jacob point remcomp point fr
logiciels/informatique
http://www.cs.virginia.edu/~lcc-win32
Jun 27 '08 #5
Bit Byte wrote:
I am modifying some legacy code, to make the functions reentrant. I use
lots of global data (large nested structs) to pass data around quicky.
The global structures are far too large (in size) for each of my
functions to maintain copies.

Any suggestions on the best way to write a reentrant version of my
library? - bearing in mind that my global vars are mostly, pointers to
*HUGE* structures.
Others have said there's no re-entrancy in C, but I don't
understand why they think that. A C function running in the
"main line" of the program might also be called from a handler
for an asynchronous signal, and if you want to do this you'll
need to be sure the function is re-entrant. And you can make
it so, with due diligence.

Aside from that limited situation, though, C has no notion
of "concurrent execution," nothing like multiple threads or
parallel processes or anything of that kind. If your problem
involves such beyond-C things then mere re-entrancy alone may
not be enough; you should probably seek advice on a forum like
comp.programmin g.threads.

But to the mechanics: Eliminating the global variables is
not in and of itself enough to make a function re-entrant, but
it's usually a necessary first step. If you've got a global
and a function that manipulates it:

int global;
void set_global(int new_value) {
global = new_value;
}

.... you can get rid of the global by giving the function an
extra argument that points to a non-global substitute:

void set_global(int *global, int new_value) {
*global = new_value;
}

This can become tiresome if there are a lot of globals to
be eliminated, and/or if the functions call each other a lot:
You'll get snarled passing a lot of pointer arguments all over
the place and probably getting some of them wrong. But much
of that can be smoothed over by using a struct:

/* Old */
int global1;
double global2;
char *global3;
void func(void) {
global1 = 42;
global2 = 42.0;
other_func();
}
void other_func(void ) {
global3 = "XLII";
}

/* New */
struct globals {
int global1;
double global2;
char *global3;
};
void func(struct globals *gp) {
gp->global1 = 42;
gp->global2 = 42.0;
other_func(gp);
}
void other_func(stru ct globals *gp) {
gp->global3 = "XLII";
}

If there's a lot of this you may be tempted to use macros
to ease the transition:

struct globals { ... as above ... };
#define global1 gp->global1
#define global2 gp->global2
#define global3 gp->global3

.... which allows you to leave the existing functions almost
unchanged: The source still refers to plain old global2 and
so on, with the pointer automagically inserted. Do this if
you really, really feel you must -- but I've been down that
road, and just a few bends beyond where you can see it gets
rocky and rutted. Better to do the scut-work up front than
to maintain a hack for ever and ever.

--
Eric Sosman
es*****@ieee-dot-org.invalid
Jun 27 '08 #6
Eric Sosman wrote:
Bit Byte wrote:
>I am modifying some legacy code, to make the functions reentrant. I
use lots of global data (large nested structs) to pass data around
quicky. The global structures are far too large (in size) for each of
my functions to maintain copies.

Any suggestions on the best way to write a reentrant version of my
library? - bearing in mind that my global vars are mostly, pointers to
*HUGE* structures.

Others have said there's no re-entrancy in C, but I don't
understand why they think that. A C function running in the
"main line" of the program might also be called from a handler
for an asynchronous signal, and if you want to do this you'll
need to be sure the function is re-entrant. And you can make
it so, with due diligence.

Aside from that limited situation, though, C has no notion
of "concurrent execution," nothing like multiple threads or
parallel processes or anything of that kind. If your problem
involves such beyond-C things then mere re-entrancy alone may
not be enough; you should probably seek advice on a forum like
comp.programmin g.threads.

But to the mechanics: Eliminating the global variables is
not in and of itself enough to make a function re-entrant, but
it's usually a necessary first step. If you've got a global
and a function that manipulates it:

int global;
void set_global(int new_value) {
global = new_value;
}

... you can get rid of the global by giving the function an
extra argument that points to a non-global substitute:

void set_global(int *global, int new_value) {
*global = new_value;
}

This can become tiresome if there are a lot of globals to
be eliminated, and/or if the functions call each other a lot:
You'll get snarled passing a lot of pointer arguments all over
the place and probably getting some of them wrong. But much
of that can be smoothed over by using a struct:

/* Old */
int global1;
double global2;
char *global3;
void func(void) {
global1 = 42;
global2 = 42.0;
other_func();
}
void other_func(void ) {
global3 = "XLII";
}

/* New */
struct globals {
int global1;
double global2;
char *global3;
};
void func(struct globals *gp) {
gp->global1 = 42;
gp->global2 = 42.0;
other_func(gp);
}
void other_func(stru ct globals *gp) {
gp->global3 = "XLII";
}

If there's a lot of this you may be tempted to use macros
to ease the transition:

struct globals { ... as above ... };
#define global1 gp->global1
#define global2 gp->global2
#define global3 gp->global3

... which allows you to leave the existing functions almost
unchanged: The source still refers to plain old global2 and
so on, with the pointer automagically inserted. Do this if
you really, really feel you must -- but I've been down that
road, and just a few bends beyond where you can see it gets
rocky and rutted. Better to do the scut-work up front than
to maintain a hack for ever and ever.
Good advice indeed. Only bit I don't understand is your last statement:
"Better to do the scut-work up front than to maintain a hack for ever
and ever."

I thought that 'wrapping" the globals in a struct and using macros to
access fields (posibly with mutex/semaphores) was a good idea - but
after you last statement, I am not sure if you mean it is a 'hack' -
since you have been down this route already, your views are of interest
to me ...
Jun 27 '08 #7
Bit Byte wrote:
Eric Sosman wrote:
>[...]
If there's a lot of this you may be tempted to use macros
to ease the transition:

struct globals { ... as above ... };
#define global1 gp->global1
#define global2 gp->global2
#define global3 gp->global3

... which allows you to leave the existing functions almost
unchanged: The source still refers to plain old global2 and
so on, with the pointer automagically inserted. Do this if
you really, really feel you must -- but I've been down that
road, and just a few bends beyond where you can see it gets
rocky and rutted. Better to do the scut-work up front than
to maintain a hack for ever and ever.

Good advice indeed. Only bit I don't understand is your last statement:
"Better to do the scut-work up front than to maintain a hack for ever
and ever."

I thought that 'wrapping" the globals in a struct and using macros to
access fields (posibly with mutex/semaphores) was a good idea - but
after you last statement, I am not sure if you mean it is a 'hack' -
since you have been down this route already, your views are of interest
to me ...
Anything to do with the "posibly [sic] with mutex/semaphores"
part belongs in comp.programmin g.threads, not here, since as I
mentioned before the C language's limited notions of simultaneity
don't extend to multi-threaded or even multi-process programs.

Now, about macros of the kind I illustrated. The first bit
of hackishness is the introduction of an "assumed" identifier,
the `gp->' part. If the function argument isn't named literally
`gp' the thing blows up. A person reading the code will see an
argument named `gp' but will not see it used anywhere in the
body of the function, and may get confused by the apparently
unused argument. A person studying the code in a debugger will
be unable to examine or alter what seems on its face to be a
perfectly normal `global2' variable. And so on. You may save
some lexical work up front, but with those savings you buy a
nagging irritation that keeps on paying its unwelcome dividends.

A coding style guide developed by a bunch of pretty highly-
respected C folks puts it this way: "Don't change syntax via
macro substitution. It makes the program unintelligible to all
but the perpetrator." You, it seems, are even now struggling
with the decisions made by the long-ago authors of your "legacy
code," and probably complaining or at least muttering about the
lack of clarity resulting from some of those decisions. Have
mercy on the person who in turn will follow you through this
code, and seek not to be on the receiving end of his mutterings
and complaints. Remember: Source code is read by compilers but
also by programmers, and the latter are the more important
audience.

--
Er*********@sun .com
Jun 27 '08 #8
rio
What is "Reentrant code"?
A function that use all its data in the stack i.e. automatic
variables and arguments, is reentrant?
A function that use all its data that came from a reentrant malloc
function is reentrant?

Thank you

Jun 27 '08 #9
In article <48************ ***********@rea der4.news.tin.i t>, rio <a@b.cwrote:
>What is "Reentrant code"?
A function that use all its data in the stack i.e. automatic
variables and arguments, is reentrant?
A function that use all its data that came from a reentrant malloc
function is reentrant?
Suppose a routine is executing, and -somehow- during the middle
of execution, the execution gets suspended and -somehow- the
same routine gets called *while the original is suspended*.
Then if the routine works properly in the new call and exits
clealy, and upon being resumed, the suspended version continues
to work properly, then the routine was re-entrant.

In the above discussions, I omitted the mechanisms by which
the execution of a routine might get suspended and yet a new instance
of it be started. In pure standard C, the only way it can happen is
if the routine is called (directly or indirectly) as a signal handler
as a result of a system-generated signal or as a result of a raise()
call. In C that is not quite as pristine, there may be system
mechanisms (such as threads) that allow such things to happen.
--
"This quitting thing, it's a hard habit to break once you start."
-- Walter Matthau
Jun 27 '08 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
3750
by: Adrian Parker | last post by:
For some reason when I call validateFields before .Update (see below), I get this error: "Consumer's even handler called a non-reentrant method in the provider" However if I comment out the call to validateFields, all is fine. What could possibly cause this error? What is a non-reentrant method?
0
729
by: Martin B | last post by:
Hallo to everyone! Problem: -------- GridView Exception: reentrant call to the SetCurrentCellAddressCore function System: ------- WinXP Professional, english, .NET Framework 2.0 Beta Language C#
6
11038
by: junky_fellow | last post by:
what are reentrant functions? What are the characteristics of a reentrant code ? what things should be kept in mind while writing a reentrant code ?
2
2840
by: TheOne | last post by:
Would anyone please point me to a list of reentrant GNU C/C++ library functions? I have searched a lot on the web for it but without any success. Man page of signal(2) has listed system calls (POSIX 1003.1-2003 list) which are safe(reentrant) but thats not sufficient for my purpose. Thanks in advance.
9
8289
by: TheOne | last post by:
Would anyone please point me to a list of reentrant C library functions? I want to know which C library functions are safe to use inside a signal handler across all platforms. Does GNU C library make few other functions reentrant on Linux platform? I have searched a lot on the web for it but without any success. Man page of signal(2) has listed system calls (POSIX 1003.1-2003 list) which are safe(reentrant) but thats not sufficient for...
2
1845
by: a | last post by:
Hi, I have the following setup: PHP 5.1.x on Apache 2.x on Windows XP. A php script receives data from a form upon user submit, and then execs a Windows process, which may take some time to complete (actually this process performs a quite complex task which involves starting another process and then requesting a Windows service to perform yet other tasks). Everything works fine as long as the user submits the form and then patiently...
1
2741
by: jj_online | last post by:
This is not a C++ specific issue. However, I am trying to implement a readwritelock in C++ and hence would like to get help from this group. a readwritelock allows shared lock among all readers and exclusive lock for a single writer. After implemented, I realized that the writer may suffer starvation: readers can continuously get shared lock and hence writer will wait indefinitely. so I added a writer wait count and prevent reader...
17
3253
by: fmassei | last post by:
Dear all, I'm trying to put some old code in a portable, cross-platform library and I'm facing a big problem: is there a standard, platform- independent way to write a reentrant function that allocate dynamic memory? In other words: is it safe to use malloc() or free() in a thread-safe function? Thank you, Francesco
5
2382
by: Roland Mainz | last post by:
Hi! ---- Does anyone here know any XML parsers which are reentrant, threadsafe, maintained (e.g. the project should still be active+alive) and written in ANSI-C (libxml2 is unfortunately not reentrant and I'm currently not sure whether "Parsifal" (http://www.saunalahti.fi/~samiuus/toni/xmlproc/)) is still under active development... ?
0
8394
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
8306
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
8732
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
8503
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
7327
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
6164
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
4304
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
2726
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
1955
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.