rate-variable.cc
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:5k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /*
  2.  * Copyright (c) 1995 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  * This product includes software developed by the Computer Systems
  16.  * Engineering Group at Lawrence Berkeley Laboratory.
  17.  * 4. Neither the name of the University nor of the Laboratory may be used
  18.  *    to endorse or promote products derived from this software without
  19.  *    specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33. static const char rcsid[] =
  34.     "@(#) $Header: /cvsroot/otcl-tclcl/tclcl/rate-variable.cc,v 1.4 2005/09/07 04:53:51 tom_henderson Exp $ (LBL)";
  35. #include <stdlib.h>
  36. #include <sys/types.h>
  37. #ifndef WIN32
  38. #include <sys/time.h>
  39. #endif
  40. #include "rate-variable.h"
  41. /*
  42.  * The following command & the associate service procedure
  43.  * creates a `rate variable'.  Reading a rate variable returns
  44.  * the time rate of change of its value.  Writing a rate variable
  45.  * updates the rate of change estimate.  A rate variable can be
  46.  * either simple or an array element.  It must be global.  This
  47.  * routine is called as:
  48.  * rate_variable varname filter_const
  49.  * where 'varname' is the variable name (e.g., "foo" or "foo(bar)")
  50.  * and 'filter_const' is a smoothing constant for the rate estimate.
  51.  * It should be >0 and <1 (a value of 1 will result in no smoothing).
  52.  */
  53. struct rv_data {
  54. double rate;
  55. double filter;
  56. timeval lastupdate;
  57. int lastval;
  58. char format[16];
  59. };
  60. void RateVariable::init()
  61. {
  62. (void)new RateVariable;
  63. }
  64. char* RateVariable::update_rate_var(ClientData clientData, Tcl_Interp* tcl,
  65.     CONST84 char* name1, 
  66.     CONST84 char* name2, int flags)
  67. {
  68. rv_data* rv = (rv_data*)clientData;
  69. if (rv == NULL)
  70. return ("no clientdata for rate var");
  71. if (flags & TCL_TRACE_WRITES) {
  72. /*
  73.  * the variable has been written with a new value.
  74.  * compute the rate of change & make that its vale
  75.  * for subsequent reads.
  76.  */
  77. char res[128];
  78. flags &= TCL_GLOBAL_ONLY;
  79. CONST char* cv = (char *) Tcl_GetVar2(tcl, name1, name2, flags);
  80. if (cv == NULL)
  81. return (tcl->result);
  82. int curval = atoi(cv);
  83. double rate = 0.;
  84. timeval tv;
  85. gettimeofday(&tv, 0);
  86. if (rv->lastupdate.tv_sec != 0) {
  87. /* not first time through */
  88. double dt = double(tv.tv_sec - rv->lastupdate.tv_sec) +
  89.     double(tv.tv_usec -
  90. rv->lastupdate.tv_usec) * 1e-6;
  91. if (dt <= 0.)
  92. /* have to wait until next clock tick */
  93. return NULL;
  94. double dv = double(curval - rv->lastval);
  95. if (dv >= 0.) {
  96. rate = rv->rate;
  97. rate += (dv/dt - rate) * rv->filter;
  98. /* work around tcl f.p. precision bug */
  99. if (rate < 1e-12)
  100. rate = 0.;
  101. }
  102. }
  103. rv->rate = rate;
  104. rv->lastupdate = tv;
  105. rv->lastval = curval;
  106. sprintf(res, rv->format, rate);
  107. Tcl_SetVar2(tcl, name1, name2, res, flags);
  108. } else if (flags & (TCL_TRACE_DESTROYED|TCL_INTERP_DESTROYED)) {
  109. delete rv;
  110. }
  111. return NULL;
  112. }
  113. int RateVariable::command(int argc, const char *const*argv)
  114. {
  115. Tcl& tcl = Tcl::instance();
  116. const char* fmt;
  117. if (argc == 4)
  118. fmt = argv[3];
  119. else if (argc == 3)
  120. fmt = "%g";
  121. else {
  122. tcl.result("usage: rate_variable varname filter_const");
  123. return (TCL_ERROR);
  124. }
  125. double fconst = atof(argv[2]);
  126. if (fconst <= 0. || fconst > 1.) {
  127. tcl.result("rate_variable: invalid filter constant");
  128. return (TCL_ERROR);
  129. }
  130. rv_data* rv = new rv_data;
  131. rv->filter = fconst;
  132. rv->rate = 0.;
  133. rv->lastupdate.tv_sec = 0;
  134. rv->lastval = 0;
  135. strcpy(rv->format, fmt);
  136. int sts = Tcl_TraceVar(tcl.interp(), (char*)argv[1],
  137. TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
  138. (Tcl_VarTraceProc *) update_rate_var, (ClientData)rv);
  139. if (sts != TCL_OK)
  140. delete rv;
  141. return (sts);
  142. }