void wait () const;
private:
+ /**
+ * Copy constructor. Made
+ * private since copying these
+ * kinds of objects is a no-go.
+ */
+ PosixThreadManager (const PosixThreadManager &) {};
+
/**
* List of thread ids. This
* variable actually points to
* files including it, we use a
* void pointer instead.
*/
- void * const thread_id_list;
+ volatile void * const thread_id_list;
+
+ /**
+ * Mutex by which we guard all
+ * accesses to the thread list.
+ */
+ PosixThreadMutex list_mutex;
};
// wait for all threads, and
// release memory
wait ();
- delete reinterpret_cast<std::list<pthread_t>*>(thread_id_list);
+ list_mutex.acquire ();
+ if (thread_id_list != 0)
+ delete reinterpret_cast<std::list<pthread_t>*>(thread_id_list);
+ thread_id_list = 0;
+ list_mutex.release ();
}
std::list<pthread_t> &tid_list
= *reinterpret_cast<std::list<pthread_t>*>(thread_id_list);
+ list_mutex.acquire ();
tid_list.push_back (pthread_t());
+ pthread_t *tid = &tid_list.back();
+ list_mutex.release ();
// start new thread. retry until
// we either succeed or get an
int error = 0;
do
{
- error = pthread_create (&tid_list.back(), 0, fun_ptr, fun_data);
+ error = pthread_create (tid, 0, fun_ptr, fun_data);
}
while (error == EAGAIN);
- Assert (error == 0, ExcInternalError());
+ AssertThrow (error == 0, ExcInternalError());
}
void
PosixThreadManager::wait () const
{
+ list_mutex.acquire ();
std::list<pthread_t> &tid_list
= *reinterpret_cast<std::list<pthread_t>*>(thread_id_list);
+ // wait for all the threads in
+ // turn
for (std::list<pthread_t>::iterator i=tid_list.begin();
i != tid_list.end(); ++i)
pthread_join (*i, 0);
+
+ // now we know that these threads
+ // have finished, remove their
+ // tid's from the list. this way,
+ // when new threads are spawned
+ // and waited for, we won't wait
+ // for expired threads with their
+ // invalid handles again
+ tid_list.clear ();
+
+ list_mutex.release ();
}
# endif
<h3>base</h3>
<ol>
+ <li> <p>
+ Fixed: The <code class="class">PosixThreadManager</code> called
+ its <code class="member">wait</code> function in the
+ destructor. If this had been called before already, then the
+ same threads would have been waited for twice, which invokes
+ undefined behavior. This is fixed by making sure that <code
+ class="member">wait</code> removes the id's of the threads it
+ has already waited for, and so calling it more than once will
+ not wait for threads which have already been waited for.
+ <br>
+ (Michael Anderson, WB 2003/01/16)
+ </p>
+
<li> <p>
Fixed: The <code class="class">Subscriptor</code> uses a counter to
count how many <code class="class">SmartPointer</code> objects subscribe
the assumption that the variable cannot change between two subsequent
reads.
<br>
- (Michael Anderson, WB 2003/01/11)
+ (WB 2003/01/11)
</p>
<li> <p>