/* ZazouMiniWebServer Copyright (C) 2003-2011 Xavier Garreau This file is part of ZazouMiniWebServer. ZazouMiniWebServer is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. ZazouMiniWebServer is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with ZazouMiniWebServer; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _ZTHREADPOOL_H #define _ZTHREADPOOL_H 1 #include "ZOSAL.h" #include #include #include // #define zprintf printf #define zprintf /* *** ZRequest class *** */ class ZRequest { public: ZRequest () {}; virtual ~ZRequest() {}; }; /* *** End ZRequest class *** */ /* *** ZReqProvider class *** */ class ZReqProvider { HANDLE_MUTEX queue_mutex; HANDLE_SEMAPHORE request_semaphore; std::queue requests; public: ZReqProvider(); ~ZReqProvider(); BYTE request_add (ZRequest* r); ZRequest* request_get(); protected: void CloseSyncObjects(); }; /* *** End ZReqProvider class *** */ /* *** ZThread class *** */ class ZThread { HANDLE_MUTEX stop_mutex; HANDLE_THREAD handle; volatile BOOL stop_thread; static void __cdecl start(void* data); ZReqProvider* request_provider; void run(); public: template static T* create(ZReqProvider* rp); HANDLE_THREAD get_handle() { return handle; } ~ZThread(); BYTE stop(); protected: ZThread(); BOOL should_stop(); virtual void handle_request(ZRequest* r) { std::cout << "WARNING: Default request handler called !" << std::endl << std::endl; delete r; } }; /* *** Template implementation *** */ template static T* ZThread::create(ZReqProvider* rp){ T* t = new T(); t->stop_thread = FALSE; t->request_provider = rp; t->handle = (HANDLE_THREAD)_beginthread(ZThread::start, 0, t); if (t->handle == (HANDLE_THREAD)-1) { delete t; return NULL; } return t; } /* *** End ZThread class *** */ /* *** ZThreadPool class *** */ template class ZThreadPool : public ZReqProvider { std::queue pool; public: ZThreadPool(WORD min_threads = 1); WORD addSomeThreads(WORD nb_threads = 1); WORD delSomeThreads(WORD nb_threads = 1); ~ZThreadPool(); }; /* *** Template implementation *** */ template ZThreadPool::ZThreadPool(WORD min_threads) : ZReqProvider() { addSomeThreads(min_threads); } template WORD ZThreadPool::addSomeThreads(WORD nb_threads) { T* t; WORD i = 0; WORD created = 0; for (i = 0; i < nb_threads; ++i) { t = ZThread::create(this); if (t) { pool.push(t); ++created; } else { print_dbg("\nERROR: in ZThreadPool, could not create ZThread.\n\n"); } } return created; } template WORD ZThreadPool::delSomeThreads(WORD nb_threads) { DWORD nbThreadsInPool = static_cast(pool.size()); WORD i = 0; WORD deleted; if (nb_threads>=nbThreadsInPool) { nb_threads = nbThreadsInPool - 1; } deleted = nb_threads; // On dit aux threads qu'ils peuvent s'arrêter while (nb_threads--) { pool.front()->stop(); pool.pop(); } return deleted; } template ZThreadPool::~ZThreadPool() { DWORD nbThreads = static_cast(pool.size()); HANDLE_THREAD* thread_handles_tab = new HANDLE_THREAD[nbThreads*sizeof(HANDLE)]; WORD i = 0; // On dit aux threads qu'ils peuvent s'arrêter while (!pool.empty()) { ZThread* t = pool.front(); thread_handles_tab[i++] = t->get_handle(); t->stop(); pool.pop(); } // Pour suppression des semaphores et mutexes // Et déblocage des threads CloseSyncObjects(); // Attente des threads // 1 par 1 parce que WaitForMultipleObjects est limité en nombre d'objets for (i = 0; i