xpcom/glue/nsThreadUtils.h

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
michael@0 3 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 #ifndef nsThreadUtils_h__
michael@0 8 #define nsThreadUtils_h__
michael@0 9
michael@0 10 #include "prthread.h"
michael@0 11 #include "prinrval.h"
michael@0 12 #include "MainThreadUtils.h"
michael@0 13 #include "nsIThreadManager.h"
michael@0 14 #include "nsIThread.h"
michael@0 15 #include "nsIRunnable.h"
michael@0 16 #include "nsICancelableRunnable.h"
michael@0 17 #include "nsStringGlue.h"
michael@0 18 #include "nsCOMPtr.h"
michael@0 19 #include "nsAutoPtr.h"
michael@0 20 #include "mozilla/Likely.h"
michael@0 21
michael@0 22 //-----------------------------------------------------------------------------
michael@0 23 // These methods are alternatives to the methods on nsIThreadManager, provided
michael@0 24 // for convenience.
michael@0 25
michael@0 26 /**
michael@0 27 * Set name of the target thread. This operation is asynchronous.
michael@0 28 */
michael@0 29 extern NS_COM_GLUE void
michael@0 30 NS_SetThreadName(nsIThread *thread, const nsACString &name);
michael@0 31
michael@0 32 /**
michael@0 33 * Static length version of the above function checking length of the
michael@0 34 * name at compile time.
michael@0 35 */
michael@0 36 template <size_t LEN>
michael@0 37 inline NS_COM_GLUE void
michael@0 38 NS_SetThreadName(nsIThread *thread, const char (&name)[LEN])
michael@0 39 {
michael@0 40 static_assert(LEN <= 16,
michael@0 41 "Thread name must be no more than 16 characters");
michael@0 42 NS_SetThreadName(thread, nsDependentCString(name));
michael@0 43 }
michael@0 44
michael@0 45 /**
michael@0 46 * Create a new thread, and optionally provide an initial event for the thread.
michael@0 47 *
michael@0 48 * @param result
michael@0 49 * The resulting nsIThread object.
michael@0 50 * @param initialEvent
michael@0 51 * The initial event to run on this thread. This parameter may be null.
michael@0 52 * @param stackSize
michael@0 53 * The size in bytes to reserve for the thread's stack.
michael@0 54 *
michael@0 55 * @returns NS_ERROR_INVALID_ARG
michael@0 56 * Indicates that the given name is not unique.
michael@0 57 */
michael@0 58 extern NS_COM_GLUE NS_METHOD
michael@0 59 NS_NewThread(nsIThread **result,
michael@0 60 nsIRunnable *initialEvent = nullptr,
michael@0 61 uint32_t stackSize = nsIThreadManager::DEFAULT_STACK_SIZE);
michael@0 62
michael@0 63 /**
michael@0 64 * Creates a named thread, otherwise the same as NS_NewThread
michael@0 65 */
michael@0 66 template <size_t LEN>
michael@0 67 inline NS_METHOD
michael@0 68 NS_NewNamedThread(const char (&name)[LEN],
michael@0 69 nsIThread **result,
michael@0 70 nsIRunnable *initialEvent = nullptr,
michael@0 71 uint32_t stackSize = nsIThreadManager::DEFAULT_STACK_SIZE)
michael@0 72 {
michael@0 73 // Hold a ref while dispatching the initial event to match NS_NewThread()
michael@0 74 nsCOMPtr<nsIThread> thread;
michael@0 75 nsresult rv = NS_NewThread(getter_AddRefs(thread), nullptr, stackSize);
michael@0 76 if (NS_WARN_IF(NS_FAILED(rv)))
michael@0 77 return rv;
michael@0 78 NS_SetThreadName<LEN>(thread, name);
michael@0 79 if (initialEvent) {
michael@0 80 rv = thread->Dispatch(initialEvent, NS_DISPATCH_NORMAL);
michael@0 81 NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Initial event dispatch failed");
michael@0 82 }
michael@0 83
michael@0 84 *result = nullptr;
michael@0 85 thread.swap(*result);
michael@0 86 return rv;
michael@0 87 }
michael@0 88
michael@0 89 /**
michael@0 90 * Get a reference to the current thread.
michael@0 91 *
michael@0 92 * @param result
michael@0 93 * The resulting nsIThread object.
michael@0 94 */
michael@0 95 extern NS_COM_GLUE NS_METHOD
michael@0 96 NS_GetCurrentThread(nsIThread **result);
michael@0 97
michael@0 98 /**
michael@0 99 * Dispatch the given event to the current thread.
michael@0 100 *
michael@0 101 * @param event
michael@0 102 * The event to dispatch.
michael@0 103 *
michael@0 104 * @returns NS_ERROR_INVALID_ARG
michael@0 105 * If event is null.
michael@0 106 */
michael@0 107 extern NS_COM_GLUE NS_METHOD
michael@0 108 NS_DispatchToCurrentThread(nsIRunnable *event);
michael@0 109
michael@0 110 /**
michael@0 111 * Dispatch the given event to the main thread.
michael@0 112 *
michael@0 113 * @param event
michael@0 114 * The event to dispatch.
michael@0 115 * @param dispatchFlags
michael@0 116 * The flags to pass to the main thread's dispatch method.
michael@0 117 *
michael@0 118 * @returns NS_ERROR_INVALID_ARG
michael@0 119 * If event is null.
michael@0 120 */
michael@0 121 extern NS_COM_GLUE NS_METHOD
michael@0 122 NS_DispatchToMainThread(nsIRunnable *event,
michael@0 123 uint32_t dispatchFlags = NS_DISPATCH_NORMAL);
michael@0 124
michael@0 125 #ifndef XPCOM_GLUE_AVOID_NSPR
michael@0 126 /**
michael@0 127 * Process all pending events for the given thread before returning. This
michael@0 128 * method simply calls ProcessNextEvent on the thread while HasPendingEvents
michael@0 129 * continues to return true and the time spent in NS_ProcessPendingEvents
michael@0 130 * does not exceed the given timeout value.
michael@0 131 *
michael@0 132 * @param thread
michael@0 133 * The thread object for which to process pending events. If null, then
michael@0 134 * events will be processed for the current thread.
michael@0 135 * @param timeout
michael@0 136 * The maximum number of milliseconds to spend processing pending events.
michael@0 137 * Events are not pre-empted to honor this timeout. Rather, the timeout
michael@0 138 * value is simply used to determine whether or not to process another event.
michael@0 139 * Pass PR_INTERVAL_NO_TIMEOUT to specify no timeout.
michael@0 140 */
michael@0 141 extern NS_COM_GLUE NS_METHOD
michael@0 142 NS_ProcessPendingEvents(nsIThread *thread,
michael@0 143 PRIntervalTime timeout = PR_INTERVAL_NO_TIMEOUT);
michael@0 144 #endif
michael@0 145
michael@0 146 /**
michael@0 147 * Shortcut for nsIThread::HasPendingEvents.
michael@0 148 *
michael@0 149 * It is an error to call this function when the given thread is not the
michael@0 150 * current thread. This function will return false if called from some
michael@0 151 * other thread.
michael@0 152 *
michael@0 153 * @param thread
michael@0 154 * The current thread or null.
michael@0 155 *
michael@0 156 * @returns
michael@0 157 * A boolean value that if "true" indicates that there are pending events
michael@0 158 * in the current thread's event queue.
michael@0 159 */
michael@0 160 extern NS_COM_GLUE bool
michael@0 161 NS_HasPendingEvents(nsIThread *thread = nullptr);
michael@0 162
michael@0 163 /**
michael@0 164 * Shortcut for nsIThread::ProcessNextEvent.
michael@0 165 *
michael@0 166 * It is an error to call this function when the given thread is not the
michael@0 167 * current thread. This function will simply return false if called
michael@0 168 * from some other thread.
michael@0 169 *
michael@0 170 * @param thread
michael@0 171 * The current thread or null.
michael@0 172 * @param mayWait
michael@0 173 * A boolean parameter that if "true" indicates that the method may block
michael@0 174 * the calling thread to wait for a pending event.
michael@0 175 *
michael@0 176 * @returns
michael@0 177 * A boolean value that if "true" indicates that an event from the current
michael@0 178 * thread's event queue was processed.
michael@0 179 */
michael@0 180 extern NS_COM_GLUE bool
michael@0 181 NS_ProcessNextEvent(nsIThread *thread = nullptr, bool mayWait = true);
michael@0 182
michael@0 183 //-----------------------------------------------------------------------------
michael@0 184 // Helpers that work with nsCOMPtr:
michael@0 185
michael@0 186 inline already_AddRefed<nsIThread>
michael@0 187 do_GetCurrentThread() {
michael@0 188 nsIThread *thread = nullptr;
michael@0 189 NS_GetCurrentThread(&thread);
michael@0 190 return already_AddRefed<nsIThread>(thread);
michael@0 191 }
michael@0 192
michael@0 193 inline already_AddRefed<nsIThread>
michael@0 194 do_GetMainThread() {
michael@0 195 nsIThread *thread = nullptr;
michael@0 196 NS_GetMainThread(&thread);
michael@0 197 return already_AddRefed<nsIThread>(thread);
michael@0 198 }
michael@0 199
michael@0 200 //-----------------------------------------------------------------------------
michael@0 201
michael@0 202 #ifdef MOZILLA_INTERNAL_API
michael@0 203 // Fast access to the current thread. Do not release the returned pointer! If
michael@0 204 // you want to use this pointer from some other thread, then you will need to
michael@0 205 // AddRef it. Otherwise, you should only consider this pointer valid from code
michael@0 206 // running on the current thread.
michael@0 207 extern NS_COM_GLUE nsIThread *NS_GetCurrentThread();
michael@0 208 #endif
michael@0 209
michael@0 210 //-----------------------------------------------------------------------------
michael@0 211
michael@0 212 #ifndef XPCOM_GLUE_AVOID_NSPR
michael@0 213
michael@0 214 #undef IMETHOD_VISIBILITY
michael@0 215 #define IMETHOD_VISIBILITY NS_COM_GLUE
michael@0 216
michael@0 217 // This class is designed to be subclassed.
michael@0 218 class NS_COM_GLUE nsRunnable : public nsIRunnable
michael@0 219 {
michael@0 220 public:
michael@0 221 NS_DECL_THREADSAFE_ISUPPORTS
michael@0 222 NS_DECL_NSIRUNNABLE
michael@0 223
michael@0 224 nsRunnable() {
michael@0 225 }
michael@0 226
michael@0 227 protected:
michael@0 228 virtual ~nsRunnable() {
michael@0 229 }
michael@0 230 };
michael@0 231
michael@0 232 // This class is designed to be subclassed.
michael@0 233 class NS_COM_GLUE nsCancelableRunnable : public nsICancelableRunnable
michael@0 234 {
michael@0 235 public:
michael@0 236 NS_DECL_THREADSAFE_ISUPPORTS
michael@0 237 NS_DECL_NSIRUNNABLE
michael@0 238 NS_DECL_NSICANCELABLERUNNABLE
michael@0 239
michael@0 240 nsCancelableRunnable() {
michael@0 241 }
michael@0 242
michael@0 243 protected:
michael@0 244 virtual ~nsCancelableRunnable() {
michael@0 245 }
michael@0 246 };
michael@0 247
michael@0 248 #undef IMETHOD_VISIBILITY
michael@0 249 #define IMETHOD_VISIBILITY NS_VISIBILITY_HIDDEN
michael@0 250
michael@0 251 // An event that can be used to call a method on a class. The class type must
michael@0 252 // support reference counting. This event supports Revoke for use
michael@0 253 // with nsRevocableEventPtr.
michael@0 254 template <class ClassType,
michael@0 255 typename ReturnType = void,
michael@0 256 bool Owning = true>
michael@0 257 class nsRunnableMethod : public nsRunnable
michael@0 258 {
michael@0 259 public:
michael@0 260 virtual void Revoke() = 0;
michael@0 261
michael@0 262 // These ReturnTypeEnforcer classes set up a blacklist for return types that
michael@0 263 // we know are not safe. The default ReturnTypeEnforcer compiles just fine but
michael@0 264 // already_AddRefed will not.
michael@0 265 template <typename OtherReturnType>
michael@0 266 class ReturnTypeEnforcer
michael@0 267 {
michael@0 268 public:
michael@0 269 typedef int ReturnTypeIsSafe;
michael@0 270 };
michael@0 271
michael@0 272 template <class T>
michael@0 273 class ReturnTypeEnforcer<already_AddRefed<T> >
michael@0 274 {
michael@0 275 // No ReturnTypeIsSafe makes this illegal!
michael@0 276 };
michael@0 277
michael@0 278 // Make sure this return type is safe.
michael@0 279 typedef typename ReturnTypeEnforcer<ReturnType>::ReturnTypeIsSafe check;
michael@0 280 };
michael@0 281
michael@0 282 template <class ClassType, typename Arg, bool Owning>
michael@0 283 struct nsRunnableMethodReceiver {
michael@0 284 ClassType *mObj;
michael@0 285 Arg mArg;
michael@0 286 nsRunnableMethodReceiver(ClassType *obj, Arg arg)
michael@0 287 : mObj(obj)
michael@0 288 , mArg(arg)
michael@0 289 { NS_IF_ADDREF(mObj); }
michael@0 290 ~nsRunnableMethodReceiver() { Revoke(); }
michael@0 291 void Revoke() { NS_IF_RELEASE(mObj); }
michael@0 292 };
michael@0 293
michael@0 294 template <class ClassType, bool Owning>
michael@0 295 struct nsRunnableMethodReceiver<ClassType, void, Owning> {
michael@0 296 ClassType *mObj;
michael@0 297 nsRunnableMethodReceiver(ClassType *obj) : mObj(obj)
michael@0 298 { NS_IF_ADDREF(mObj); }
michael@0 299 ~nsRunnableMethodReceiver() { Revoke(); }
michael@0 300 void Revoke() { NS_IF_RELEASE(mObj); }
michael@0 301 };
michael@0 302
michael@0 303 template <class ClassType>
michael@0 304 struct nsRunnableMethodReceiver<ClassType, void, false> {
michael@0 305 ClassType *mObj;
michael@0 306 nsRunnableMethodReceiver(ClassType *obj) : mObj(obj) {}
michael@0 307 void Revoke() { mObj = nullptr; }
michael@0 308 };
michael@0 309
michael@0 310 template <typename Method, bool Owning> struct nsRunnableMethodTraits;
michael@0 311
michael@0 312 template <class C, typename R, typename A, bool Owning>
michael@0 313 struct nsRunnableMethodTraits<R (C::*)(A), Owning> {
michael@0 314 typedef C class_type;
michael@0 315 typedef R return_type;
michael@0 316 typedef A arg_type;
michael@0 317 typedef nsRunnableMethod<C, R, Owning> base_type;
michael@0 318 };
michael@0 319
michael@0 320 template <class C, typename R, bool Owning>
michael@0 321 struct nsRunnableMethodTraits<R (C::*)(), Owning> {
michael@0 322 typedef C class_type;
michael@0 323 typedef R return_type;
michael@0 324 typedef void arg_type;
michael@0 325 typedef nsRunnableMethod<C, R, Owning> base_type;
michael@0 326 };
michael@0 327
michael@0 328 #ifdef NS_HAVE_STDCALL
michael@0 329 template <class C, typename R, typename A, bool Owning>
michael@0 330 struct nsRunnableMethodTraits<R (__stdcall C::*)(A), Owning> {
michael@0 331 typedef C class_type;
michael@0 332 typedef R return_type;
michael@0 333 typedef A arg_type;
michael@0 334 typedef nsRunnableMethod<C, R, Owning> base_type;
michael@0 335 };
michael@0 336
michael@0 337 template <class C, typename R, bool Owning>
michael@0 338 struct nsRunnableMethodTraits<R (NS_STDCALL C::*)(), Owning> {
michael@0 339 typedef C class_type;
michael@0 340 typedef R return_type;
michael@0 341 typedef void arg_type;
michael@0 342 typedef nsRunnableMethod<C, R, Owning> base_type;
michael@0 343 };
michael@0 344 #endif
michael@0 345
michael@0 346 template <typename Method, typename Arg, bool Owning>
michael@0 347 class nsRunnableMethodImpl
michael@0 348 : public nsRunnableMethodTraits<Method, Owning>::base_type
michael@0 349 {
michael@0 350 typedef typename nsRunnableMethodTraits<Method, Owning>::class_type ClassType;
michael@0 351 nsRunnableMethodReceiver<ClassType, Arg, Owning> mReceiver;
michael@0 352 Method mMethod;
michael@0 353 public:
michael@0 354 nsRunnableMethodImpl(ClassType *obj,
michael@0 355 Method method,
michael@0 356 Arg arg)
michael@0 357 : mReceiver(obj, arg)
michael@0 358 , mMethod(method)
michael@0 359 {}
michael@0 360 NS_IMETHOD Run() {
michael@0 361 if (MOZ_LIKELY(mReceiver.mObj))
michael@0 362 ((*mReceiver.mObj).*mMethod)(mReceiver.mArg);
michael@0 363 return NS_OK;
michael@0 364 }
michael@0 365 void Revoke() {
michael@0 366 mReceiver.Revoke();
michael@0 367 }
michael@0 368 };
michael@0 369
michael@0 370 template <typename Method, bool Owning>
michael@0 371 class nsRunnableMethodImpl<Method, void, Owning>
michael@0 372 : public nsRunnableMethodTraits<Method, Owning>::base_type
michael@0 373 {
michael@0 374 typedef typename nsRunnableMethodTraits<Method, Owning>::class_type ClassType;
michael@0 375 nsRunnableMethodReceiver<ClassType, void, Owning> mReceiver;
michael@0 376 Method mMethod;
michael@0 377
michael@0 378 public:
michael@0 379 nsRunnableMethodImpl(ClassType *obj,
michael@0 380 Method method)
michael@0 381 : mReceiver(obj)
michael@0 382 , mMethod(method)
michael@0 383 {}
michael@0 384
michael@0 385 NS_IMETHOD Run() {
michael@0 386 if (MOZ_LIKELY(mReceiver.mObj))
michael@0 387 ((*mReceiver.mObj).*mMethod)();
michael@0 388 return NS_OK;
michael@0 389 }
michael@0 390
michael@0 391 void Revoke() {
michael@0 392 mReceiver.Revoke();
michael@0 393 }
michael@0 394 };
michael@0 395
michael@0 396 // Use this template function like so:
michael@0 397 //
michael@0 398 // nsCOMPtr<nsIRunnable> event =
michael@0 399 // NS_NewRunnableMethod(myObject, &MyClass::HandleEvent);
michael@0 400 // NS_DispatchToCurrentThread(event);
michael@0 401 //
michael@0 402 // Statically enforced constraints:
michael@0 403 // - myObject must be of (or implicitly convertible to) type MyClass
michael@0 404 // - MyClass must defined AddRef and Release methods
michael@0 405 //
michael@0 406 template<typename PtrType, typename Method>
michael@0 407 typename nsRunnableMethodTraits<Method, true>::base_type*
michael@0 408 NS_NewRunnableMethod(PtrType ptr, Method method)
michael@0 409 {
michael@0 410 return new nsRunnableMethodImpl<Method, void, true>(ptr, method);
michael@0 411 }
michael@0 412
michael@0 413 template<typename T>
michael@0 414 struct dependent_type
michael@0 415 {
michael@0 416 typedef T type;
michael@0 417 };
michael@0 418
michael@0 419
michael@0 420 // Similar to NS_NewRunnableMethod. Call like so:
michael@0 421 // Type myArg;
michael@0 422 // nsCOMPtr<nsIRunnable> event =
michael@0 423 // NS_NewRunnableMethodWithArg<Type>(myObject, &MyClass::HandleEvent, myArg);
michael@0 424 template<typename Arg, typename Method, typename PtrType>
michael@0 425 typename nsRunnableMethodTraits<Method, true>::base_type*
michael@0 426 NS_NewRunnableMethodWithArg(PtrType ptr, Method method, typename dependent_type<Arg>::type arg)
michael@0 427 {
michael@0 428 return new nsRunnableMethodImpl<Method, Arg, true>(ptr, method, arg);
michael@0 429 }
michael@0 430
michael@0 431 template<typename PtrType, typename Method>
michael@0 432 typename nsRunnableMethodTraits<Method, false>::base_type*
michael@0 433 NS_NewNonOwningRunnableMethod(PtrType ptr, Method method)
michael@0 434 {
michael@0 435 return new nsRunnableMethodImpl<Method, void, false>(ptr, method);
michael@0 436 }
michael@0 437
michael@0 438 #endif // XPCOM_GLUE_AVOID_NSPR
michael@0 439
michael@0 440 // This class is designed to be used when you have an event class E that has a
michael@0 441 // pointer back to resource class R. If R goes away while E is still pending,
michael@0 442 // then it is important to "revoke" E so that it does not try use R after R has
michael@0 443 // been destroyed. nsRevocableEventPtr makes it easy for R to manage such
michael@0 444 // situations:
michael@0 445 //
michael@0 446 // class R;
michael@0 447 //
michael@0 448 // class E : public nsRunnable {
michael@0 449 // public:
michael@0 450 // void Revoke() {
michael@0 451 // mResource = nullptr;
michael@0 452 // }
michael@0 453 // private:
michael@0 454 // R *mResource;
michael@0 455 // };
michael@0 456 //
michael@0 457 // class R {
michael@0 458 // public:
michael@0 459 // void EventHandled() {
michael@0 460 // mEvent.Forget();
michael@0 461 // }
michael@0 462 // private:
michael@0 463 // nsRevocableEventPtr<E> mEvent;
michael@0 464 // };
michael@0 465 //
michael@0 466 // void R::PostEvent() {
michael@0 467 // // Make sure any pending event is revoked.
michael@0 468 // mEvent->Revoke();
michael@0 469 //
michael@0 470 // nsCOMPtr<nsIRunnable> event = new E();
michael@0 471 // if (NS_SUCCEEDED(NS_DispatchToCurrentThread(event))) {
michael@0 472 // // Keep pointer to event so we can revoke it.
michael@0 473 // mEvent = event;
michael@0 474 // }
michael@0 475 // }
michael@0 476 //
michael@0 477 // NS_IMETHODIMP E::Run() {
michael@0 478 // if (!mResource)
michael@0 479 // return NS_OK;
michael@0 480 // ...
michael@0 481 // mResource->EventHandled();
michael@0 482 // return NS_OK;
michael@0 483 // }
michael@0 484 //
michael@0 485 template <class T>
michael@0 486 class nsRevocableEventPtr {
michael@0 487 public:
michael@0 488 nsRevocableEventPtr()
michael@0 489 : mEvent(nullptr) {
michael@0 490 }
michael@0 491
michael@0 492 ~nsRevocableEventPtr() {
michael@0 493 Revoke();
michael@0 494 }
michael@0 495
michael@0 496 const nsRevocableEventPtr& operator=(T *event) {
michael@0 497 if (mEvent != event) {
michael@0 498 Revoke();
michael@0 499 mEvent = event;
michael@0 500 }
michael@0 501 return *this;
michael@0 502 }
michael@0 503
michael@0 504 void Revoke() {
michael@0 505 if (mEvent) {
michael@0 506 mEvent->Revoke();
michael@0 507 mEvent = nullptr;
michael@0 508 }
michael@0 509 }
michael@0 510
michael@0 511 void Forget() {
michael@0 512 mEvent = nullptr;
michael@0 513 }
michael@0 514
michael@0 515 bool IsPending() {
michael@0 516 return mEvent != nullptr;
michael@0 517 }
michael@0 518
michael@0 519 T *get() { return mEvent; }
michael@0 520
michael@0 521 private:
michael@0 522 // Not implemented
michael@0 523 nsRevocableEventPtr(const nsRevocableEventPtr&);
michael@0 524 nsRevocableEventPtr& operator=(const nsRevocableEventPtr&);
michael@0 525
michael@0 526 nsRefPtr<T> mEvent;
michael@0 527 };
michael@0 528
michael@0 529 /**
michael@0 530 * A simple helper to suffix thread pool name
michael@0 531 * with incremental numbers.
michael@0 532 */
michael@0 533 class nsThreadPoolNaming
michael@0 534 {
michael@0 535 public:
michael@0 536 nsThreadPoolNaming() : mCounter(0) {}
michael@0 537
michael@0 538 /**
michael@0 539 * Creates and sets next thread name as "<aPoolName> #<n>"
michael@0 540 * on the specified thread. If no thread is specified (aThread
michael@0 541 * is null) then the name is synchronously set on the current thread.
michael@0 542 */
michael@0 543 void SetThreadPoolName(const nsACString & aPoolName,
michael@0 544 nsIThread * aThread = nullptr);
michael@0 545
michael@0 546 private:
michael@0 547 volatile uint32_t mCounter;
michael@0 548
michael@0 549 nsThreadPoolNaming(const nsThreadPoolNaming &) MOZ_DELETE;
michael@0 550 void operator=(const nsThreadPoolNaming &) MOZ_DELETE;
michael@0 551 };
michael@0 552
michael@0 553 /**
michael@0 554 * Thread priority in most operating systems affect scheduling, not IO. This
michael@0 555 * helper is used to set the current thread to low IO priority for the lifetime
michael@0 556 * of the created object. You can only use this low priority IO setting within
michael@0 557 * the context of the current thread.
michael@0 558 */
michael@0 559 class MOZ_STACK_CLASS nsAutoLowPriorityIO
michael@0 560 {
michael@0 561 public:
michael@0 562 nsAutoLowPriorityIO();
michael@0 563 ~nsAutoLowPriorityIO();
michael@0 564
michael@0 565 private:
michael@0 566 bool lowIOPrioritySet;
michael@0 567 #if defined(XP_MACOSX)
michael@0 568 int oldPriority;
michael@0 569 #endif
michael@0 570 };
michael@0 571
michael@0 572
michael@0 573
michael@0 574 #endif // nsThreadUtils_h__

mercurial