> 
> Yes. Once can set the priority but that leaves the problem of how to avoid
> 100% CPU useage.
> 
> Here is an idea. If the function called by ->fire() return false, the
> function is removed from the gtk_idle queue.
> 
> For a background spellchecking, after each block is spell-checked, the
> function could return true if there was another block in the queue and
> false if not.
> 
> Spell-checking would be restarted via a timer::set() or timer::start() and
> continue until all the blocks are spell checked.
> 
> What do think?

I think this is not a good idea. This is because this is very platform
dependant. If there is a similar mechanism in Win32, it will probably
not remove the function from the queue if it returns false).

It would (probably) be better to do proper bookkeeping on the timers
and remove a function from the idle queue if there is nothing to do. I
included a patch to do just this. The patch may also build on Win32,
because I implemented a 'dummy' , maybe someone can replace it with
something better?

Please have a look and comment on anything that could be done better.

Cheers,
Ben.

-- 
  Ben Mesman                   Snow b.v. - Unix consultants & OO developers 
  The Amazing Snowmen          Produktgroep Open Source
diff -ruN abi.orig/src/af/util/unix/ut_unixTimer.cpp 
abi/src/af/util/unix/ut_unixTimer.cpp
--- abi.orig/src/af/util/unix/ut_unixTimer.cpp  Tue Mar 27 10:35:45 2001
+++ abi/src/af/util/unix/ut_unixTimer.cpp       Wed Aug 29 12:13:27 2001
@@ -75,6 +75,7 @@
        */
        stop();
 
+       m_bDoAsFastAsPossible = false;
        m_iGtkTimerId = gtk_timeout_add(iMilliseconds, _Timer_Proc, this);
 
        if (getIdentifier() == 0)
@@ -87,6 +88,31 @@
        return 0;
 }
 
+UT_sint32 UT_UNIXTimer::setAsFastAsPossible()
+{
+  /*
+    The goal here is to put a function in an idle queue.  This method
+    should not block.  It should call some OS routine which provides
+    idle facilities, or use another timing mechanism.  It is assumed
+    that this routine requires a C callback.  That callback, when it
+    is called, must look up the UT_Timer object which corresponds to
+    it, and call its fire() method.  See ut_unixTimer.cpp for an
+    example of how it's done with GTK.  We're hoping that something
+    similar will work for other platforms.
+  */
+  stop();
+
+  m_bDoAsFastAsPossible = true;
+  m_iGtkTimerId = gtk_idle_add(_Timer_Proc, this);
+
+  if (getIdentifier() == 0)
+    setIdentifier(m_iGtkTimerId);
+
+  m_iMilliseconds = 0;
+
+  return 0;
+}
+
 void UT_UNIXTimer::stop()
 {
        // stop the delivery of timer events.
@@ -94,15 +120,24 @@
        if (m_iGtkTimerId != 0)
        {
 //             UT_DEBUGMSG(("ut_unixTimer.cpp: timer [%d] (with id [%d]) stopped\n", 
getIdentifier(), m_iGtkTimerId));
-               gtk_timeout_remove(m_iGtkTimerId);
+               if (m_bDoAsFastAsPossible)
+                 gtk_idle_remove(m_iGtkTimerId);
+               else
+                 gtk_timeout_remove(m_iGtkTimerId);
                m_iGtkTimerId = 0;
        }
 }
 
 void UT_UNIXTimer::start()
 {
-       // resume the delivery of events.
-       UT_ASSERT(m_iMilliseconds > 0);
-       set(m_iMilliseconds);
+  if (m_bDoAsFastAsPossible)
+    {
+      setAsFastAsPossible();
+    }
+  else
+    {
+      UT_ASSERT(m_iMilliseconds > 0);
+      set(m_iMilliseconds);
+    }
 }
 
diff -ruN abi.orig/src/af/util/unix/ut_unixTimer.h abi/src/af/util/unix/ut_unixTimer.h
--- abi.orig/src/af/util/unix/ut_unixTimer.h    Fri Jul 27 15:47:11 2001
+++ abi/src/af/util/unix/ut_unixTimer.h Wed Aug 29 11:42:09 2001
@@ -31,12 +31,14 @@
        virtual ~UT_UNIXTimer();
 
        virtual UT_sint32 set(UT_uint32 iMilliseconds);
+       virtual UT_sint32 setAsFastAsPossible();
        virtual void stop();
        virtual void start();
        
 private:
        UT_sint32 m_iMilliseconds;
        UT_uint32 m_iGtkTimerId;
+       bool m_bDoAsFastAsPossible;
 };
 
 #endif /* UT_UNIXTIMER_H */
diff -ruN abi.orig/src/af/util/win/ut_Win32Timer.cpp 
abi/src/af/util/win/ut_Win32Timer.cpp
--- abi.orig/src/af/util/win/ut_Win32Timer.cpp  Fri Jul 27 23:34:02 2001
+++ abi/src/af/util/win/ut_Win32Timer.cpp       Wed Aug 29 11:42:09 2001
@@ -24,6 +24,8 @@
 #include "ut_assert.h"
 #include "gr_Win32Graphics.h"
 
+#define DEFAULT_MSECS 100
+
 /*****************************************************************/
        
 UT_Timer* UT_Timer::static_constructor(UT_TimerCallback pCallback, void* pData, 
GR_Graphics * pG)
@@ -90,6 +92,16 @@
        m_bStarted = true;
        setIdentifier(idTimer);
        return 0;
+}
+
+UT_sint32 UT_Win32Timer::setAsFastAsPossible()
+{
+  // Just a placeholder until someone implements an idle-queue
+  // mechanism. See ut_unixTimer.cpp for more information.
+  m_iMilliseconds = DEFAULT_MSECS;
+       
+  if (!m_bStarted)
+    set(m_iMilliseconds);
 }
 
 void UT_Win32Timer::stop(void)
diff -ruN abi.orig/src/af/util/win/ut_Win32Timer.h abi/src/af/util/win/ut_Win32Timer.h
--- abi.orig/src/af/util/win/ut_Win32Timer.h    Tue Feb  6 23:54:10 2001
+++ abi/src/af/util/win/ut_Win32Timer.h Wed Aug 29 11:42:09 2001
@@ -31,6 +31,7 @@
        ~UT_Win32Timer();
 
        virtual UT_sint32 set(UT_uint32 iMilliseconds);
+       virtual UT_sint32 setAsFastAsPossible();
        virtual void stop(void);
        virtual void start(void);
 
diff -ruN abi.orig/src/af/util/xp/ut_timer.h abi/src/af/util/xp/ut_timer.h
--- abi.orig/src/af/util/xp/ut_timer.h  Thu Jul 26 22:59:27 2001
+++ abi/src/af/util/xp/ut_timer.h       Wed Aug 29 11:42:09 2001
@@ -46,6 +46,7 @@
        void* getInstanceData();
        
        virtual UT_sint32 set(UT_uint32 iMilliseconds) = 0;     /* set freq and start 
*/
+       virtual UT_sint32 setAsFastAsPossible() = 0;    /* set idle and start */
        virtual void stop(void) = 0;            /* suspend events */
        virtual void start(void) = 0;           /* resume events */
        void fire();
--- abi.orig/src/text/fmt/xp/fl_DocLayout.cpp   Wed Aug 29 09:10:18 2001
+++ abi/src/text/fmt/xp/fl_DocLayout.cpp        Wed Aug 29 11:53:28 2001
@@ -897,12 +897,13 @@
                }
        }
 
-       if (i != 0 && pDocLayout->m_bStopSpellChecking == false)
+       if (i == 0) //&& pDocLayout->m_bStopSpellChecking == false)
        {
-               // restart timer unless it's not needed any more
-               //pDocLayout->m_pBackgroundCheckTimer->start();
+               // stop timer if it's not needed any more
+               pDocLayout->m_pBackgroundCheckTimer->stop();
        }
        pDocLayout->m_bImSpellCheckingNow = false;
+       return;
 }
 
 void FL_DocLayout::queueBlockForBackgroundCheck(UT_uint32 reason, fl_BlockLayout 
*pBlock, bool bHead)
@@ -916,7 +917,8 @@
        {
                m_pBackgroundCheckTimer = 
UT_Timer::static_constructor(_backgroundCheck, this, m_pG);
                if (m_pBackgroundCheckTimer)
-                       m_pBackgroundCheckTimer->set(BACKGROUND_CHECK_MSECS);
+                       //m_pBackgroundCheckTimer->set(BACKGROUND_CHECK_MSECS);
+                       m_pBackgroundCheckTimer->setAsFastAsPossible();
        }
        else
        {

Reply via email to