#ifndef __OneTimeTimeout_h_ #define __OneTimeTimeout_h_ #include "../shared/SelectableRequestQueue.h" #include "../shared/Messages.h" #include "../shared/ThreadClass.h" /* This provides a simple timer. You submit a request. When the timer * goes off you get the request back. You can subclass the request if you * want more information in the callback. * * There is no way to cancel a callback. The idea is that when you are * done with an object, you will erase any references to it. If you get * a callback and you don't know where it came from, you ignore it. * * This was made, in large part, to support HttpThread.C. That thread will * expect the HTTP server to hand us a complete request very quickly. If not, * we assume something is wrong and delete the socket. When the request is * completed, HttpThread.C will pass the request we got from the server to * the another unit, and will not remember anything more about the request. * * HttpThread.C will only need one of these per socket. (SCGI only sends * one request per socket.) So we don't need any other payload in the request. * The request always contains a pointer to the socket. (It has to!) When * HttpThread.C gets timeout it will check if it's still managing that socket. * If so, it deletes that socket. If not, it ignores the request. * * Note that DeanManTimer.h provides an interesting alternative. That works * with requests that have to be repeated constantly. */ class OneTimeTimeoutRequest : public Request { private: const int _finalId; RequestListener *const _finalDestination; const TimeVal _timeout; const SocketInfo::SerialNumber _socketSerialNumber; // For debug only!!! public: OneTimeTimeoutRequest(SocketInfo *socket, TimeVal timeout, int finalId, RequestListener *finalDestination) : Request(socket), _finalId(finalId), _finalDestination(finalDestination), _timeout(timeout), _socketSerialNumber(SocketInfo::getSerialNumber(socket)) { } void send(); TimeVal getTimeout() const { return _timeout; } }; class OneTimeTimeoutThread : ThreadClass { private: enum { mtSubmit, mtQuit }; SelectableRequestQueue _incoming; // Our standard ISAM design pattern. We have list of OneTimeTimeoutRequest // pointers. They can be indexed by timeout (not unique), socket (not // unique), or request pointer (unique). typedef std::pair< TimeVal, OneTimeTimeoutRequest * > ByTimeItem; typedef std::set< ByTimeItem > ByTime; ByTime _byTime; typedef std::pair< SocketInfo *, OneTimeTimeoutRequest * > BySocketItem; typedef std::set< BySocketItem > BySocket; BySocket _bySocket; typedef std::set< OneTimeTimeoutRequest * > ByRequest; ByRequest _byRequest; void remove(OneTimeTimeoutRequest *request); void remove(SocketInfo *socket); void add(OneTimeTimeoutRequest *request); static OneTimeTimeoutThread *_instance; protected: void threadFunction(); public: OneTimeTimeoutThread(); ~OneTimeTimeoutThread(); void submit(OneTimeTimeoutRequest *request); static void initialize(); static OneTimeTimeoutThread &getInstance() { return *_instance; } }; #endif