Passing a va_list between threads... can it be done?
Passing a va_list between threads... can it be done?
- Subject: Passing a va_list between threads... can it be done?
- From: Greg Hurrell <email@hidden>
- Date: Thu, 16 Mar 2006 18:13:09 +0100
I've currently got code like the following that has two types of method:
1. A method that takes a variable number of arguments
2. An equivalent method that accepts a va_list parameter
The first method is really just a wrapper for the second.
- (void)function:(NSString *)format, ...
{
va_list args;
va_start(args, format);
[self vFunction:format args:args];
va_end(args);
}
- (void)vFunction:(NSString *)format args:(va_list)args
{
// do something with args
}
Now this all works great but in some circumstances I would like be
able to pass the va_list parameter from one thread to another; the
basic flow is as follows:
1. In main thread, prepare the va_list
2. Detach worker thread, passing it the va_list
3a. Main thread continues on about its business
3b. At the same time the worker thread processes the va_list
The problem is that (as far as I know), the va_list is just a pointer
to an argument on the stack. If the method in the main thread
detaches the worker thread and then returns before the worker thread
is finished, the arguments that were previously on the stack will get
taken off the stack and the va_list pointer will become invalid; if
the worker thread continues working with it then at best it could get
garbage data and at worst could crash the app.
So my question is, does anyone know of an elegant workaround that
will allow me to safely pass a va_list from one thread to another? I
have spent some time thinking about solutions but before going too
far down that track I wanted to ask for some expert advice... I don't
know if it's even worth trying or if I'll just end up in a dead end.
Ideas I've played with so far:
1. Making copies of the arguments on the stack (to be freed later by
the worker thread), and passing a new va_list pointer to the work
thread (pointing to the copied arguments, not the originals on the
stack); sounds very complex and might be architecture-dependent.
2. Copying the arguments into an NSArray and passing that instead
(thus requiring me to rewrite the methods in the worker thread); but
this is quite complex and also will lead to some major breakage (will
no longer be able to use the va_list and call vprintf, NSLogv and
friends).
3. Use the C99 va_copy macro; but I can't find a clear indication of
*what* it does on Darwin/GCC (in the stdarg.h header it just defines
it as __builtin_va_copy) and so I can't be sure if it will help me in
this situation. Experimentation leads me to believe that it won't
help (ie. my app still crashes if I use va_copy). The clearest
description that I've been able to find of it so far is this one (for
Linux):
http://www.frech.ch/man/man3/va_copy.3.html
If anyone wants to know *why* I want to be able to pass a va_list
from one thread to another I'd be happy to provide the details, but
I've left it out here to keep this message short. (The short version:
I need to wrap up these method calls in an NSInvocation and
NSInvocation doesn't play nicely with methods that accept a variable
number of arguments, hence the need for the methods which accept a
va_list parameter; and I need the NSInvocations in the first place so
that I can put long-running processes in a queue and work through
them in a background thread.)
Cheers,
Greg
Attachment:
smime.p7s
Description: S/MIME cryptographic signature
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden