[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Dotgnu-pnet-commits] CVS: pnetlib/Xsharp Timer.cs,NONE,1.1 TimerCallba
From: |
Rhys Weatherley <address@hidden> |
Subject: |
[Dotgnu-pnet-commits] CVS: pnetlib/Xsharp Timer.cs,NONE,1.1 TimerCallback.cs,NONE,1.1 Display.cs,1.2,1.3 Xlib.cs.in,1.4,1.5 |
Date: |
Fri, 06 Jun 2003 22:18:41 -0400 |
Update of /cvsroot/dotgnu-pnet/pnetlib/Xsharp
In directory subversions:/tmp/cvs-serv12827/Xsharp
Modified Files:
Display.cs Xlib.cs.in
Added Files:
Timer.cs TimerCallback.cs
Log Message:
Add timeout support to Xsharp.
--- NEW FILE ---
/*
* Timer.cs - Timer handling for Xsharp.
*
* Copyright (C) 2003 Southern Storm Software, Pty Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
namespace Xsharp
{
using System;
/// <summary>
/// <para>Instances of <see cref="T:Xsharp.Timer"/> are used to
/// implement timeout functionality on X displays.</para>
/// </summary>
///
/// <remarks>
/// <para>The delivery of timeout notifications may be delayed by
/// event processing, operating system housekeeping, or system load.
/// That is, they are not delivered in "real time". The only
/// guarantee is that they will be delivered on or sometime after
/// the specified time.</para>
/// </remarks>
public sealed class Timer : IDisposable
{
// Internal state.
private Display dpy;
private TimerCallback callback;
private Object state;
private DateTime nextDue;
private int period;
private bool onDisplayQueue;
private bool stopped;
private Timer next;
private Timer prev;
/// <summary>
/// <para>Create a new timer.</para>
/// </summary>
///
/// <param name="callback">
/// <para>The delegate to invoke when the timer expires.</para>
/// </param>
///
/// <param name="state">
/// <para>The state information to pass to the callback.</para>
/// </param>
///
/// <param name="dueTime">
/// <para>The number of milliseconds until the timer expires
/// for the first time.</para>
/// </param>
///
/// <exception cref="T:System.ArgumentNullException">
/// <para>The <paramref name="callback"/> parameter is
/// <see langword="null"/>.</para>
/// </exception>
///
/// <exception cref="T:System.ArgumentOutOfRangeException">
/// <para>The <paramref name="dueTime"/> parameter is
/// less than zero.</para>
/// </exception>
public Timer(TimerCallback callback, Object state, int dueTime)
: this(null, callback, state, dueTime, -1) {}
/// <summary>
/// <para>Create a new timer.</para>
/// </summary>
///
/// <param name="callback">
/// <para>The delegate to invoke when the timer expires.</para>
/// </param>
///
/// <param name="state">
/// <para>The state information to pass to the callback.</para>
/// </param>
///
/// <param name="dueTime">
/// <para>The number of milliseconds until the timer expires
/// for the first time.</para>
/// </param>
///
/// <param name="period">
/// <para>The number of milliseconds between timer expiries, or
/// -1 to only expire once at <paramref name="dueTime"/>.</para>
/// </param>
///
/// <exception cref="T:System.ArgumentNullException">
/// <para>The <paramref name="callback"/> parameter is
/// <see langword="null"/>.</para>
/// </exception>
///
/// <exception cref="T:System.ArgumentOutOfRangeException">
/// <para>The <paramref name="dueTime"/> parameter is
/// less than zero.</para>
/// </exception>
public Timer(TimerCallback callback, Object state,
int dueTime, int period)
: this(null, callback, state, dueTime, period) {}
/// <summary>
/// <para>Create a new timer.</para>
/// </summary>
///
/// <param name="dpy">
/// <para>The display to create the timer for, or <see langword="null"/>
/// to use the application's primary display.</para>
/// </param>
///
/// <param name="callback">
/// <para>The delegate to invoke when the timer expires.</para>
/// </param>
///
/// <param name="state">
/// <para>The state information to pass to the callback.</para>
/// </param>
///
/// <param name="dueTime">
/// <para>The number of milliseconds until the timer expires
/// for the first time.</para>
/// </param>
///
/// <exception cref="T:System.ArgumentNullException">
/// <para>The <paramref name="callback"/> parameter is
/// <see langword="null"/>.</para>
/// </exception>
///
/// <exception cref="T:System.ArgumentOutOfRangeException">
/// <para>The <paramref name="dueTime"/> parameter is
/// less than zero.</para>
/// </exception>
public Timer(Display dpy, TimerCallback callback,
Object state, int dueTime)
: this(dpy, callback, state, dueTime, -1) {}
/// <summary>
/// <para>Create a new timer.</para>
/// </summary>
///
/// <param name="dpy">
/// <para>The display to create the timer for, or <see langword="null"/>
/// to use the application's primary display.</para>
/// </param>
///
/// <param name="callback">
/// <para>The delegate to invoke when the timer expires.</para>
/// </param>
///
/// <param name="state">
/// <para>The state information to pass to the callback.</para>
/// </param>
///
/// <param name="dueTime">
/// <para>The number of milliseconds until the timer expires
/// for the first time.</para>
/// </param>
///
/// <param name="period">
/// <para>The number of milliseconds between timer expiries, or
/// -1 to only expire once at <paramref name="dueTime"/>.</para>
/// </param>
///
/// <exception cref="T:System.ArgumentNullException">
/// <para>The <paramref name="callback"/> parameter is
/// <see langword="null"/>.</para>
/// </exception>
///
/// <exception cref="T:System.ArgumentOutOfRangeException">
/// <para>The <paramref name="dueTime"/> parameter is
/// less than zero.</para>
/// </exception>
public Timer(Display dpy, TimerCallback callback,
Object state, int dueTime, int period)
{
if(callback == null)
{
throw new
ArgumentNullException("callback");
}
if(dpy == null)
{
this.dpy = Application.Primary.Display;
}
else
{
this.dpy = dpy;
}
if(dueTime < 0)
{
throw new ArgumentOutOfRangeException
("dueTime",
S._("X_NonNegative"));
}
this.callback = callback;
this.state = state;
this.nextDue =
DateTime.Now + new TimeSpan
(dueTime *
TimeSpan.TicksPerMillisecond);
this.period = period;
this.stopped = false;
AddTimer();
}
/// <summary>
/// <para>Change the parameters for this timer.</para>
/// </summary>
///
/// <param name="dueTime">
/// <para>The number of milliseconds until the timer expires
/// for the first time.</para>
/// </param>
///
/// <exception cref="T:System.ArgumentOutOfRangeException">
/// <para>The <paramref name="dueTime"/> parameter is
/// less than zero.</para>
/// </exception>
public void Change(int dueTime)
{
Change(dueTime, -1);
}
/// <summary>
/// <para>Change the parameters for this timer.</para>
/// </summary>
///
/// <param name="dueTime">
/// <para>The number of milliseconds until the timer expires
/// for the first time.</para>
/// </param>
///
/// <param name="period">
/// <para>The number of milliseconds between timer expiries, or
/// -1 to only expire once at <paramref name="dueTime"/>.</para>
/// </param>
///
/// <exception cref="T:System.ArgumentOutOfRangeException">
/// <para>The <paramref name="dueTime"/> parameter is
/// less than zero.</para>
/// </exception>
public void Change(int dueTime, int period)
{
if(dueTime < 0)
{
throw new ArgumentOutOfRangeException
("dueTime",
S._("X_NonNegative"));
}
RemoveTimer();
this.nextDue =
DateTime.Now + new TimeSpan
(dueTime *
TimeSpan.TicksPerMillisecond);
this.period = period;
this.stopped = false;
AddTimer();
}
/// <summary>
/// <para>Dispose of this timer, stopping any pending timeouts.</para>
/// </summary>
public void Dispose()
{
Stop();
}
/// <summary>
/// <para>Stop this timer. Another timeout can be started at
/// some future point using <c>Change</c>.</para>
/// </summary>
public void Stop()
{
stopped = true;
RemoveTimer();
}
// Add the timer to the display's timer queue.
private void AddTimer()
{
lock(dpy)
{
if(!onDisplayQueue)
{
Timer current = dpy.timerQueue;
Timer prev = null;
while(current != null &&
current.nextDue <= nextDue)
{
prev = current;
current = current.next;
}
this.next = current;
this.prev = prev;
if(current != null)
{
current.prev = this;
}
if(prev != null)
{
prev.next = this;
}
else
{
dpy.timerQueue = this;
}
onDisplayQueue = true;
}
}
}
// Remove the timer from the display's timer queue.
private void RemoveTimer()
{
lock(dpy)
{
if(onDisplayQueue)
{
if(next != null)
{
next.prev = prev;
}
if(prev != null)
{
prev.next = next;
}
else
{
dpy.timerQueue = next;
}
onDisplayQueue = false;
next = null;
prev = null;
}
}
}
// Activate timers that have fired on a particular display.
internal static void ActivateTimers(Display dpy)
{
// Bail out early if there are no timers, to
avoid
// calling "DateTime.Now" if we don't need to.
lock(dpy)
{
if(dpy.timerQueue == null)
{
return;
}
}
DateTime now = DateTime.Now;
Timer timer;
DateTime next;
for(;;)
{
// Remove the first timer from the
queue if
// it has expired. Bail out if it
hasn't.
lock(dpy)
{
timer = dpy.timerQueue;
if(timer == null)
{
break;
}
else if(timer.nextDue <= now)
{
timer.RemoveTimer();
}
else
{
break;
}
}
// Invoke the timer's callback delegate.
timer.callback(timer.state);
// Add the timer back onto the queue if
necessary.
if(!timer.stopped &&
!timer.onDisplayQueue)
{
if(timer.period < 0)
{
timer.stopped = true;
}
else
{
next = timer.nextDue +
new
TimeSpan(timer.period *
TimeSpan.TicksPerMillisecond);
while(next <= now)
{
next += new
TimeSpan
(timer.period *
TimeSpan.TicksPerMillisecond);
}
timer.nextDue = next;
timer.AddTimer();
}
}
}
}
// Get the number of milliseconds until the next timeout.
// Returns -1 if there are no active timers.
internal static int GetNextTimeout(Display dpy)
{
lock(dpy)
{
if(dpy.timerQueue != null)
{
DateTime fireAt =
dpy.timerQueue.nextDue;
long diff = fireAt.Ticks -
DateTime.Now.Ticks;
if(diff <= 0)
{
// The timeout has
already fired or is about to.
return 0;
}
else if(diff > (100 *
TimeSpan.TicksPerSecond))
{
// Don't wait more than
100 seconds at a time.
return 100000;
}
else
{
// Return the number of
milliseconds + 1.
// The "+ 1" takes care
of rounding errors
// due to converting
ticks to milliseconds.
return ((int)(diff /
TimeSpan.TicksPerMillisecond))
+ 1;
}
}
}
return -1;
}
} // class Timer
} // namespace Xsharp
--- NEW FILE ---
/*
* TimerCallback.cs - Callback for "Xsharp.Timer" objects.
*
* Copyright (C) 2003 Southern Storm Software, Pty Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
namespace Xsharp
{
using System;
/// <summary>
/// <para>Callback delegate for <see cref="T:Xsharp.Timer"/> objects.</para>
/// </summary>
///
/// <param name="state">
/// <para>The state information that was passed to the timer's constructor.
/// </para>
/// </param>
public delegate void TimerCallback(Object state);
} // namespace Xsharp
Index: Display.cs
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnetlib/Xsharp/Display.cs,v
retrieving revision 1.2
retrieving revision 1.3
diff -C2 -r1.2 -r1.3
*** Display.cs 6 Jun 2003 12:59:44 -0000 1.2
--- Display.cs 7 Jun 2003 02:18:39 -0000 1.3
***************
*** 59,62 ****
--- 59,63 ----
internal Hashtable fonts;
internal BuiltinBitmaps bitmaps;
+ internal Timer timerQueue;
// Constructor.
***************
*** 477,484 ****
--- 478,493 ----
IntPtr dpy = Lock();
XEvent xevent;
+ int timeout;
+
Xlib.XFlush(dpy);
inMainLoop = true;
while(!quit)
{
+ // Flush any requests that are
in the outgoing queue.
+ Xlib.XFlush(dpy);
+
+ // Process timers that need to
be activated.
+ Timer.ActivateTimers(this);
+
// Do we have pending expose
events to process?
if(pendingExposes)
***************
*** 509,514 ****
{
// Wait for the next
event.
! Xlib.XNextEvent(dpy,
out xevent);
! DispatchEvent(ref
xevent);
}
}
--- 518,535 ----
{
// Wait for the next
event.
! timeout =
Timer.GetNextTimeout(this);
! if(timeout < 0)
! {
!
Xlib.XNextEvent(dpy, out xevent);
!
DispatchEvent(ref xevent);
! }
! else
! {
!
if(Xlib.XNextEventWithTimeout
! (dpy,
out xevent, timeout) > 0)
! {
!
DispatchEvent(ref xevent);
! }
! }
}
}
Index: Xlib.cs.in
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnetlib/Xsharp/Xlib.cs.in,v
retrieving revision 1.4
retrieving revision 1.5
diff -C2 -r1.4 -r1.5
*** Xlib.cs.in 7 Jun 2003 00:13:09 -0000 1.4
--- Xlib.cs.in 7 Jun 2003 02:18:39 -0000 1.5
***************
*** 482,485 ****
--- 482,491 ----
(IntPtr display, Window w, Atom property);
+ // Helper functions from "libXsharpSupport.so".
+
+ [DllImport("XsharpSupport")]
+ extern public static @X_int@ XNextEventWithTimeout
+ (IntPtr display, out XEvent xevent, @X_int@ timeout);
+
} // class Xlib
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Dotgnu-pnet-commits] CVS: pnetlib/Xsharp Timer.cs,NONE,1.1 TimerCallback.cs,NONE,1.1 Display.cs,1.2,1.3 Xlib.cs.in,1.4,1.5,
Rhys Weatherley <address@hidden> <=