summaryrefslogtreecommitdiffstats
path: root/base/timer.h
diff options
context:
space:
mode:
authoragl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-02-20 02:00:04 +0000
committeragl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-02-20 02:00:04 +0000
commite68e62fa169c45bd779bfe890aa4fcdaa24d267d (patch)
treeefdb18adec880e7f780d8cde4e12893d3a20234f /base/timer.h
parent7fe07d0726bad485fa40150aa9f7cecb1318217e (diff)
downloadchromium_src-e68e62fa169c45bd779bfe890aa4fcdaa24d267d.zip
chromium_src-e68e62fa169c45bd779bfe890aa4fcdaa24d267d.tar.gz
chromium_src-e68e62fa169c45bd779bfe890aa4fcdaa24d267d.tar.bz2
Bitmap transport
This patch reworks bitmap transport on all platforms. Linux and Mac are switched from serialising bitmaps over the IPC channel to using shared memory. All platforms gain a shared memory mapping cache on the host side. The concept of a TransportDIB (device independent bitmap) is added to encapsulate most of the platform specifics. On Linux, we use SysV shared memory. This is because X shared pixmaps, which predate POSIX SHM, can only use SysV. By using SysV between renderer and browser, we open up the possibility to map the shared memory directly from the renderer to the X server. On Mac, we use POSIX shared memory. However, since this needs filesystem access and the Mac renderer is sandboxed from the filesystem, we add two new messages from renderer -> browser: The first, AllocTransportDIB, synchronously creates a transport DIB in the browser and passes a handle back to the renderer. The second, FreeTransportDIB, asynchronously, notifies the browser that it may close its handle to the shared memory region. On Mac, the shared memory regions are identified by their inode numbers on the wire. This means that the browser must keep handles open to all the allocated shared memory regions (since an inode number is insufficient to map the region). The alternative design is that the renderer passes the file descriptor with each paint operation. Since passing file descriptors is special case in the code, I felt that it would be best to minimise their use. Creating and freeing transport DIBs are relatively rare operations relative to paints and scrolls. On Windows, most of the code remains the same, except that Windows now uses the mapping cache added in this patch. This allows the browser to maintain a shared memory mapping for a transport DIB over several paints. Previously it mapped and unmapped for every operation, causing lots of TLB and VM churn. Review URL: http://codereview.chromium.org/21485 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@10071 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/timer.h')
-rw-r--r--base/timer.h63
1 files changed, 61 insertions, 2 deletions
diff --git a/base/timer.h b/base/timer.h
index 698d59d..eb00486 100644
--- a/base/timer.h
+++ b/base/timer.h
@@ -89,7 +89,7 @@ class BaseTimer_Helper {
// Used to orphan delayed_task_ so that when it runs it does nothing.
void OrphanDelayedTask();
-
+
// Used to initiated a new delayed task. This has the side-effect of
// orphaning delayed_task_ if it is non-null.
void InitiateDelayedTask(TimerTask* timer_task);
@@ -128,7 +128,7 @@ class BaseTimer : public BaseTimer_Helper {
private:
typedef BaseTimer<Receiver, kIsRepeating> SelfType;
-
+
class TimerTask : public BaseTimer_Helper::TimerTask {
public:
TimerTask(TimeDelta delay, Receiver* receiver, ReceiverMethod method)
@@ -198,6 +198,65 @@ class OneShotTimer : public BaseTimer<Receiver, false> {};
template <class Receiver>
class RepeatingTimer : public BaseTimer<Receiver, true> {};
+//-----------------------------------------------------------------------------
+// A Delay timer is like The Button from Lost. Once started, you have to keep
+// calling Reset otherwise it will call the given method in the MessageLoop
+// thread.
+//
+// Once created, it is inactive until Reset is called. Once |delay| seconds have
+// passed since the last call to Reset, the callback is made. Once the callback
+// has been made, it's inactive until Reset is called again.
+template <class Receiver>
+class DelayTimer {
+ public:
+ typedef void (Receiver::*ReceiverMethod)();
+
+ DelayTimer(TimeDelta delay, Receiver* receiver, ReceiverMethod method)
+ : receiver_(receiver),
+ method_(method),
+ delay_(delay) {
+ }
+
+ void Reset() {
+ DelayFor(delay_);
+ }
+
+ private:
+ void DelayFor(TimeDelta delay) {
+ trigger_time_ = Time::Now() + delay;
+
+ // If we already have a timer that will expire at or before the given delay,
+ // then we have nothing more to do now.
+ if (timer_.IsRunning() && timer_.GetCurrentDelay() <= delay)
+ return;
+
+ // The timer isn't running, or will expire too late, so restart it.
+ timer_.Stop();
+ timer_.Start(delay, this, &DelayTimer<Receiver>::Check);
+ }
+
+ void Check() {
+ if (trigger_time_.is_null())
+ return;
+
+ // If we have not waited long enough, then wait some more.
+ const Time now = Time::Now();
+ if (now < trigger_time_) {
+ DelayFor(trigger_time_ - now);
+ return;
+ }
+
+ (receiver_->*method_)();
+ }
+
+ Receiver *const receiver_;
+ const ReceiverMethod method_;
+ const TimeDelta delay_;
+
+ OneShotTimer<DelayTimer<Receiver> > timer_;
+ Time trigger_time_;
+};
+
} // namespace base
#endif // BASE_TIMER_H_