cURL / Mailing Lists / curl-library / Single Mail

curl-library

living _with_ global variables

From: Bryan Henderson <bryanh_at_giraffe-data.com>
Date: Tue, 27 Dec 2005 17:50:37 +0100

I have an alternative to propose for the issue of global variables in
libcurl and their effect on modularity.

Eliminating global variables from GnuTLS turned out to be fairly difficult,
partly because there are a _lot_ of functions that need a context argument
added, and partly because GnuTLS maintainers are lukewarm to the basic idea
that life without global variables is better, and propose the alternative
below.

But the global variables in GnuTLS, and OpenSSL, and I presume the other
components that libcurl uses, are special in that they are all effectively
built-in constants, except for the fact that there has to be a library call
at some point to set them up. IOW, if the program/library loader were
smarter, it could set these up as real constants.

So this means the library can be used by multiple independent modules,
all calling global_init() and global_term(), as long as global_init()
and global_term() maintain a reference count and do their thing only on
the first and last call, respectively.

Now the problem with the reference count is that it isn't thread-safe.
Two independent modules running in separate threads might call
global_init() separately and make a mess.

But thread-safe isn't essential for these routines, because they can be
called at the very beginning and end of a program, when it is only one
thread. The code at that level doesn't necessarily know that this library
will be used and thus needs to be initialized, but that requirement can
propagate up through each layer's own global_init() function.

libcurl already has that thread-unsafe global init function, so it's
all set for this paradigm but for one thing: It doesn't do the
reference count. It has a flag "I've been initialized." If that
could be changed to "I've been initialized N times", and
curl_global_init() conspicuously documented as thread-unsafe (to the
greatest degree -- you must execute it when there is no other thread
in the program doing anything, not just no other thread using
libcurl), we'd have a solution to the modularity problem.

The fail-safe global init in curl_easy_init() would have to get
messier -- it would have to do its thing only if the init count is 0.

This is kind of ugly compared to private contexts, especially in an
object-oriented program, but it's really easy.

For dynamically loaded libraries, I believe this isn't any better or
worse than what we have today.

Does this work? Have I missed something?

-- 
Bryan Henderson                                    Phone 408-621-2000
San Jose, California
Received on 2005-12-27