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
_______________________________________________
Gnustep-dev mailing list
Gnustep-dev@gnu.org
http://lists.gnu.org/mailman/listinfo/gnustep-dev