gnustep-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: NSSound Code Review


From: David Chisnall
Subject: Re: NSSound Code Review
Date: Thu, 30 Jul 2009 15:12:05 +0100

On 30 Jul 2009, at 14:37, David Ayers wrote:

Am Mittwoch, den 29.07.2009, 21:23 -0500 schrieb Stef Bidi:
David C.:
I took a quick look at your comments and did some quick
modifications... uploaded the results.  There were a few things that
will need a lot more work, so I left those as is for now.

David A.:
I am using threads and locks, and unfortunately it's the only way for
me to get where I want to be (streaming audio data).  If I understood
your replies correctly, your suggesting using pthread instead of
NSLock and NSConditionLock?  David C. expressed some concerns on how
I'm using the locks as well.

Yes, well, almost...

I am suggesting that you use the objc_thread threading abstraction layer
in libobjc instead of NSThread.  David C. is suggesting to use pthread
directly and avoid the abstraction layer.

Wait, no I'm not. I am in no way suggesting that this code should not use NSThread / NSLock. I am suggesting that NSCondition might be a better fit for some of this code than NSConditionLock, and that it should wait until NSCondition is committed to GNUstep before being finalised.

I believe that David C. believes that all deployments we care about have
a pthread library they /could/ use.

Correct. There is even the MIT pthreads package for systems which have no kernel support for threading (and, yes, it does run on OPENSTEP) and the GNU pth library which provides cooperative multithreading, if you're that-way inclined.

I believe he believes both your
code and GNUstep proper should simply use that independent of what the
objc_runtime and the gcc runtime uses.

No, I believe that this code should use the abstractions provided by GNUstep. Putting platform-specific code anywhere other than the few bits of Foundation designed as platform abstractions (NSObject, NSThread, NSRunloop, and so on) is a terrible idea and not one I would ever advocate unless profiling showed that it was completely unavoidable.

Foundation IS (among other things) a platform abstraction layer. Using another platform abstraction layer in Foundation code is just silly.

I'm not sure whether he believes that gcc already uses pthreads under
the abstraction layers for $(ALL_RELEVANT_PLATFORMS) or not.  From his
last reply I would infer that he may believe that we simply shouldn't
have to care.

GCC has no notion of threads, with the exception of the __thread keyword which GNUstep does not use because it is not supported by GCC 2.96. GCC does not use pthreads or any other threading layer when generating code, except for __thread when it uses some platform (and often linker)-specific code.

He does believe, that by using pthreads directly we can make use of some
optimizations / avoid inefficiencies that the abstraction layers
introduce.

In NSLock, not in other code.  Other code should use NSLock directly.

I believe we do have to care.  GNUstep currently doesn't define which
platforms it supports.  We simply do not know.  I do know that the
discussions on the mailing list is not an indication of what is in use.

We require a POSIX platform. POSIX threads are part of POSIX. Ten years ago, they were a poorly-supported part of POSIX. Now they are standard everywhere, including Windows, QNX, VxWorks and Symbian via their respective POSIX layers.

I also believe that the approach to bypass NSThread by using the
abstraction layers is fairly common practice.  Most use cases I know
have a very limited interaction with the rest of the system and are
often performance critical. They are written in plain C, so no messages
are being passed, no notifications processed, just plain grunt work in
C.  This is also what Apple seems to be doing.

I don't disagree with doing this in performance-critical application code. There may be places in GNUstep where it is required, but this is emphatically not one. The cost of the system calls for sending the data to the device is orders of magnitude more than the cost of sending a message, and so the cost of sending a message which calls a function to acquire a lock, rather than calling a function directly is tiny. The cost of spawning a thread, similarly, is much greater than the cost of sending a message, so we gain nothing by doing this.

As always, profiling should come before optimisation. Not doing this is the reason why the GNUstep text system is such a mess. Start with maintainable abstractions, and if they prove to be too slow then short- circuit them, but don't throw away abstractions just because they add a tiny bit of overhead.

Another scenario where threading implementations can be added to the
executable are language bridges. Java, Ruby, Python... I'm not sure how
JIGS/RIGS work but I have seen bridges that start a VM in a separate
thread of the same process.

Reading the release notes, it appears that the Java bridge was one of the main reasons why Cocoa always runs in multithreaded mode. Java- Cocoa code uses Java threads, which are userspace threads with an N:M threading model, unlike NSThread which always maps to the a kernel or libc thread.

The only way to keep the executable sane and debugable in my view is if all components share the "native" threading environment. The only way I
see to make this possible is to use the abstraction layers.

Fortunately, GNUstep has a sane set of abstractions. NSThread and the classes declared in NSLock.h.

Of course I'd also like to see the optimizations that David C. is aiming
at.  I just don't believe the way to achieve it is by bypassing the
abstraction layers.  My approach would be to optimize the abstraction
layers.

I didn't propose optimisations here. When I rewrote the NSLock classes to use pthreads, I halved the amount of code and added an implementation of NSCondition. To me, less code which does more is more maintainable.

The fact that, because it isn't using the buggy and largely- unmaintained abstraction layer in libobjc is an added bonus. The code in libobjc uses recursive mutexes. It does not create or destroy threads, and it does not use condition variables. This means that the functions for doing any of these things in libobjc are not tested by libobjc and in some cases are just stub implementations which always return NULL. Depending on these, rather than well-tested pthread implementations does not make sense.

I'd be happy to entertain suggestions to use some other threading abstraction library as long as:

1) It is well supported.
2) It is widely used (so we aren't the only ones finding bugs in it.

However, since most of the platforms where we run provide POSIX threads in their libc or in a standard system library, there would also have to be a compelling reason for adding an extra dependency. The only platform we actively support where pthreads are not the native implementation is Windows - I wouldn't be averse to the idea of someone providing native Windows implementations of NSLock.m and NSThread.m, in addition to the pthread version, to eliminate the dependency on a pthread abstraction layer on this platform.

By keeping the threading code in the GNUstep threading classes, we retain the option of providing platform-specific versions if this is ever deemed desirable for a given platform.

David




reply via email to

[Prev in Thread] Current Thread [Next in Thread]