michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* vim: set ts=2 et sw=2 tw=80: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this file, michael@0: * You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this file, michael@0: * You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: // Original code by: ekr@rtfm.com michael@0: michael@0: // Implementation of the NR timer interface michael@0: michael@0: // Some code here copied from nrappkit. The license was. michael@0: michael@0: /** michael@0: Copyright (C) 2004, Network Resonance, Inc. michael@0: Copyright (C) 2006, Network Resonance, Inc. michael@0: All Rights Reserved michael@0: michael@0: Redistribution and use in source and binary forms, with or without michael@0: modification, are permitted provided that the following conditions michael@0: are met: michael@0: michael@0: 1. Redistributions of source code must retain the above copyright michael@0: notice, this list of conditions and the following disclaimer. michael@0: 2. Redistributions in binary form must reproduce the above copyright michael@0: notice, this list of conditions and the following disclaimer in the michael@0: documentation and/or other materials provided with the distribution. michael@0: 3. Neither the name of Network Resonance, Inc. nor the name of any michael@0: contributors to this software may be used to endorse or promote michael@0: products derived from this software without specific prior written michael@0: permission. michael@0: michael@0: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' michael@0: AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE michael@0: IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE michael@0: ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE michael@0: LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR michael@0: CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF michael@0: SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS michael@0: INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN michael@0: CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) michael@0: ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE michael@0: POSSIBILITY OF SUCH DAMAGE. michael@0: michael@0: michael@0: ekr@rtfm.com Sun Feb 22 19:35:24 2004 michael@0: */ michael@0: michael@0: #include michael@0: michael@0: #include "nsCOMPtr.h" michael@0: #include "nsComponentManagerUtils.h" michael@0: #include "nsServiceManagerUtils.h" michael@0: #include "nsIEventTarget.h" michael@0: #include "nsITimer.h" michael@0: #include "nsNetCID.h" michael@0: #include "runnable_utils.h" michael@0: michael@0: extern "C" { michael@0: #include "nr_api.h" michael@0: #include "async_timer.h" michael@0: } michael@0: michael@0: michael@0: namespace mozilla { michael@0: michael@0: class nrappkitTimerCallback : public nsITimerCallback michael@0: { michael@0: public: michael@0: // We're going to release ourself in the callback, so we need to be threadsafe michael@0: NS_DECL_THREADSAFE_ISUPPORTS michael@0: NS_DECL_NSITIMERCALLBACK michael@0: michael@0: nrappkitTimerCallback(NR_async_cb cb, void *cb_arg, michael@0: const char *function, int line) michael@0: : cb_(cb), cb_arg_(cb_arg), function_(function), line_(line) { michael@0: } michael@0: michael@0: private: michael@0: virtual ~nrappkitTimerCallback() {} michael@0: michael@0: protected: michael@0: /* additional members */ michael@0: NR_async_cb cb_; michael@0: void *cb_arg_; michael@0: std::string function_; michael@0: int line_; michael@0: }; michael@0: michael@0: NS_IMPL_ISUPPORTS(nrappkitTimerCallback, nsITimerCallback) michael@0: michael@0: NS_IMETHODIMP nrappkitTimerCallback::Notify(nsITimer *timer) { michael@0: r_log(LOG_GENERIC, LOG_DEBUG, "Timer callback fired (set in %s:%d)", michael@0: function_.c_str(), line_); michael@0: michael@0: cb_(0, 0, cb_arg_); michael@0: michael@0: // Allow the timer to go away. michael@0: timer->Release(); michael@0: return NS_OK; michael@0: } michael@0: } // close namespace michael@0: michael@0: michael@0: using namespace mozilla; michael@0: michael@0: // These timers must only be used from the STS thread. michael@0: // This function is a helper that enforces that. michael@0: static void CheckSTSThread() { michael@0: nsresult rv; michael@0: michael@0: nsCOMPtr sts_thread; michael@0: michael@0: sts_thread = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv); michael@0: michael@0: MOZ_ASSERT(NS_SUCCEEDED(rv)); michael@0: ASSERT_ON_THREAD(sts_thread); michael@0: } michael@0: michael@0: int NR_async_timer_set(int timeout, NR_async_cb cb, void *arg, char *func, michael@0: int l, void **handle) { michael@0: nsresult rv; michael@0: CheckSTSThread(); michael@0: michael@0: nsCOMPtr timer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv); michael@0: if (NS_FAILED(rv)) { michael@0: return(R_FAILED); michael@0: } michael@0: michael@0: rv = timer->InitWithCallback(new nrappkitTimerCallback(cb, arg, func, l), michael@0: timeout, nsITimer::TYPE_ONE_SHOT); michael@0: if (NS_FAILED(rv)) { michael@0: return R_FAILED; michael@0: } michael@0: michael@0: // We need an AddRef here to keep the timer alive, per the spec. michael@0: timer->AddRef(); michael@0: michael@0: if (handle) michael@0: *handle = timer.get(); michael@0: // Bug 818806: if we have no handle to the timer, we have no way to avoid michael@0: // it leaking (though not the callback object) if it never fires (or if michael@0: // we exit before it fires). michael@0: michael@0: return 0; michael@0: } michael@0: michael@0: int NR_async_schedule(NR_async_cb cb, void *arg, char *func, int l) { michael@0: // No need to check the thread because we check it next in the michael@0: // timer set. michael@0: return NR_async_timer_set(0, cb, arg, func, l, nullptr); michael@0: } michael@0: michael@0: int NR_async_timer_cancel(void *handle) { michael@0: // Check for the handle being nonzero because sometimes we get michael@0: // no-op cancels that aren't on the STS thread. This can be michael@0: // non-racy as long as the upper-level code is careful. michael@0: if (!handle) michael@0: return 0; michael@0: michael@0: CheckSTSThread(); michael@0: michael@0: nsITimer *timer = static_cast(handle); michael@0: michael@0: timer->Cancel(); michael@0: // Allow the timer to go away. michael@0: timer->Release(); michael@0: michael@0: return 0; michael@0: } michael@0: