cURL / Mailing Lists / curl-library / Single Mail

curl-library

Re: mutex stuff

From: Daniel Stenberg <daniel_at_haxx.se>
Date: Thu, 21 Mar 2002 16:33:26 +0100 (MET)

On Thu, 21 Mar 2002, Noel Byron wrote:

> Ah, I have not though about that... But since the the user code implements
> the create function it can easily supply the same mutex (handle) to all
> calls to Curl_mutex_new(). In addition we could pass a CURL_MUTEX_USAGE to
> Curl_mutex_new(int) so the user can decide wich mutexes he wants to use
> for the different tasks in libcURL.
>
> If I'm right, the only real difference I see is that libcURL does not have
> to call Curl_mutex_new() (and hopefully Cur_mutex_free() :o). I agree, that
> could improve stability.
>
> But if we want to reuse mutexes at all we should consider the following
> situation: Thread A locks mutex m1 and while it is locked, Thread A locks
> another mutex m2. This is no problem if m1 and m2 are different mutexes,
> but if m2 and m1 are the same mutex we would have a deadlock situation.
> Most mutex implementations are not recursive. We should keep that in mind.

That's a very good point, and I haven't really put much thought on that yet.

It only makes a dead-lock if the libcurl code attempts to lock two mutexes at
the same time, as then the application might use the same native mutex for
both of them and thus it'll hang forever.

I say we should avoid (at all costs) locking two mutexes at the same time
within libcurl (I mean within one single thread running libcurl).

Right? Wouldn't that prevent this dead-lock risk?

> > You then enable mutex magic in libcurl similar to this:
> >
> > struct curl_mutex1 moootexx=
> > {CURL_MUTEX_ONE, NULL, my_unlock, my_lock};
> >
> > curl_easy_setopt(easy, CURLOPT_MUTEX, &moootexx);
>
> Ah, now it becomes clearer. I had a totally diffent view.

I figured that. That's also why I like to talk around actual code examples
and prototypes. It makes it less abstract.

> Ok, that looks quite elegant. But what I don't really understand is that
> you tie mutexex to CURL handles. For example the global DNS cache. You
> would add the mutex lock and unlock code for it as soon as a CURL handle
> (with a activated mutex) would access it? That would mean some CURL handles
> could operate on the cache synchronized and some not depending on
> CURLOPT_MUTEX for the handle?

You focus too much on the DNS cache! ;-) I'm trying to set a generic approach
for all kinds of sharing between handles.

The "global" DNS cache is a kind of violation of the whole libcurl principle
(global variables don't belong in library code), and as such it must not be
used as a (good) example when we discuss data sharing.

The only reason we have a global DNS cache, is for single-threaded
applications that want the cache to survive between indepdendent easy handles
are inited and cleaned up. We should never encourage that kind of usage.

All caching *should* be done on a per-handle basis and then we should
specificly tell the handles to share the data, using mutexes.

Think of cookies and you might see it clearer.

(Yes, we can still support global DNS caching but it is a special case that
will remain a "special case" until proven otherwise.)

> The same is true for me. It is no problem to change my code but I have a
> important question:
>
> A use case...

Use cases are good.

> I intended to use the global DNS cache. In addition I wanted to write a
> function that lets me fill this cache outside the a CURL operation. Eg
> curl_hostname_resolve_and_add_to_cache("www.somwhere.xy/foo");

There's no API for "filling" the cache from outside libcurl and I honestly
can't see the point of doing it either. Can you elaborate on what good this
would do for your program?

> My next idea was to increase the cache timeout to several hours since DNS
> names don't change often.

There's an option for that.

> And now my most twisted idea... I would start a thread that does nothing
> else then hostname resolving an list of URLs which have to be downloaded
> later. Remember, I want to write a GUI app that must download a massive
> amount of URLs.
>
> This is my answer to ansynchronous DNS resolving. ;o)

Yes, but the total running time will remain the same. You won't gain anything
by resolving the names prematurely, on the contrary, you only risk that the
info is bad when you eventually need/use it.

Or am I missing something?

> It could be interesting for the multi API, too. Since resoving a DNS name
> could take several seconds and longer.
>
> So my question: would this be possible with the 'id' approach?

It really doesn't matter what approach we use, as the 'id' approach would
only make a difference on how we lock mutexes from within libcurl.

Of course you will be able to have all those 511 threads running libcurl to
share the DNS cache.

We only need to implement this! ;-)

-- 
    Daniel Stenberg -- curl groks URLs -- http://curl.haxx.se/
Received on 2002-03-21