Re: Using POSIX threads with Cocoa?
Re: Using POSIX threads with Cocoa?
- Subject: Re: Using POSIX threads with Cocoa?
- From: Vince Ackerman <email@hidden>
- Date: Wed, 21 Apr 2004 09:17:51 -0700
From: email@hidden
Subject: Re: Using POSIX threads with Cocoa?
Date: April 21, 2004 08:18:58 PDT
To: email@hidden
Cc: email@hidden
Michael and Dave,
Thanks. I have searched everywhere for documentation on pthreads and
can't find much definitive info... perhaps you could give me some
basic instruction in pthreads/mutex? I'm not sure what the following
are doing (if I could understand it, maybe I could write the same in
Cocoa):
// In TeleoEasy_Start, what are they initializing here? Maybe if I
understood the "big picture" of what mutex_init does it would answer a
lot of the other questions.
pthread_mutex_init( &teleoThreadMutex, NULL );
// What is the difference between "pthread_mutex_init" and
"pthread_create" and "pthread_join"?
pthread_create( &teleoInputThread, NULL, doInput, NULL );
// Fire up the timer thread
pthread_create( &teleoTimerThread, NULL, doTimer, NULL );
Apparently, the threads should never exit during the life of the app,
so I don't really care about the TeleoEasy_Continue() function. But are
the threads running if I don't call it? Does pthread_join() start the
threads or does pthread_create() do that? Maybe I'm not able to send
the set/get calls due to not calling this function and starting the
threads? They use it in main() after all the init stuff is done.
void TeleoEasy_Continue() // Waits for the library to exit
{
pthread_join( teleoInputThread, NULL );
pthread_join( teleoTimerThread, NULL );
pthread_mutex_destroy( &teleoThreadMutex );
}
Another question, if I detach a my own thread (the doinput thread, for
example) with NSThread, will the TeleEasy_Lock / Unlock calls within
that thread still work? Are the Lock/Unlock funtions acting on the
thread they are in, or locking the other threads? Dumb question I'm
sure, but as I mentioned, I don't understand threading as well as I'd
like to... As far as I can tell, the doinput thread reads characters
(get/set calls from the main thread) and passes them to the network
manager?
They have a great web site with good documentation online.... but some
of it is still over my head. If it would help, here's the main page
from their SDK documentation:
http://www.makingthings.com/products/documentation/teleo_user_guide/
teleo_application_sdk.html#teleo_easy
This is from their docs describing threading issues:
// ---------------- SNIP -------------------
One of the things that the Teleo Easy interface tries to do is hide
operating system details. A program built with Teleo Easy checks
interfaces for new characters, runs timers, and runs your code all at
the same time. The secret to this is that (where possible) Teleo Easy
creates program threads for each of the above activies. The ideal
situation is that you can do whatever you want in your code without
ever having to pause to check for incoming characters from the Teleo
Network or send timer events to the layers beneath. Similarly, you
should be able to call all the functions you like without concern that
they'll be interrupted half way through by another thread.
Almost all thread safety issues are dealt with by the TeleoEasy
framework. If your code is being activated by an update callback it is
guaranteed to be not interrupted by another thread. The only case we
can't help you with is the main program thread. If you call TeleoEasy
routines from within your main program thread you need to call
TeleoEasy_Lock( ) first and TeleoEasy_Unlock( ) afterwards. This is a
small sacrifice for having to never worry about checking files or
timers.
TeleoEasy_Lock( );
proxy_valueGet( ... &value );
TeleoEasy_Unlock( );
// ---------------- End --------------------------------------
Guess the timer has to run separately. Their documentation allows for
low level control of their hardware if you want to get that deep ( I
don't), but it does say that the timer thread sends timer events to the
lower level managers to check for data on the network etc. Don't know
if this helps, but here's a paragraph from their docs related to timer
events:
// ---------------- SNIP -------------------
The last methods to consider on the Channel are those to do with timer
events. The owner of the Channel has the responsibility at certain
times to call the Channel back with timer events. The Channel uses the
(*timerRequest)( ) callback to tell its owner when it wants these
events. When the events are activated, the owner should call the
Channel using the TC_timerEvent( ) function. A parameter passed to the
TC_timerEvent( ) function is ms - an estimate of roughly the timer
interval. This is to create some flexibility for the implemention of
the timer. Internally, the Channel is designed with a 10ms event timer
in mind, this should be considered the optimal timer interval.
Internally the Channel uses the event for two purposes: the first is to
check for abandoned incoming messages. Say, for example, the Channel is
parsing characters in the middle of receiving a message, but the lower
layers lose the rest of the incoming packet's characters. Without some
kind of timer, the parser would just sit there mid-message waiting for
the rest. What's worse is that when the next (presumably good) message
comes along, it would be lost too since the parser would think the
first characters of the new message really were the rest of the old
one. So to prevent this situation, each time the Channel receives a
timerEvent it increments an internal clock. Whenever a character is
received by the Channel it clears that clock. So if the clock value
ever exceeds a certain time, it is decided that the message has been
corrupted and the parser is reset.
The other thing timer events are used for is to manage the outgoing
message queue (if enabled via TC_sendQueueEnable( ) ). If the message
queue is enabled and if ever a write error occurs when sending a
message, the message is copied and queued. The send is attempted again
later during one of the subsequent timer events calls.
So the timer is enabled when either one of the following is true: the
parser is not in it's initial waiting state (i.e. it's processing an
incoming message) or there was a send failure and a message is waiting
in the send queue.
The use of timer events is not compulsory. The consequences of not
using them are two-fold: first, there is no way to detect dead messages
in the parser - so messages that get corrupted will probably also
corrupt the next message. Second, there is no way to implement a send
queue (since there is never any time allocated to retry the send. So if
you're planning to not use the timers you will need not use the send
queue.
Timers are not necessary until they are requested, and can stop once
they are unrequested again, although it is not an error to ignore the
(*timerRequest)( ) function call and run the timerEvents all the time.
//------------------------End----------------------------------------
Thanks for your help! Sorry if this is taking up bandwidth......
Vince Ackerman
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.