Back to index

lightning-sunbird  0.9+nobinonly
nsTimerImpl.h
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * ***** BEGIN LICENSE BLOCK *****
00005  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00006  *
00007  * The contents of this file are subject to the Mozilla Public License Version
00008  * 1.1 (the "License"); you may not use this file except in compliance with
00009  * the License. You may obtain a copy of the License at
00010  * http://www.mozilla.org/MPL/
00011  *
00012  * Software distributed under the License is distributed on an "AS IS" basis,
00013  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00014  * for the specific language governing rights and limitations under the
00015  * License.
00016  *
00017  * The Original Code is mozilla.org code.
00018  *
00019  * The Initial Developer of the Original Code is
00020  * Netscape Communications Corporation.
00021  * Portions created by the Initial Developer are Copyright (C) 2001
00022  * the Initial Developer. All Rights Reserved.
00023  *
00024  * Contributor(s):
00025  *   Stuart Parmenter <pavlov@netscape.com>
00026  *
00027  * Alternatively, the contents of this file may be used under the terms of
00028  * either of the GNU General Public License Version 2 or later (the "GPL"),
00029  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00030  * in which case the provisions of the GPL or the LGPL are applicable instead
00031  * of those above. If you wish to allow use of your version of this file only
00032  * under the terms of either the GPL or the LGPL, and not to allow others to
00033  * use your version of this file under the terms of the MPL, indicate your
00034  * decision by deleting the provisions above and replace them with the notice
00035  * and other provisions required by the GPL or the LGPL. If you do not delete
00036  * the provisions above, a recipient may use your version of this file under
00037  * the terms of any one of the MPL, the GPL or the LGPL.
00038  *
00039  * ***** END LICENSE BLOCK ***** */
00040 
00041 #ifndef nsTimerImpl_h___
00042 #define nsTimerImpl_h___
00043 
00044 //#define FORCE_PR_LOG /* Allow logging in the release build */
00045 
00046 #include "nsITimer.h"
00047 #include "nsVoidArray.h"
00048 #include "nsIThread.h"
00049 #include "nsITimerInternal.h"
00050 #include "nsIObserver.h"
00051 
00052 #include "nsCOMPtr.h"
00053 
00054 #include "prlog.h"
00055 
00056 #if defined(PR_LOGGING)
00057 static PRLogModuleInfo *gTimerLog = PR_NewLogModule("nsTimerImpl");
00058 #define DEBUG_TIMERS 1
00059 #else
00060 #undef DEBUG_TIMERS
00061 #endif
00062 
00063 #define NS_TIMER_CLASSNAME "Timer"
00064 #define NS_TIMER_CID \
00065 { /* 5ff24248-1dd2-11b2-8427-fbab44f29bc8 */         \
00066      0x5ff24248,                                     \
00067      0x1dd2,                                         \
00068      0x11b2,                                         \
00069     {0x84, 0x27, 0xfb, 0xab, 0x44, 0xf2, 0x9b, 0xc8} \
00070 }
00071 
00072 enum {
00073   CALLBACK_TYPE_UNKNOWN   = 0,
00074   CALLBACK_TYPE_INTERFACE = 1,
00075   CALLBACK_TYPE_FUNC      = 2,
00076   CALLBACK_TYPE_OBSERVER  = 3
00077 };
00078 
00079 // Two timer deadlines must differ by less than half the PRIntervalTime domain.
00080 #define DELAY_INTERVAL_LIMIT    PR_BIT(8 * sizeof(PRIntervalTime) - 1)
00081 
00082 // Maximum possible delay (XXX rework to use ms rather than interval ticks).
00083 #define DELAY_INTERVAL_MAX      (DELAY_INTERVAL_LIMIT - 1)
00084 
00085 // Is interval-time t less than u, even if t has wrapped PRIntervalTime?
00086 #define TIMER_LESS_THAN(t, u)   ((t) - (u) > DELAY_INTERVAL_LIMIT)
00087 
00088 class nsTimerImpl : public nsITimer, public nsITimerInternal
00089 {
00090 public:
00091 
00092   nsTimerImpl();
00093 
00094   static NS_HIDDEN_(nsresult) Startup();
00095   static NS_HIDDEN_(void) Shutdown();
00096 
00097   friend class TimerThread;
00098 
00099   void Fire();
00100   void PostTimerEvent();
00101   void SetDelayInternal(PRUint32 aDelay);
00102 
00103   NS_DECL_ISUPPORTS
00104   NS_DECL_NSITIMER
00105   NS_DECL_NSITIMERINTERNAL
00106 
00107   PRInt32 GetGeneration() { return mGeneration; }
00108 
00109 private:
00110   ~nsTimerImpl();
00111 
00112   nsresult InitCommon(PRUint32 aType, PRUint32 aDelay);
00113 
00114   void ReleaseCallback()
00115   {
00116     if (mCallbackType == CALLBACK_TYPE_INTERFACE)
00117       NS_RELEASE(mCallback.i);
00118     else if (mCallbackType == CALLBACK_TYPE_OBSERVER)
00119       NS_RELEASE(mCallback.o);
00120   }
00121 
00122   nsCOMPtr<nsIThread>   mCallingThread;
00123 
00124   void *                mClosure;
00125 
00126   union {
00127     nsTimerCallbackFunc c;
00128     nsITimerCallback *  i;
00129     nsIObserver *       o;
00130   } mCallback;
00131 
00132   // These members are set by Init (called from NS_NewTimer) and never reset.
00133   PRUint8               mCallbackType;
00134   PRPackedBool          mIdle;
00135 
00136   // These members are set by the initiating thread, when the timer's type is
00137   // changed and during the period where it fires on that thread.
00138   PRUint8               mType;
00139   PRPackedBool          mFiring;
00140 
00141 
00142   // Use a PRBool (int) here to isolate loads and stores of these two members
00143   // done on various threads under the protection of TimerThread::mLock, from
00144   // loads and stores done on the initiating/type-changing/timer-firing thread
00145   // to the above PRUint8/PRPackedBool members.
00146   PRBool                mArmed;
00147   PRBool                mCanceled;
00148 
00149   // The generation number of this timer, re-generated each time the timer is
00150   // initialized so one-shot timers can be canceled and re-initialized by the
00151   // arming thread without any bad race conditions.
00152   PRInt32               mGeneration;
00153 
00154   PRUint32              mDelay;
00155   PRIntervalTime        mTimeout;
00156 
00157 #ifdef DEBUG_TIMERS
00158   PRIntervalTime        mStart, mStart2;
00159   static double         sDeltaSum;
00160   static double         sDeltaSumSquared;
00161   static double         sDeltaNum;
00162 #endif
00163 
00164 };
00165 
00166 #define NS_TIMERMANAGER_CONTRACTID "@mozilla.org/timer/manager;1"
00167 #define NS_TIMERMANAGER_CLASSNAME "Timer Manager"
00168 #define NS_TIMERMANAGER_CID \
00169 { /* 4fe206fa-1dd2-11b2-8a0a-88bacbecc7d2 */         \
00170      0x4fe206fa,                                     \
00171      0x1dd2,                                         \
00172      0x11b2,                                         \
00173     {0x8a, 0x0a, 0x88, 0xba, 0xcb, 0xec, 0xc7, 0xd2} \
00174 }
00175 
00176 #include "nsITimerManager.h"
00177 
00178 class nsTimerManager : nsITimerManager
00179 {
00180 public:
00181   nsTimerManager();
00182 
00183   NS_DECL_ISUPPORTS
00184   NS_DECL_NSITIMERMANAGER
00185 
00186   nsresult AddIdleTimer(nsITimer* timer);
00187 private:
00188   ~nsTimerManager();
00189 
00190   PRLock *mLock;
00191   nsVoidArray mIdleTimers;
00192 };
00193 
00194 
00195 #endif /* nsTimerImpl_h___ */