LCOV - code coverage report
Current view: directory - xpcom/glue - nsThreadUtils.h (source / functions) Found Hit Coverage
Test: app.info Lines: 10 0 0.0 %
Date: 2012-06-02 Functions: 5 0 0.0 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* vim:set ts=2 sw=2 sts=2 et cindent: */
       3                 : /* ***** BEGIN LICENSE BLOCK *****
       4                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       5                 :  *
       6                 :  * The contents of this file are subject to the Mozilla Public License Version
       7                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       8                 :  * the License. You may obtain a copy of the License at
       9                 :  * http://www.mozilla.org/MPL/
      10                 :  *
      11                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      12                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      13                 :  * for the specific language governing rights and limitations under the
      14                 :  * License.
      15                 :  *
      16                 :  * The Original Code is Mozilla code.
      17                 :  *
      18                 :  * The Initial Developer of the Original Code is Google Inc.
      19                 :  * Portions created by the Initial Developer are Copyright (C) 2006
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *  Darin Fisher <darin@meer.net>
      24                 :  *
      25                 :  * Alternatively, the contents of this file may be used under the terms of
      26                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      27                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      28                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      29                 :  * of those above. If you wish to allow use of your version of this file only
      30                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      31                 :  * use your version of this file under the terms of the MPL, indicate your
      32                 :  * decision by deleting the provisions above and replace them with the notice
      33                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      34                 :  * the provisions above, a recipient may use your version of this file under
      35                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      36                 :  *
      37                 :  * ***** END LICENSE BLOCK ***** */
      38                 : 
      39                 : #ifndef nsThreadUtils_h__
      40                 : #define nsThreadUtils_h__
      41                 : 
      42                 : #include "prthread.h"
      43                 : #include "prinrval.h"
      44                 : #include "nsIThreadManager.h"
      45                 : #include "nsIThread.h"
      46                 : #include "nsIRunnable.h"
      47                 : #include "nsStringGlue.h"
      48                 : #include "nsCOMPtr.h"
      49                 : #include "nsAutoPtr.h"
      50                 : #include "mozilla/threads/nsThreadIDs.h"
      51                 : 
      52                 : // This is needed on some systems to prevent collisions between the symbols
      53                 : // appearing in xpcom_core and xpcomglue.  It may be unnecessary in the future
      54                 : // with better toolchain support.
      55                 : #ifdef MOZILLA_INTERNAL_API
      56                 : # define NS_NewThread NS_NewThread_P
      57                 : # define NS_GetCurrentThread NS_GetCurrentThread_P
      58                 : # define NS_GetMainThread NS_GetMainThread_P
      59                 : # define NS_IsMainThread NS_IsMainThread_P
      60                 : # define NS_DispatchToCurrentThread NS_DispatchToCurrentThread_P
      61                 : # define NS_DispatchToMainThread NS_DispatchToMainThread_P
      62                 : # define NS_ProcessPendingEvents NS_ProcessPendingEvents_P
      63                 : # define NS_HasPendingEvents NS_HasPendingEvents_P
      64                 : # define NS_ProcessNextEvent NS_ProcessNextEvent_P
      65                 : #endif
      66                 : 
      67                 : //-----------------------------------------------------------------------------
      68                 : // These methods are alternatives to the methods on nsIThreadManager, provided
      69                 : // for convenience.
      70                 : 
      71                 : /**
      72                 :  * Create a new thread, and optionally provide an initial event for the thread.
      73                 :  *
      74                 :  * @param result
      75                 :  *   The resulting nsIThread object.
      76                 :  * @param initialEvent
      77                 :  *   The initial event to run on this thread.  This parameter may be null.
      78                 :  * @param stackSize
      79                 :  *   The size in bytes to reserve for the thread's stack.
      80                 :  *
      81                 :  * @returns NS_ERROR_INVALID_ARG
      82                 :  *   Indicates that the given name is not unique.
      83                 :  */
      84                 : extern NS_COM_GLUE NS_METHOD
      85                 : NS_NewThread(nsIThread **result,
      86                 :              nsIRunnable *initialEvent = nsnull,
      87                 :              PRUint32 stackSize = nsIThreadManager::DEFAULT_STACK_SIZE);
      88                 : 
      89                 : /**
      90                 :  * Get a reference to the current thread.
      91                 :  *
      92                 :  * @param result
      93                 :  *   The resulting nsIThread object.
      94                 :  */
      95                 : extern NS_COM_GLUE NS_METHOD
      96                 : NS_GetCurrentThread(nsIThread **result);
      97                 : 
      98                 : /**
      99                 :  * Get a reference to the main thread.
     100                 :  *
     101                 :  * @param result
     102                 :  *   The resulting nsIThread object.
     103                 :  */
     104                 : extern NS_COM_GLUE NS_METHOD
     105                 : NS_GetMainThread(nsIThread **result);
     106                 : 
     107                 : #if defined(MOZILLA_INTERNAL_API) && defined(XP_WIN)
     108                 : bool NS_IsMainThread();
     109                 : #elif defined(MOZILLA_INTERNAL_API) && defined(NS_TLS)
     110                 : // This is defined in nsThreadManager.cpp and initialized to `Main` for the
     111                 : // main thread by nsThreadManager::Init.
     112                 : extern NS_TLS mozilla::threads::ID gTLSThreadID;
     113               0 : inline bool NS_IsMainThread()
     114                 : {
     115               0 :   return gTLSThreadID == mozilla::threads::Main;
     116                 : }
     117                 : #else
     118                 : /**
     119                 :  * Test to see if the current thread is the main thread.
     120                 :  *
     121                 :  * @returns true if the current thread is the main thread, and false
     122                 :  * otherwise.
     123                 :  */
     124                 : extern NS_COM_GLUE bool NS_IsMainThread();
     125                 : #endif
     126                 : 
     127                 : /**
     128                 :  * Dispatch the given event to the current thread.
     129                 :  *
     130                 :  * @param event
     131                 :  *   The event to dispatch.
     132                 :  *
     133                 :  * @returns NS_ERROR_INVALID_ARG
     134                 :  *   If event is null.
     135                 :  */
     136                 : extern NS_COM_GLUE NS_METHOD
     137                 : NS_DispatchToCurrentThread(nsIRunnable *event);
     138                 : 
     139                 : /**
     140                 :  * Dispatch the given event to the main thread.
     141                 :  *
     142                 :  * @param event
     143                 :  *   The event to dispatch.
     144                 :  * @param dispatchFlags
     145                 :  *   The flags to pass to the main thread's dispatch method.
     146                 :  *
     147                 :  * @returns NS_ERROR_INVALID_ARG
     148                 :  *   If event is null.
     149                 :  */
     150                 : extern NS_COM_GLUE NS_METHOD
     151                 : NS_DispatchToMainThread(nsIRunnable *event,
     152                 :                         PRUint32 dispatchFlags = NS_DISPATCH_NORMAL);
     153                 : 
     154                 : #ifndef XPCOM_GLUE_AVOID_NSPR
     155                 : /**
     156                 :  * Process all pending events for the given thread before returning.  This
     157                 :  * method simply calls ProcessNextEvent on the thread while HasPendingEvents
     158                 :  * continues to return true and the time spent in NS_ProcessPendingEvents
     159                 :  * does not exceed the given timeout value.
     160                 :  *
     161                 :  * @param thread
     162                 :  *   The thread object for which to process pending events.  If null, then
     163                 :  *   events will be processed for the current thread.
     164                 :  * @param timeout
     165                 :  *   The maximum number of milliseconds to spend processing pending events.
     166                 :  *   Events are not pre-empted to honor this timeout.  Rather, the timeout
     167                 :  *   value is simply used to determine whether or not to process another event.
     168                 :  *   Pass PR_INTERVAL_NO_TIMEOUT to specify no timeout.
     169                 :  */
     170                 : extern NS_COM_GLUE NS_METHOD
     171                 : NS_ProcessPendingEvents(nsIThread *thread,
     172                 :                         PRIntervalTime timeout = PR_INTERVAL_NO_TIMEOUT);
     173                 : #endif
     174                 : 
     175                 : /**
     176                 :  * Shortcut for nsIThread::HasPendingEvents.
     177                 :  *
     178                 :  * It is an error to call this function when the given thread is not the
     179                 :  * current thread.  This function will return false if called from some
     180                 :  * other thread.
     181                 :  *
     182                 :  * @param thread
     183                 :  *   The current thread or null.
     184                 :  *
     185                 :  * @returns
     186                 :  *   A boolean value that if "true" indicates that there are pending events
     187                 :  *   in the current thread's event queue.
     188                 :  */
     189                 : extern NS_COM_GLUE bool
     190                 : NS_HasPendingEvents(nsIThread *thread = nsnull);
     191                 : 
     192                 : /**
     193                 :  * Shortcut for nsIThread::ProcessNextEvent.
     194                 :  *   
     195                 :  * It is an error to call this function when the given thread is not the
     196                 :  * current thread.  This function will simply return false if called
     197                 :  * from some other thread.
     198                 :  *
     199                 :  * @param thread
     200                 :  *   The current thread or null.
     201                 :  * @param mayWait
     202                 :  *   A boolean parameter that if "true" indicates that the method may block
     203                 :  *   the calling thread to wait for a pending event.
     204                 :  *
     205                 :  * @returns
     206                 :  *   A boolean value that if "true" indicates that an event from the current
     207                 :  *   thread's event queue was processed.
     208                 :  */
     209                 : extern NS_COM_GLUE bool
     210                 : NS_ProcessNextEvent(nsIThread *thread = nsnull, bool mayWait = true);
     211                 : 
     212                 : //-----------------------------------------------------------------------------
     213                 : // Helpers that work with nsCOMPtr:
     214                 : 
     215                 : inline already_AddRefed<nsIThread>
     216               0 : do_GetCurrentThread() {
     217               0 :   nsIThread *thread = nsnull;
     218               0 :   NS_GetCurrentThread(&thread);
     219               0 :   return already_AddRefed<nsIThread>(thread);
     220                 : }
     221                 : 
     222                 : inline already_AddRefed<nsIThread>
     223                 : do_GetMainThread() {
     224                 :   nsIThread *thread = nsnull;
     225                 :   NS_GetMainThread(&thread);
     226                 :   return already_AddRefed<nsIThread>(thread);
     227                 : }
     228                 : 
     229                 : //-----------------------------------------------------------------------------
     230                 : 
     231                 : #ifdef MOZILLA_INTERNAL_API
     232                 : // Fast access to the current thread.  Do not release the returned pointer!  If
     233                 : // you want to use this pointer from some other thread, then you will need to
     234                 : // AddRef it.  Otherwise, you should only consider this pointer valid from code
     235                 : // running on the current thread.
     236                 : extern NS_COM_GLUE nsIThread *NS_GetCurrentThread();
     237                 : #endif
     238                 : 
     239                 : //-----------------------------------------------------------------------------
     240                 : 
     241                 : #ifndef XPCOM_GLUE_AVOID_NSPR
     242                 : 
     243                 : #undef  IMETHOD_VISIBILITY
     244                 : #define IMETHOD_VISIBILITY NS_COM_GLUE
     245                 : 
     246                 : // This class is designed to be subclassed.
     247                 : class NS_COM_GLUE nsRunnable : public nsIRunnable
     248                 : {
     249                 : public:
     250                 :   NS_DECL_ISUPPORTS
     251                 :   NS_DECL_NSIRUNNABLE
     252                 : 
     253               0 :   nsRunnable() {
     254               0 :   }
     255                 : 
     256                 : protected:
     257               0 :   virtual ~nsRunnable() {
     258               0 :   }
     259                 : };
     260                 : 
     261                 : #undef  IMETHOD_VISIBILITY
     262                 : #define IMETHOD_VISIBILITY NS_VISIBILITY_HIDDEN
     263                 : 
     264                 : // An event that can be used to call a method on a class.  The class type must
     265                 : // support reference counting. This event supports Revoke for use
     266                 : // with nsRevocableEventPtr.
     267                 : template <class ClassType,
     268                 :           typename ReturnType = void,
     269                 :           bool Owning = true>
     270                 : class nsRunnableMethod : public nsRunnable
     271                 : {
     272                 : public:
     273                 :   virtual void Revoke() = 0;
     274                 : 
     275                 :   // These ReturnTypeEnforcer classes set up a blacklist for return types that
     276                 :   // we know are not safe. The default ReturnTypeEnforcer compiles just fine but
     277                 :   // already_AddRefed will not.
     278                 :   template <typename OtherReturnType>
     279                 :   class ReturnTypeEnforcer
     280                 :   {
     281                 :   public:
     282                 :     typedef int ReturnTypeIsSafe;
     283                 :   };
     284                 : 
     285                 :   template <class T>
     286                 :   class ReturnTypeEnforcer<already_AddRefed<T> >
     287                 :   {
     288                 :     // No ReturnTypeIsSafe makes this illegal!
     289                 :   };
     290                 : 
     291                 :   // Make sure this return type is safe.
     292                 :   typedef typename ReturnTypeEnforcer<ReturnType>::ReturnTypeIsSafe check;
     293                 : };
     294                 : 
     295                 : template <class ClassType, bool Owning>
     296                 : struct nsRunnableMethodReceiver {
     297                 :   ClassType *mObj;
     298                 :   nsRunnableMethodReceiver(ClassType *obj) : mObj(obj) { NS_IF_ADDREF(mObj); }
     299                 :  ~nsRunnableMethodReceiver() { Revoke(); }
     300                 :   void Revoke() { NS_IF_RELEASE(mObj); }
     301                 : };
     302                 : 
     303                 : template <class ClassType>
     304                 : struct nsRunnableMethodReceiver<ClassType, false> {
     305                 :   ClassType *mObj;
     306                 :   nsRunnableMethodReceiver(ClassType *obj) : mObj(obj) {}
     307                 :   void Revoke() { mObj = nsnull; }
     308                 : };
     309                 : 
     310                 : template <typename Method, bool Owning> struct nsRunnableMethodTraits;
     311                 : 
     312                 : template <class C, typename R, bool Owning>
     313                 : struct nsRunnableMethodTraits<R (C::*)(), Owning> {
     314                 :   typedef C class_type;
     315                 :   typedef R return_type;
     316                 :   typedef nsRunnableMethod<C, R, Owning> base_type;
     317                 : };
     318                 : 
     319                 : #ifdef HAVE_STDCALL
     320                 : template <class C, typename R, bool Owning>
     321                 : struct nsRunnableMethodTraits<R (__stdcall C::*)(), Owning> {
     322                 :   typedef C class_type;
     323                 :   typedef R return_type;
     324                 :   typedef nsRunnableMethod<C, R, Owning> base_type;
     325                 : };
     326                 : #endif
     327                 : 
     328                 : template <typename Method, bool Owning>
     329                 : class nsRunnableMethodImpl
     330                 :   : public nsRunnableMethodTraits<Method, Owning>::base_type
     331                 : {
     332                 :   typedef typename nsRunnableMethodTraits<Method, Owning>::class_type ClassType;
     333                 :   nsRunnableMethodReceiver<ClassType, Owning> mReceiver;
     334                 :   Method mMethod;
     335                 : 
     336                 : public:
     337                 :   nsRunnableMethodImpl(ClassType *obj,
     338                 :                        Method method)
     339                 :     : mReceiver(obj)
     340                 :     , mMethod(method)
     341                 :   {}
     342                 : 
     343                 :   NS_IMETHOD Run() {
     344                 :     if (NS_LIKELY(mReceiver.mObj))
     345                 :       ((*mReceiver.mObj).*mMethod)();
     346                 :     return NS_OK;
     347                 :   }
     348                 : 
     349                 :   void Revoke() {
     350                 :     mReceiver.Revoke();
     351                 :   }
     352                 : };
     353                 : 
     354                 : // Use this template function like so:
     355                 : //
     356                 : //   nsCOMPtr<nsIRunnable> event =
     357                 : //     NS_NewRunnableMethod(myObject, &MyClass::HandleEvent);
     358                 : //   NS_DispatchToCurrentThread(event);
     359                 : //
     360                 : // Statically enforced constraints:
     361                 : //  - myObject must be of (or implicitly convertible to) type MyClass
     362                 : //  - MyClass must defined AddRef and Release methods
     363                 : //
     364                 : template<typename PtrType, typename Method>
     365                 : typename nsRunnableMethodTraits<Method, true>::base_type*
     366                 : NS_NewRunnableMethod(PtrType ptr, Method method)
     367                 : {
     368                 :   return new nsRunnableMethodImpl<Method, true>(ptr, method);
     369                 : }
     370                 : 
     371                 : template<typename PtrType, typename Method>
     372                 : typename nsRunnableMethodTraits<Method, false>::base_type*
     373                 : NS_NewNonOwningRunnableMethod(PtrType ptr, Method method)
     374                 : {
     375                 :   return new nsRunnableMethodImpl<Method, false>(ptr, method);
     376                 : }
     377                 : 
     378                 : #endif  // XPCOM_GLUE_AVOID_NSPR
     379                 : 
     380                 : // This class is designed to be used when you have an event class E that has a
     381                 : // pointer back to resource class R.  If R goes away while E is still pending,
     382                 : // then it is important to "revoke" E so that it does not try use R after R has
     383                 : // been destroyed.  nsRevocableEventPtr makes it easy for R to manage such
     384                 : // situations:
     385                 : //
     386                 : //   class R;
     387                 : //
     388                 : //   class E : public nsRunnable {
     389                 : //   public:
     390                 : //     void Revoke() {
     391                 : //       mResource = nsnull;
     392                 : //     }
     393                 : //   private:
     394                 : //     R *mResource;
     395                 : //   };
     396                 : //
     397                 : //   class R {
     398                 : //   public:
     399                 : //     void EventHandled() {
     400                 : //       mEvent.Forget();
     401                 : //     }
     402                 : //   private:
     403                 : //     nsRevocableEventPtr<E> mEvent;
     404                 : //   };
     405                 : //
     406                 : //   void R::PostEvent() {
     407                 : //     // Make sure any pending event is revoked.
     408                 : //     mEvent->Revoke();
     409                 : //
     410                 : //     nsCOMPtr<nsIRunnable> event = new E();
     411                 : //     if (NS_SUCCEEDED(NS_DispatchToCurrentThread(event))) {
     412                 : //       // Keep pointer to event so we can revoke it.
     413                 : //       mEvent = event;
     414                 : //     }
     415                 : //   }
     416                 : //
     417                 : //   NS_IMETHODIMP E::Run() {
     418                 : //     if (!mResource)
     419                 : //       return NS_OK;
     420                 : //     ...
     421                 : //     mResource->EventHandled();
     422                 : //     return NS_OK;
     423                 : //   }
     424                 : //
     425                 : template <class T>
     426                 : class nsRevocableEventPtr {
     427                 : public:
     428                 :   nsRevocableEventPtr()
     429                 :     : mEvent(nsnull) {
     430                 :   }
     431                 : 
     432                 :   ~nsRevocableEventPtr() {
     433                 :     Revoke();
     434                 :   }
     435                 : 
     436                 :   const nsRevocableEventPtr& operator=(T *event) {
     437                 :     if (mEvent != event) {
     438                 :       Revoke();
     439                 :       mEvent = event;
     440                 :     }
     441                 :     return *this;
     442                 :   }
     443                 : 
     444                 :   void Revoke() {
     445                 :     if (mEvent) {
     446                 :       mEvent->Revoke();
     447                 :       mEvent = nsnull;
     448                 :     }
     449                 :   }
     450                 : 
     451                 :   void Forget() {
     452                 :     mEvent = nsnull;
     453                 :   }
     454                 : 
     455                 :   bool IsPending() {
     456                 :     return mEvent != nsnull;
     457                 :   }
     458                 :   
     459                 :   T *get() { return mEvent; }
     460                 : 
     461                 : private:
     462                 :   // Not implemented
     463                 :   nsRevocableEventPtr(const nsRevocableEventPtr&);
     464                 :   nsRevocableEventPtr& operator=(const nsRevocableEventPtr&);
     465                 : 
     466                 :   nsRefPtr<T> mEvent;
     467                 : };
     468                 : 
     469                 : #endif  // nsThreadUtils_h__

Generated by: LCOV version 1.7