⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 schedcl.cpp

📁 OPCSERVER源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
    upt->bandwidth0 += percent * period;
   }
 upt->bandwidth = (upt->bandwidth0 + (1 << 11)) / (1 << 12);
#endif
#endif

#if 0 == SATURATE_PERCENT
  if (upt->bandwidth > 100) upt->bandwidth = 100;
#endif

SkipBW:
 if (upt->bandwidth >= 2)
   {
    if (statperiod < loSTATPERIOD) statperiod = loSTATPERIOD;
    statperiod += statperiod >> 1;
    if (statperiod <= nextsleep) nextsleep = statperiod >> 1;
//       UL_WARNING((LOGID, "UPDATE %u%% -> %u", (int)upt->bandwidth, nextsleep));
   }
 if (loMAXSLEEP <  nextsleep &&
     loMAXSLEEP < (nextsleep >>= 1)) nextsleep = loMAXSLEEP;
/* if (nextsleep > 20000)
   {
    UL_WARNING((LOGID, "UPDATE %u", nextsleep));
   }*/
 upt->nextsleep = nextsleep;

 return;
}

DWORD lo_adjust_bandwidth(DWORD bandwidth, loMilliSec bandw_time, loMilliSec curtime)
{
 if (-1 != bandwidth)
   {
    curtime -= bandw_time;
    curtime -= loSTATPERIOD >> 4;
    if (curtime < ~curtime) /* no overflow */
      {
       curtime  +=  loSTATPERIOD;
       bandwidth = (loSTATPERIOD * bandwidth + (curtime >> 1)) / curtime;
      }
   }
 return bandwidth;
}

static void unadvise_all(LightOPCServer *cli);

/* Be careful looking on "#if LO_TIMEBACK": here are 4(!) 
   different handlig for this minor problem. 
In short words, under some circumance (e.g. runnning VDM)
the Win2k may produce delays that are shorter than requested.
For example, Sleep(20) may awake after 15ms. Then Sleep(5) 
returns immediately (i.e. there would be a few hundreds of Sleep(5) 
for real delay of 5ms). 

I don't know is it problem of Sleep() or WaitFor...() or GetTickCount().
Is it problem of waiting or rounding of system clocks...
Anyway we have a problem.

Basically we have to increase delay by the timer granularity 
on the next sleep. We have following choices:

LO_TIMEBACK == 0 : ignore problem. Call cond_wait(...,delay) till the 
time elapsed. It's a kind of empty loop with too much context switches.

Otherwise we can detect we have been awoked before requsted and no 
other events pending.

LO_TIMEBACK > 0 : run the _one_ empty update cycle and then increase
delay (round-up) for some (LO_TIMEBACK ms) time:
        a) rounding-up by nanosecond recalculation of timer granularity;
        b) simply add the granularity (millisecond accuracy) 
           to the NEXTSLEEP.

LO_TIMEBACK < 0 : assume we have awoken at the time; 
perform update cycle prematurely as if it just in time (round-down);
then increase NEXTSLEEP by the difference of the real and 
assumed time [TimeShift].

The last way minimizes average updaterate error.
*/

void LightOPCServer::client_scheduler(void)
{
#if LO_TIMEBACK > 0 /* round up */
 loMilliSec TimeBack = 0;
#endif
#if LO_TIMEBACK < 0 /* round down */
 loMilliSec TimeShift = 0;
#else
# define    TimeShift  (0)
#endif
 loUpdTimes upt;
 loDCL_ABSTIME(abst);
// if (!loIS_VALID(this)) return;
 UL_NOTICE((LOG_SR("thr_async(%p) started"), this));
 loThrControl_accept(&async);
 memset(&upt, 0, sizeof(upt));
 upt.nextsleep = loMAXSLEEP;
 lo_MILLISECABS(upt.finish, abst);

 lw_mutex_lock(&async.lk);

 if (async.tstate >= 0)
   {
#if LO_USE_BOTHMODEL
 if (0 == ole_initialized &&
     (/*se->driver.*/ldFlags & loDf_BOTHMODEL))
   {
    HRESULT oli = CoInitializeEx(NULL, COINIT_MULTITHREADED);
    if (SUCCEEDED(oli)) ole_initialized = 1;
    else UL_WARNING((LOGID, "%!l client_scheduler(%p)::CoInitialize() FAILED",
                   oli, this));
   }
#endif

 for(;;)
   {
//if (async.state) UL_ERROR((LOG_SR("SHC  %d"), async.state));
#if 0
 UL_DEBUG((LOGID, "WA:%d %u + %ums =%u", 
   upt.datasent, bandwidth_time, upt.nextsleep, bandwidth_time + upt.nextsleep));
#endif
    if (0 == async.tstate && /* don't sleep when a request pending! */
        !(shuttingdown && shutdown_conn.request))
      {
#if LO_TIMEBACK > 0
       if (TimeBack)
         {
          if ((bandwidth_time - TimeBack) > LO_TIMEBACK) TimeBack = 0;
#if 1
          /* millisec round-up */
          lw_conds_timedwait(&async.cond, &async.lk, 
                             loABSREL(abst, upt.nextsleep + lo_timegran_ms));
          UL_DEBUG((LOGID, "WAIT AA: %u", lo_timegran_ms));
#else
          /* nanosec round-up */
          unsigned add_sleep;
          ULONGLONG upt_nextsleep = upt.nextsleep;
          upt_nextsleep *= 10000;
          if (add_sleep = (unsigned)(upt_nextsleep % lo_timegran_100ns))
            add_sleep = (lo_timegran_100ns - add_sleep + 9999) / 10000 & 0x0ff;
               /* add no more than 1/4 sec */
          lw_conds_timedwait(&async.cond, &async.lk, 
                             loABSREL(abst, upt.nextsleep add_sleep));
          UL_DEBUG((LOGID, "WAIT AA: %u", add_sleep));
#endif
         }
       else 
#endif /*LO_TIMEBACK > 0*/
       lw_conds_timedwait(&async.cond, &async.lk, 
                         loABSREL(abst, upt.nextsleep + TimeShift));
      }
    LO_HEAPCHECK(this);
    if (async.tstate < 0) break;
    lo_MILLISEC(upt.awoke);
#if 1
// if (bandwidth_time + upt.nextsleep >= upt.awoke)
   UL_DEBUG((LOGID, "WAIT WA:%d:%d %u + %ums =%u %+d", 
   upt.datasent, async.tstate, 
   bandwidth_time, upt.nextsleep, bandwidth_time + upt.nextsleep,   
   upt.awoke - (bandwidth_time + upt.nextsleep)));
#endif

    if (!async.tstate && !lo_NO_TIMEBACK &&
        upt.nextsleep > upt.awoke - bandwidth_time)
#if LO_TIMEBACK < 0
      {
        /* round down */
        UL_TRACE((LOGID, "WAITing problem was:%d now:%d", 
          TimeShift, upt.nextsleep - (upt.awoke - bandwidth_time)));
        TimeShift = upt.nextsleep - (upt.awoke - bandwidth_time);
        if (TimeShift > lo_timegran_ms) TimeShift = 0/*lo_timegran_ms*/;
        upt.awoke += TimeShift;
      }
    else TimeShift = 0;
#elif LO_TIMEBACK > 0
      {
        /* round up */
        TimeBack = upt.awoke;
        UL_TRACE((LOGID, "WAITing problem"));
      }
#else
    UL_WARNING((LOGID, "WAITing problem")); /* no solution */
#endif /*LO_TIMEBACK*/

    if (shuttingdown && shutdown_conn.request)
      {
       loShutdownConn sc = shutdown_conn;
       loShutdownConn_init(&shutdown_conn);
       lw_mutex_unlock(&async.lk);
       UL_NOTICE((LOG_SR("Going to IOPCShutdown")));
       loShutdownConn_call(&sc);
       lw_mutex_lock(&async.lk);
      }
    if (loThrControl_outof01(&async))
      {
       UL_DEBUG((LOG_SR("Going to shutdown (%p) ..."), this));
       loShutdownConn_clear(&shutdown_conn);
       lw_mutex_unlock(&async.lk); /* MUST be called outside of lock !!!*/
       UL_NOTICE((LOG_SR("Unadvising groups thr_async(%p) ..."), this));
       unadvise_all(this);
       otrk.ot_disconnect_all(0);
       clear_all();
       otrk.ot_disconnect_all(0);
       loQueueBcast_abort(&q_ret);
       UL_NOTICE((LOG_SR("Self terminating thr_async(%p) ..."), this));
       selfdestroy(); /* at this point <this> is no longer valid */
       UL_NOTICE((LOGID, "Self terminating thr_async(%p) Ok", this));
       return;
      }
/* on stopped we have to sleep
   on shutdown we have to sleep or to break */
    else
      {
       if (1 == async.tstate) /* no timeout occured */
         {
          async.tstate = 0; /* clear signal */
          if (q_req.req)
            {
             lo_rio_requests(this); /* Do requests first ==> low delay */
             if (loThrControl_outof01(&async)) continue;
            }
         }
       lw_mutex_unlock(&async.lk);

       upt.datasent = 0;
       upt.overload = 0;
       upt.updated = 0;
       upt.nextsleep = loHUGESLEEP;

       lo_MILLISEC(upt.beginupd);  upt.beginupd += TimeShift;
       update_sheduler(otrk.ot_stopped? 0: this, se, &upt);

       lw_mutex_lock(&async.lk);
#if 0
       if (q_req.req)
         {
          lo_rio_requests(this);  /* it does loThrControl_outof01(&async); */
         }
#endif
       if (upt.datasent) se->driver.ldCurrentTime(&ctxt.cactx, &ostatus.ftLastUpdateTime);

       lo_MILLISECABS(bandwidth_time, abst);  bandwidth_time += TimeShift;
       sched_timings(&upt, bandwidth_time);
       ostatus.dwBandWidth = /*stopped? (DWORD)-1: */(DWORD)upt.bandwidth;
      }
#if 0
    if (shuttingdown && upt.nextsleep > 4096) upt.nextsleep = 4096;
#endif
   } /* end of for(;;) */
 } /* if (async.tstate >= 0) */

{
#if LO_USE_BOTHMODEL
 int oleini = ole_initialized; ole_initialized = 0;
#endif

 loThrControl_finish(&async);
 lw_mutex_unlock(&async.lk);

 UL_NOTICE((LOGID, "thr_async(%p) finished", this));
#if LO_USE_BOTHMODEL
 if (oleini) CoUninitialize();
#endif
}
}

static void unadvise_all(LightOPCServer *cli)
{
 unsigned gndx;
 LightOPCGroup **grpl;

 cli->lock_read();
 gndx = cli->grl.gl_count;
 grpl = (LightOPCGroup**)cli->grl.gl_list;
 while(gndx)
   {
    LightOPCGroup *grp;
    if ((grp = grpl[--gndx]) && grp->advise_present)
      grp->clear_advise();
   }
 cli->unlock();
}
/* end of shedcl.cpp */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -