JC> On (31 Aug 97) Darin Mcbride wrote to Jerry Coffin...
DM> Hmmm... when I looked at the code, it didn't look
DM> too bad to switch...
DM> mind you, I probably have a little more experience with OS/2
DM> semaphores, so it'd just look easier to me. :-)
JC> The problem wouldn't have been in changing the class itself. It would
JC> have been in changing the code that depended upon the class...
Hmmm... so the code depended on real semaphoring in Win32, but on events in
OS/2? That's wierd code, Jerry. :-)
DM> The actual code is an IsClaimed() function to see if the currently
DM> running thread owns the semaphore. It's primarily for assertions -
DM> make sure that we are currently inside our semaphore... i.e.
DM> template
DM> class SafeQueue
DM> {
DM> // ...
DM> private:
DM> DoPush(const T& t)
DM> {
DM> assert(GetSemaphore().IsClaimed());
DM> ...
DM> }
DM> // ...
DM> };
DM> Any code calling DoPush should have already claimed the semaphore
DM> before calling DoPush().
JC> Hmm...presumably, there's a public Push() that's basically something
JC> like:
JC> Push(const T &t) {
JC> GetSemaphore().Claim();
JC> DoPush(t);
JC> GetSemaphore().Release();
JC> }
Not quite. Seeing as I've posted the code already... ;-) I have a SemUse
object type that takes a semaphore object. On construction, it claims the
semaphore, on destruction it releases the semaphore.
So, I have a few push operations.
1. push single T.
2. push from T* begin to T* end.
3. push size_type len starting from T* buf.
All of these should claim the semaphore first.
After realizing the overhead in the DoPush, I've since changed 2 & 3 not to
use DoPush, so I could move the DoPush code to the public function.
I also have DoPop(), and const & non-const _front() functions hidden behind
the glass. Originally I tried to put as much implementation details in
private members, and simply call them from public functions. But that
started looking too slow for a circular queue that was supposed to be running
in a high priority background thread. :-) While in debug mode, I don't
worry about the overhead of determining if I own the semaphore, one of the
design goals was to get full throughput on a 115200bps serial port on my
486/66, so "release-mode" we should not be making more calls to the kernal
than I have to (which may force me to write a new semaphore class which uses
gcc's fmutex rather than OS/2's mutex API).
JC> ? Offhand, it doesn't seem like the fact that a semaphore is involved
JC> should be part of the interface.
Interface? If you mean that the caller to the queue shouldn't know, I agree.
The caller doesn't. The class does.
JC> However, this leave a question in my mind as to whether it makes sense
JC> to separate obtaining the semaphore from the code that accesses the
JC> resource protected by that semaphore. I'm not sure it wouldn't be
JC> better to simly merge the two instead of trying to ensure that it has
JC> happened with an assert.
It has been mostly remerged. Not that it matters too much - the private
members are all inline anyway.
DM> That is the ONLY reason I have for it. I do NOT have a "who owns
DM> it?" function. If you want to know if someone else has it, try to
DM> claim with a 0 timeout... but it doesn't tell who.
JC> Ah, that at least eliminates the danger of any kind of race condition.
Jerry, I may be new to multithreading, but not THAT new. ;-)
--- Maximus/2 3.01
---------------
* Origin: Tanktalus' Tower BBS (1:250/102)
|