From 9f6eedfaf385304b4d5aefccd51e97ff92f6e819 Mon Sep 17 00:00:00 2001 From: Tyler Dauwalder Date: Tue, 1 Oct 2002 07:22:11 +0000 Subject: [PATCH] + Renamed and moved from src/servers/registrar/ThreadManager.{h,cpp} + Fixed iteration bugs + Added more complete debugging output git-svn-id: file:///srv/svn/repos/haiku/trunk/current@1320 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/app/RegistrarThreadManager.h | 45 ++++ src/kits/app/RegistrarThreadManager.cpp | 245 +++++++++++++++++++ 2 files changed, 290 insertions(+) create mode 100644 headers/private/app/RegistrarThreadManager.h create mode 100644 src/kits/app/RegistrarThreadManager.cpp diff --git a/headers/private/app/RegistrarThreadManager.h b/headers/private/app/RegistrarThreadManager.h new file mode 100644 index 0000000000..ed3534f49a --- /dev/null +++ b/headers/private/app/RegistrarThreadManager.h @@ -0,0 +1,45 @@ +//---------------------------------------------------------------------- +// This software is part of the OpenBeOS distribution and is covered +// by the OpenBeOS license. +//--------------------------------------------------------------------- +/*! + \file RegistrarThreadManager.h + RegistrarThreadManager interface declaration +*/ + +#ifndef REGISTRAR_THREAD_MANAGER_H +#define REGISTRAR_THREAD_MANAGER_H + +#include +#include + +#include + +class RegistrarThread; + +class RegistrarThreadManager : public BHandler { +public: + RegistrarThreadManager(); + ~RegistrarThreadManager(); + + // BHandler virtuals + virtual void MessageReceived(BMessage* message); + + // Thread management functions + status_t LaunchThread(RegistrarThread *thread); + status_t CleanupThreads(); + status_t ShutdownThreads(); + status_t KillThreads(); + + uint ThreadCount() const; + +private: + static const uint kThreadLimit = 12; + + std::list::iterator& RemoveThread(std::list::iterator &i); + + std::list fThreads; + uint fThreadCount; +}; + +#endif // THREAD_MANAGER_H diff --git a/src/kits/app/RegistrarThreadManager.cpp b/src/kits/app/RegistrarThreadManager.cpp new file mode 100644 index 0000000000..6cf043c862 --- /dev/null +++ b/src/kits/app/RegistrarThreadManager.cpp @@ -0,0 +1,245 @@ +//---------------------------------------------------------------------- +// This software is part of the OpenBeOS distribution and is covered +// by the OpenBeOS license. +//--------------------------------------------------------------------- +/*! + \file RegistrarThreadManager.cpp + RegistrarThreadManager implementation +*/ + +#include "RegistrarThreadManager.h" + +#include +#include + +#include + +//#define DBG(x) x +#define DBG(x) +#define OUT printf + +/*! + \class RegistrarThreadManager + \brief RegistrarThreadManager is the master of all threads spawned by the registrar + +*/ + +//! Creates a new RegistrarThreadManager object +RegistrarThreadManager::RegistrarThreadManager() + : fThreadCount(0) +{ +} + +// destructor +/*! \brief Destroys the RegistrarThreadManager object, killing and deleting any still + running threads. +*/ +RegistrarThreadManager::~RegistrarThreadManager() +{ + KillThreads(); +} + +// MessageReceived +/*! \brief Handles \c B_REG_MIME_UPDATE_THREAD_FINISHED messages, passing on all others. + + Each \c B_REG_MIME_UPDATE_THREAD_FINISHED message triggers a call to CleanupThreads(). +*/ +void +RegistrarThreadManager::MessageReceived(BMessage* message) +{ + switch (message->what) { + case B_REG_MIME_UPDATE_THREAD_FINISHED: + { + CleanupThreads(); + break; + } + + default: + { + BHandler::MessageReceived(message); + break; + } + } +} + +// LaunchThread +/*! \brief Launches the given thread, passing responsiblity for it onto the + RegistrarThreadManager object. + + \param thread Pointer to a newly allocated \c RegistrarThread object. + + If the result of the function is \c B_OK, the \c RegistrarThreadManager object + assumes ownership of \a thread; if the result is an error code, it + does not. + + \return + - \c B_OK: success + - \c B_NO_MORE_THREADS: the number of concurrently allowed threads (defined by + RegistrarThreadManager::kThreadLimit) has already been reached + - \c B_BAD_THREAD_STATE: the thread has already been launched + - other error code: failure +*/ +status_t +RegistrarThreadManager::LaunchThread(RegistrarThread *thread) +{ + status_t err = thread ? B_OK : B_BAD_VALUE; + if (!err) + err = fThreadCount < kThreadLimit ? B_OK : B_NO_MORE_THREADS; + + if (!err) { + fThreads.push_back(thread); + fThreadCount++; + err = thread->Run(); + if (err) { + std::list::iterator i; + for (i = fThreads.begin(); i != fThreads.end(); i++) { + if ((*i) == thread) { + fThreads.erase(i); + fThreadCount--; + break; + } + } + } + } + if (!err) + DBG(OUT("RegistrarThreadManager::LaunchThread(): launched new '%s' thread, " + "id %ld\n", thread->Name(), thread->Id())); + return err; +} + +// CleanupThreads +/*! \brief Frees the resources of any threads that are no longer running + + \todo This function should perhaps be triggered periodically by a + BMessageRunner once we have our own BMessageRunner implementation. +*/ +status_t +RegistrarThreadManager::CleanupThreads() +{ + std::list::iterator i; + for (i = fThreads.begin(); i != fThreads.end(); ) { + std::list::iterator next = i; + next++; + + if (*i) { + if ((*i)->IsFinished()) { + DBG(OUT("RegistrarThreadManager::CleanupThreads(): Cleaning up thread %ld\n", + (*i)->Id())); + RemoveThread(i); + } + } else { + OUT("WARNING: RegistrarThreadManager::CleanupThreads(): NULL mime_update_thread_shared_data " + "pointer found in and removed from RegistrarThreadManager::fThreads list\n"); + i = fThreads.erase(i); + } + + i = next; + } + return B_OK; +} + +// ShutdownThreads +/*! \brief Requests that any running threads quit and frees the resources + of any threads that are no longer running. + + \todo This function should be called during system shutdown around + the same time as global B_QUIT_REQUESTED messages are sent out. +*/ +status_t +RegistrarThreadManager::ShutdownThreads() +{ + std::list::iterator i; + for (i = fThreads.begin(); i != fThreads.end(); ) { + std::list::iterator next = i; + next++; + + if (*i) { + if ((*i)->IsFinished()) { + DBG(OUT("RegistrarThreadManager::ShutdownThreads(): Cleaning up thread %ld\n", + (*i)->Id())); + RemoveThread(i); + } else { + DBG(OUT("RegistrarThreadManager::ShutdownThreads(): Shutting down thread %ld\n", + (*i)->Id())); + (*i)->AskToExit(); + } + } else { + OUT("WARNING: RegistrarThreadManager::ShutdownThreads(): NULL mime_update_thread_shared_data " + "pointer found in and removed from RegistrarThreadManager::fThreads list\n"); + i = fThreads.erase(i); + } + + i = next; + } + + /*! \todo We may want to iterate back through the list at this point, + snooze for a moment if find an unfinished thread, and kill it if + it still isn't finished by the time we're done snoozing. + */ + + return B_OK; +} + +// KillThreads +/*! \brief Kills any running threads and frees their resources. + + \todo This function should probably be called during system shutdown + just before kernel shutdown begins. +*/ +status_t +RegistrarThreadManager::KillThreads() +{ + std::list::iterator i; + for (i = fThreads.begin(); i != fThreads.end(); ) { + std::list::iterator next = i; + next++; + + if (*i) { + if (!(*i)->IsFinished()) { + DBG(OUT("RegistrarThreadManager::KillThreads(): Killing thread %ld\n", + (*i)->Id())); + status_t err = kill_thread((*i)->Id()); + if (err) + OUT("WARNING: RegistrarThreadManager::KillThreads(): kill_thread(%ld) failed with " + "error code 0x%lx\n", (*i)->Id(), err); + } + DBG(OUT("RegistrarThreadManager::KillThreads(): Cleaning up thread %ld\n", + (*i)->Id())); + RemoveThread(i); + } else { + OUT("WARNING: RegistrarThreadManager::KillThreads(): NULL mime_update_thread_shared_data " + "pointer found in and removed from RegistrarThreadManager::fThreads list\n"); + fThreads.erase(i); + } + + i = next; + } + return B_OK; +} + +// ThreadCount +/*! \brief Returns the number of threads currently under management + + This is not necessarily a count of how many threads are actually running, + as threads may remain in the thread list that are finished and waiting + to be cleaned up. + + \return The number of threads currently under management +*/ +uint +RegistrarThreadManager::ThreadCount() const +{ + return fThreadCount; +} + +// RemoveThread +/*! \brief Deletes the given thread and removes it from the thread list. +*/ +std::list::iterator& +RegistrarThreadManager::RemoveThread(std::list::iterator &i) +{ + delete *i; + fThreadCount--; + return (i = fThreads.erase(i)); +} +