This is the mail archive of the
libstdc++@sourceware.cygnus.com
mailing list for the libstdc++ project.
Re: Thread-safe libio [was Re: BUG in libstdc++ ... libio ... pthreads]
- To: libstdc++@sourceware.cygnus.com
- Subject: Re: Thread-safe libio [was Re: BUG in libstdc++ ... libio ... pthreads]
- From: Andreas Gruenbacher <a.gruenbacher@infosys.tuwien.ac.at>
- Date: Sat, 15 May 1999 01:16:29 +0200
- Organization: Technical University of Vienna
- References: <B7A6155A71B6D211BB2D0008C7B250B709065B@daytonmsg.ball.com>
"Edwards, Phil" wrote:
>
> + #1 Synchronization mechanism
> [snip]
> + b) use a mutex to protect the buffers.
> + Advantage: possibly more efficient
> + Disadvantage: ?
>
> Possibly more efficient than... what? flockfile()? Could be. If we don't
> want to do a bunch of system calls (on whatever platform), we should use an
> exclusion mechanism that runs in user space. POSIX would be wonderful, but
> my experience thus far is that it's still being tweaked and debugged in the
> most common platforms.
>
> I wrote a semaphore wrapper library to help protect client code from this.
> I'm in the midst of rewriting it to use either POSIX, or native Unix
> semctl()-family, or native Win32 stuff as its underlying implementation,
> chosen at compile time. Thus, synchronization sections of client code are
> transparently portable. Doing it isn't all that difficult, but making the
> wrappers /efficient/ is troublesome.
>
> We would either have to use a similar wrapping method, or try POSIX (since
> we're discussing pthreads anyhow), or...?
How about using pthread synchronization on platforms that support it,
and flock() or semaphores on other platforms, as log as pthreads are not
available? Win32 platforms could as well use Win32 calls, of course.
flockfile() is a thread-specific extension, so non-thread platforms may
not support it.
Deciding which of mutexes, semaphores, or flock() to use at library
build time should be possible quite efficiently, I suppose. All the code
necessary can be wrapped in a synchronization class similar to the one
attached, and will be inlined.
Another issue that arises is exception safety. If one of the streambuf
methods throws, the lock is never released by the current
cleanup_region_... code. An approach similar to the attached Monitor
seems preferable. I'm not sure how well that interacts with C code,
however...
> + #2 Choosing thread-safety
> + The user should be able to choose between a thread-safe and a
> + non-thread-safe implementation; preferably on a per-object basis. This
> + could be supported by:
> [snip a couple of ideas with "disadvantage: non-standard extension"]
>
> If we give them that choice, it'll be non-standard /however/ we do it. :-)
> Every method I think of gets shot down by my own brain before I finish
> typing the paragraph, however.
How about a flag in streambuf that controls thread-safetyness of stdio
and iostreams? That way, both C and C++ code could share the same flag.
On the other hand, an arbitrary streambuf that isn't derived from the
libio streambuf couldn't be used as a replacement of the libio streambuf
anymore. (Can that be done currently??)
Andreas
-----------------------------------------------------------------------
Andreas Gruenbacher, Vienna University of Technology
a.gruenbacher@infosys.tuwien.ac.at
Contact information: http://www.infosys.tuwien.ac.at/~agruenba
#include <pthread.h>
class Monitor {
public:
Monitor() {
pthread_mutex_init(&mutex, NULL);
}
~Monitor() {
pthread_mutex_destroy(&mutex);
}
pthread_mutex_t get_mutex() {
return mutex;
}
class Lock;
friend class Lock;
friend class ConditionVariable;
class Lock {
public:
Lock(Monitor& monitor) : monitor(monitor) {
pthread_mutex_lock(&monitor.mutex);
}
~Lock() {
pthread_mutex_unlock(&monitor.mutex);
}
private:
Monitor& monitor;
};
private:
pthread_mutex_t mutex;
};
// Example class using Monitor
class SynchronizedSomething : public Monitor {
int monitored_value;
public:
void set(int value) {
Monitor::Lock lock(*this);
monitored_value = value;
}
int get() {
Monitor::Lock lock(*this);
return monitored_value;
}
};