[wx-dev] wxThread, thread local storage and wxLog
Armel Asselin
asselin.armel at wanadoo.fr
Wed Aug 9 01:39:07 PDT 2006
> AA> As an example, imagine multiple internet clients threads, each
> handling a
> AA> different web site: you want a log output per thread. In this case,
> only TLS
> AA> can help.
>
> Not at all. You can simply extend wxLog to include the id of the thread
> which generated the message (e.g. as another DoLog() argument) which would
> probably be much simpler. TLS is very useful, of course, but it's not
> really needed here, IMHO you rarely want to handle the log messages from a
> thread in the thread itself (if only because you can't access GUI from
> it).
doing this mean that the log itself must be aware of what to do of the
results coming from a particular thread, it seems to be intverted design: I
use my thread(s) to execute small tasks which may be relative to different
bigger tasks, and the log target should be bound to the big task... only
each small task will know.
> AA> I propose to add:
> AA> - static int wxThread::AllocateTlsEntry( int id ): id should be in a
> range
> AA> defined by wx, the returned value would be an offset for that id, we
> could
> AA> arrange to have id => offset mapping to be the same for all threads,
> it
> AA> would allow having global variables being initialized once with this
> offset
> AA> (avoiding frequent calls to AllocateTlsEntry)
> AA> - static void *wxThread::GetTlsEntry (int offset): returns the
> "offset"
> AA> entry of the TLS (a simple indirection)
> AA> - static void wxThread::SetTlsEntry (int offset, void *value) : set
> the
> AA> value (never deleted by tls)
> AA> static void wxThread::SetTlsEntry (int offset, wxObject *value, bool
> owned):
> AA> set the value, deleted at thread destruction if <owned>
>
> This directly corresponds to Win32/pthreads API so is not bad but is too
> low level to my taste. TLS slots are useful for associating a piece of
> data, of some type, with the thread. So in my own code I have a separate
> class for them:
yes it is low level and i'd be perfectly ok to use _in addition_ your
template based stuff.
note that I did not intend to store all of that stuff in the system TLS
(because of the potential limitations that you cited), but storing a
wxArrayPtr or something similar in the wxThread object.
> AA> For wxLog:
> AA> - potentially: add: static void wxLog::SetActiveTargetPerThread( bool
> AA> enable ): if !enable (default), active target is not in TLS but inside
> a
> AA> singleton as before.
>
> I don't like having 2 separate modes of operation for the same class. Of
> course, as I said, I don't believe having per-thread loggers is that
> useful
> at all, IMO just including the id of the logging thread is a much better
> idea. But if you do absolutely want to do it like this we'd need to have
> SetActiveTargetForThisThread(wxLog *log) which would store log pointer in
> the TLS and GetActiveTarget() would need to look in the TLS first and fall
> back to the global variable if the pointer is not set in the TLS. This
> would make it possible to use per-thread wxLog for some threads only.
OK having the system working by fallback looks to me a good way. but just
some ideas:
it will indeed fix the wxLogNull enable/disable pairing issue _if we put at
least a redirecting log target per thread_ so should not we at least add
that, from a user point of view it would not change anything? no?
> Also notice that there is a very finite number of TLS slots available so
> wxWidgets on its own shouldn't use more than one of them. Thus, if we use
> TLS for any internal needs, we need to allocate a single struct
> (wxPerThreadData) and put everything we need inside it.
(see above)
Armel
More information about the wx-dev
mailing list