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

📄 schedcl.cpp

📁 OPCSERVER源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/**************************************************************************
 *                                                                        *
 * Light OPC Server development library                                   *
 *                                                                        *
 *   Copyright (c) 2000  Timofei Bondarenko                               *
                                                                          *
 thread procedures for LightOPCServer::async scheduler
 **************************************************************************/
#ifndef _WIN32_DCOM
#define _WIN32_DCOM /* for CoInitializeEx() */
#endif
#include "privopc.h"
#if 0
#include <malloc.h>
#define LO_HEAPCHECK(pp) { int hc; if (_HEAPOK != (hc = _heapchk())) \
        UL_ERROR((LOGID, "heapchk() %d %p %s %d", hc, pp, __FILE__, __LINE__)); }
#else
#define LO_HEAPCHECK(pp)
#endif

#define loHUGESLEEP  (((loMilliSec)~0)>>2)

#define loMAXSLEEP   (0xfffff) /* ~17min default refresh period */

#if 0
#define SATURATE_PERCENT (1) /* 0/1 */
#define USE_DOUBLE       (1) /* 0/1 */
#define USE_PAIR         (0) /* probably == !USE_DOUBLE */
#else
#define SATURATE_PERCENT (1) /* 0/1 */
#define USE_DOUBLE       (0) /* 0/1 */
#define USE_PAIR         (1) /* probably == !USE_DOUBLE */
#endif

#if 0
#define loSTATPERIOD    (1024) /* time for averaging bandwidth value */
unsigned lo_statperiod(unsigned stp) { return loSTATPERIOD; }
#else
static loMilliSec loSTATPERIOD = 1024/*1412*/;
unsigned lo_statperiod(unsigned stp)
{
 if ((stp >> 2) && stp <= (loHUGESLEEP >> 8)) loSTATPERIOD = stp;
 return loSTATPERIOD;
}
#endif

typedef struct loUpdTimes
  {
   loMilliSec    awoke, beginupd, finish;
   loMilliSec    syncpoint, latency, nextsleep;
   unsigned      datasent, overload, updated;
#if 0 != USE_DOUBLE
   double        bandwidth;
#  if 0 != USE_PAIR
   double        bandwidth0;
#  endif
#else
   unsigned long bandwidth;
#  if 0 != USE_PAIR
   unsigned long bandwidth0;
#  endif
#endif
  } loUpdTimes;

static void update_sheduler(LightOPCServer *cli, loService *se, loUpdTimes *times)
{
 unsigned gndx;
 unsigned advmask;
 LightOPCGroup *grp;
 loMilliSec curtime, syncpoint, latency,
            nextsleep = loHUGESLEEP;
 loUpdList upl;
 lo_upl_init(&upl, loUPL_variant | loUPL_timestamp | loUPL_quality | loUPL_errors |
                   loUPL_opchandle);

 curtime = times->beginupd;

 latency = se->driver.ldRefreshRate;
 syncpoint = curtime + (latency >> 1); /* or latency-1 ? We searching closest synchronization point. */
 latency = (syncpoint - times->syncpoint) % latency;
 times->syncpoint = (syncpoint -= latency);
 times->overload = 0;
 times->updated = 0;
 latency = 0;

 if (cli)
   {
    upl.rctx = cli->ctxt;
    cli->lock_read();
    for(gndx = 0; gndx < cli->grl.gl_count; gndx++)
      if ((grp = (LightOPCGroup*)cli->grl.gl_list[gndx]) && grp->Active &&
         (advmask = grp->advise_present & grp->advise_enabled))
        {
         int justactuated = grp->justactuated;
         loMilliSec updrate = grp->UpdateRate;
         loMilliSec elapsed = curtime - grp->LastUpdate;

         if (justactuated || elapsed >= updrate)
           {
            grp->justactuated = 0;
/******* data refreshing code **********/
            lw_rw_rdlock(&se->lkPrim);
            if (grp->last_trid != se->prim_trid) /* is cache changed? */
              {
               grp->last_trid = se->prim_trid;
               upl.rctx.cta.vc_lcid = grp->grLCID;
               lo_refresh_items(se, &upl, grp);
              }
            lw_rw_unlock(&se->lkPrim);
            if (upl.used)
              {
            /* upl.trqid = 0; */
               times->datasent +=
               cli->send_callback(grp, 0, &upl, advmask | loRQ_OP_REFRESH);
               loVariant_clear(upl.variant, upl.used); upl.used = 0;
               cli->lock_read(); /* relock me again */
              }
/******* end of data refreshing code ***/

            elapsed -= updrate;
            if (elapsed <= updrate && !justactuated)
              {
               if (elapsed > latency) latency = elapsed;
               grp->LastUpdate += updrate; /* Ok */
//         UL_WARNING((LOGID, "late %u/%u = %u%% >>%u ",
  //           elapsed, updrate, load, loadmax));
              }
            else /* we're late */
              {
//         UL_ERROR((LOGID, "late %u", elapsed));
               if (!justactuated)
                 {
                  times->overload++;
#if 0 == SATURATE_PERCENT
                  if (elapsed > latency) latency = elapsed;
#endif
                 }
               elapsed = curtime - (grp->LastUpdate = syncpoint);
              }
            times->updated++;
           } /* if (elapsed >= updrate) */
         updrate -= elapsed;
         if (updrate < nextsleep) nextsleep = updrate;
        } /* end of loop */
    cli->unlock();
   } /* enf of If(cli) */

 lo_upl_clear(&upl);

 times->latency = latency;
 times->nextsleep = nextsleep;
}

/* There are four case for timing:
   a) overload -> 100%
   b) Doesn't updated -> (finish - awoke) / statperiod * 100%
      where:
           statperiod = finish - times->finish
           if (nextsleep <= (finish - beginupd)) nextsleep = 0;
           else nextsleep <= (finish - beginupd);
      Updated:
   c) (finish - awoke) / (finish - awoke + nextsleep) * 100%
   d) (finish - beginupd + latency) /
       (finish - beginupd + latency + nextsleep) * 100%
 */
static void sched_timings(loUpdTimes *upt, loMilliSec finish)
{
 unsigned long percent;
 loMilliSec nextsleep = upt->nextsleep;
 loMilliSec statperiod, consumed2;

 consumed2 = finish - upt->beginupd;
 if (nextsleep > consumed2) nextsleep -= consumed2;
 else nextsleep = 0, upt->overload = 1;

 statperiod = upt->finish;
 upt->finish = finish;
 if (0 == (statperiod = finish - statperiod))
   {
#if 0
    statperiod = 1;
#else
    goto SkipBW;
#endif
   }

#if 0 != SATURATE_PERCENT
 if (upt->overload) percent = 100;
 else
#endif
   {
    unsigned long percent2;
    loMilliSec consumed1 = finish - upt->awoke;

    percent = consumed1 * 100;
    if (consumed1 += nextsleep)
      {
       if (consumed1 > statperiod) consumed1 = statperiod;
       percent = (percent + (consumed1 >> 1)) / consumed1;
      }

    percent2 = (consumed2 + upt->latency) * 100;
#if 0 != SATURATE_PERCENT
    if (consumed2 += nextsleep + upt->latency)
#else
    if (consumed2 = upt->nextsleep + upt->latency)
#endif
      percent2 = (percent2 + (consumed2 >> 1)) / consumed2;

    if (percent < percent2) percent = percent2;

#if 0 == SATURATE_PERCENT
    if (percent > 100)
      {
       statperiod = (statperiod * percent + 50) / 100;
    // UL_ERROR((LOGID, "percent=%u", percent));
       percent = 100;
      }
#else
//    if (percent > 100) UL_ERROR((LOGID, "percent=%u", percent));
#endif
   }

/*
 UL_DEBUG((LOGID, "period=%u/%u percent=%u+%u => %u",
   loSTATPERIOD, statperiod,
   (int)upt->bandwidth, percent, (int)(
   (upt->bandwidth * (loSTATPERIOD - statperiod) +
                   percent * statperiod) / loSTATPERIOD)));
// */
#if 0 == USE_PAIR
 upt->bandwidth = (upt->bandwidth * loSTATPERIOD +
                   percent * statperiod) / (statperiod + loSTATPERIOD);
#else
/*
 normalizing statperiod by statperiod /= shortslice
 to be converted from shortslice <= statperiod <= longslice
                   to  1  <= statperiod <= div_short * div_long
 shortslice = loSTATPERIOD / div_short
 longslice = loSTATPERIOD * div_long
 loSTATPERIOD ==> div_short

  bw0 (old bandwidth) = (bw0 + percent * statperiod) * div_short /
                           (statperiod + div_short)
  bw (current bandwidth) = bw0 / div_short

 to avoid overflows must be :
  (1 << 32) > 100 * div_short * (div_long + 1) * div_short

 thus: 7 bits for "100%"
      25 bits for least: 2 div_short + div_long
 for example div_short = div_long = 1 << 8
 or, for better resolution on short periods:
     div_short = 1 << 10, div_long = 1 << 5
 */
#if 0
{ unsigned long period;

 if (statperiod >= (loSTATPERIOD << 5)) period = 1 << 15;
 else if (0 == (period =
              ((statperiod << 10) + (loSTATPERIOD >> 1)) / loSTATPERIOD))
   period = 1;
 upt->bandwidth0 = (upt->bandwidth0 + percent * period) * (1 << 10);
#if 0
 upt->bandwidth0 /= (1 << 10) + period;
#else
 period += (1 << 10);
 upt->bandwidth0 = (upt->bandwidth0 + (period >> 1)) / period;
#endif
 upt->bandwidth = (upt->bandwidth0 + (1 << 9)) / (1 << 10);
}
#else
 if (statperiod >= (loSTATPERIOD << 1))
   upt->bandwidth0 = percent << 12;
 else
   {
    unsigned long period = ((statperiod << 11) +
                           (loSTATPERIOD >> 1)) / loSTATPERIOD;
    if (0 == period) period = 1;
    else if (period > (1 << 12)) period = 1 << 12;
#if 1
    upt->bandwidth0 -= (upt->bandwidth0 * period + (1 << 11)) / (1 << 12);
#else
    upt->bandwidth0 = (upt->bandwidth0 * ((1 << 12) - period) + (1 << 11)) / (1 << 12);
#endif

⌨️ 快捷键说明

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