Cairo exports and more (was Re: [cairo] Re: Munging header files for export (and other) attributes)

Hans Breuer hans at breuer.org
Wed Sep 7 14:36:17 PDT 2005


On 06.09.2005 22:58, Carl Worth wrote:
> On Mon, 05 Sep 2005 23:23:00 +0200, Hans Breuer wrote:
> 
>>On 04.09.2005 23:15, Owen Taylor wrote:
>>
>>>On Sun, 2005-09-04 at 13:58 +0200, Hans Breuer wrote:
>>> * The addition of export markers generally looks good to me.
>>>   Carl will have to make the final call as to whether he
>>>   likes the names.
>>>
>>
>>IMO after all it doesn't look that bad. Though my prefered solution
>>would have beem the symbols file approach as well - and drop the
>>concept of messing with calling conventions ;)
> 
> 
> We've have "cairo_private" inside cairoint.h for a long time. Why not
> "cairo_public" for this new attribute? I'm definitely not yet
> convinced it makes sense to put the calling convention attribute into
> the public header yet.
> 
So I must have totally misunderstood what you wrote elsewhere
On 01.09.2005 19:50, Carl Worth wrote:
 > OK. That's far more than enough talk on this subject. Let's see a
 > patch, get it into CVS, and move on. (And yes, I do realize that I'm
 > the one to blame for dragging this out so much.)

Anyway, messing with calling convention seems to be mostly a non-*NIX
problem, so some further explaination may help. There are basically
two problems here :

- Is a calling convention supposed to be part of the cairo API ?

   On win32 compilers you can define to have cdecl, stdcall, fastcall.
   Gtk+ defines it's calling convention implicit to cdecl by it's use
   of function pointer calls. To be compatible cairo must either do the
   same or *explicit* declare the calling convention in any public function.
   BTW: if the calling convention is not part of the cairo API it will not
   be possible to have a stable ABI (Application Binary Interface)

- If a calling convention is part of the cairo API : is there any interest
   to allow to use cairo from an application which chooses another defualt
   calling convention (for whatever reason?). Again Gtk+ as example does
   *not* allow this because there is no explicit calling convention in the
   headers and so almost any function call would smash the stack, if done
   with the wrong calling convention.

More details at: http://en.wikipedia.org/wiki/Calling_convention
> 
>>> * The portability stuff is mostly good. I think rather than
>>>   hacking up the PDF and PS backends to build without font
>>>   support, it would be better to not build them until we 
>>>   get font embedding working with win32 fonts. It's not
>>>   that much work.
>>
>>Maybe, but my patches are huge enough for now.
> 
> 
> As an aside, the one-big-patch style has always made these harder for
> me to work with in terms of pulling things into cairo. With the
> current patch for example, I definitely don't want these PDF and PS
> modifications in the tree. One patch per change would definitely make
> it easier to take the changes that are acceptable.
> 
But with the current patch as an example I already have done the extra
work to separate it into three independent parts. Which would be just
another waste of time if all three are not accepted ;)

> 
>>>   You may have the right idea with CMake.
>>
>>I'm not sure. There wasn't much interest in bringing it any further as I
>>announced it. Also maintaining the files for a cross-platform build alone
>>seems to be a little out of my scope.
> 
> 
> I've been meaning to respond to the cmake proposal for a long time,
> but I've just been too busy. I wanted to try it out on Linux since to
> see if it would be a viable candidate for replacing what we're
> currently using. In some ways I would be more easily convinced to
> replace our current system rather than supporting two simultaneously.
> 
> But in the meantime...
> 
> 
>>On 04.09.2005 23:18, Owen Taylor wrote:
>>
>>>I forgot to finish what I was saying, which was that while I don't think
>>>the .msc makefiles are a full solution, I think it makes sense to get
>>>them into the tree ... might as well have *something* there.
> 
> 
> Owen's likely right that something is better than nothing, so we
> should probably just put the .msc Makefiles into CVS. Hans, did you
> request/get CVS commit access yet?
> 
> 	http://freedesktop.org/wiki/AccountRequests
> 
Nope. The ssh part is easy enough but for the pgp part I currently dont
know what steps I would need to done.

> 
>>>Perhaps we should include the relevant parts of build\..\make.msc in the
>>>cairo tree to avoid having GLib be a build dependency of cairo? 
>>>
>>
>>A better solution may be to detect if the bigger environment is available
>>and fallback to a *no dependencies* cairo build? That approach was quite
>>simple to get working even with the ugly nmake syntax.
> 
> 
> What's the issue here? Is it that the current patch depends on glib
> just to borrow a piece of its build infrastructure? That's something I
> definitely don't want. What piece is it borrowing?
> 
For Gtk+, Dia, The GIMP and some other projects the msvc build relies on
configuration *by hand*. You basically need one master makefile-include-file
which defines FOO_CFLAGS and FOO_LIBS matching your installation.
It is described in more detail in :
>>http://cvs.gnome.org/viewcvs/*checkout*/glib/README.win32 ?
> 
> 
> Yes, something along those lines would be quite useful. I wrote up
> something like that for the current auto* system before releasing 1.0:
> 
> 	http://cairographics.org/INSTALL
> 
> And I think a similar document is a requirement for any new build
> system to land in the tree.
> 
Fair enough.

[...]
>>> #ifndef CAIRO_MUTEX_DECLARE
>>>+#  ifdef __GNUC__
>>> # warning "No mutex declarations, assuming single-threaded code"
>>>+#  else
>>>+#  pragma message("No mutex declarations, assuming single-threaded code")
>>>+#  endif
>>>
>>>The pragma here is as MSVC specific as #warning is GCC specific. So, it
>>>would be good to conditionalize it. 
>>
>>AFAIK unknown pragmas are supposed to be ignored (with warning).
>>#warning on the other hand gives a build error with msvc.
> 
> 
> Setting aside the poor portability of "#warning", I think that either
> version of the above should be considered a bug. Cairo really should
> be thread-safe. An obscure message scrolling by during compilation of
> cairo itself shouldn't be sufficient for building a non-thread-safe
> cairo.
> 
> 
>>>Long term, of course, what really
>>>needs to be done is implement locking for Win32.
>>>
>>
>>That one depends on a backend constructor facility cause the synchronization
>>objects can not be initialized statically. Otherwise quite a simple
>>task.
> 
> 
> And hopefully the initialization to make this complete isn't too hard
> either.
> 
Intialize:

HANDLE hMutex = CreateMutex (NULL, FALSE, NULL);

Lock:
WaitForSingleObject (hMutex, INFINITE);

Unlock:
ReleaseMutex (hMutex);

CriticalSection is a little more complex but the performance is better.

> Would it be possible to have CAIRO_MUTEX_DECLARE define a function
> that initialized the synchronization object on its first call and then
> make CAIRO_MUTEX_LOCK call into that function first? Is there some
> non-object based mutual-exclusion mechanism that could be used to do
> that without a race condition?
> 
> A less desirable approach would be to put the call to the mutex
> initializing function at the beginning of the body of every public
> function. The problem would then be that we'd need a single list of
> all mutex objects in that function, so we'd need some way to make sure
> that list stayed consistent with all instances of
> CAIRO_MUTEX_DECLARE.
> 
> And this wouldn't be any less racy, but could at least be documented
> that some public cairo function call must be called before starting up
> non-primary threads. (That's a pretty ugly interface, so hopefully we
> can avoid having to document it that way.)
> 
On win32 there is DllMain() which could be used to intialize 'global'
synchronization objects in a thread safe manner. (It is guaranteed that
no other threads are started during DLL initialization).

If I understand you suggestion correctly something like

#define LOCK(hLock) do { if (!hLock) hLock = CreateMutex(...); \
			WaitForSingleObject(hLock,INFINITE); } while (0)
#define UNLOCK(hLock) ReleaseMutex(hLock)

would be possible - if one is willing to leak the synchronizaion objects.
Does not solve the intialization race though.

	Hans

-------- Hans "at" Breuer "dot" Org -----------
Tell me what you need, and I'll tell you how to
get along without it.                -- Dilbert


More information about the cairo mailing list