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

📄 privopc.h

📁 一个OPC服务器开发的源代码。结构清晰
💻 H
📖 第 1 页 / 共 2 页
字号:
/**************************************************************************
 *                                                                        *
 * Light OPC Server development library                                   *
 *                                                                        *
 *   Copyright (c) 2000  Timofei Bondarenko, Kostya Volovich              *
 **************************************************************************/

#ifndef PRIVOPC_H
#define PRIVOPC_H

/**************************************************************************
 TODO:
 It would be better to sort groups by UpdateRate.

 advise_enabled can be eliminated***
 GetEnable() SetEnable() can modify advise_present because
   they are not work if connection was not advised.
   but how we'll find connections for explicit Refresh/Read/Write ?

 make locking for Activate/Deactivate less extensive

 it's better to compute deadband using Requested datatypes

 include TagAlias as reduced RealTag

 CacheRead from PrimaryCache vs Per-Item-Cache? less locks/more updates.

 **************************************************************************
  IMPORTANT:
            Order of the locks. When more than 1 lock should be locked
            they must be locked in this order!
            Otherwise deadlocks can occure.

loService::lkList
loClient::async.lk
loClient::lk_remove
loClient::lk_all
loService::lkDr

loClient::lk_browse
loService::lkMgmt
loService::update_pipe.lk
loService::lkPrim

 **************************************************************************
 Internal declarations:
 **************************************************************************/

#include <opcda.h>	/* The OPC custom interface defintions */
#include <opccomn.h>

#ifndef OPTIONS_H
#include "options.h"
#endif

#ifndef LIGHTOPC_H
#include "lightopc.h"
#endif
#ifndef LOSERV_H
#include "loserv.h"
#endif
#ifndef REQQUEUE_H
#include "reqqueue.h"
#endif
#ifndef UTIL_H
#include "util.h"
#endif
#ifndef GROWLIST_H
#include "growlist.h"
#endif
#ifndef OBJTRACK_H
#include "objtrack.h"
#endif

#ifdef __cplusplus
extern "C" {
#endif

/**************************************************************************/
#ifdef __cplusplus
	}
//#endif see at the EOF
#include "connpnt.h"

class LightOPCServer;
class LightOPCGroup;
class LightOPCItem;

/*#define LightOPCServer loClient
 It's right: server will be created on each client connection.
   Thus, from driver point of view LightOPCServer is assotiated with a client */

#define CLINAME_FMT   "%.16s "
#define LOG_SR(fmt)   LOGID, CLINAME_FMT fmt, client_name
#define LOG_GR(fmt)   LOGID, CLINAME_FMT fmt, owner->client_name
#define LOG_GRO(fmt)  LOGID, CLINAME_FMT fmt, (iam_attached()? owner->client_name: "?")
#define LOG_GRH(fmt)  LOGID, CLINAME_FMT "%u:" fmt, owner->client_name, ServerHandle
#define LOG_GRHO(fmt) LOGID, CLINAME_FMT "%u:" fmt, (iam_attached()? owner->client_name: "?"), ServerHandle

#define LOG_SR1(fmt,first)   LOGID, CLINAME_FMT fmt, first, client_name
#define LOG_GR1(fmt,first)   LOGID, CLINAME_FMT fmt, first, owner->client_name

#if LO_USE_OBJXREF
struct loObjXref
  {
inline  loObjXref() { InterlockedIncrement(&lo_X_objcount); }
inline ~loObjXref() { InterlockedDecrement(&lo_X_objcount); }
  };
#define LO_OBJ_XREF  loObjXref xxx_ref
#else
#define LO_OBJ_XREF
#endif

#define loUNIQUE_LEN (32)

#define LO_CHECK_STATE_(string) if (lock_state(string)) return LO_E_SHUTDOWN; else {

#define LO_CHECK_STATEz0(string) LO_CHECK_STATE_(string)
#define LO_CHECK_STATEz1(string,a1)          if (a1) *(a1) = 0; LO_CHECK_STATEz0(string)
#define LO_CHECK_STATEz2(string,a1,a2)       if (a2) *(a2) = 0; LO_CHECK_STATEz1(string,a1)
#define LO_CHECK_STATEz3(string,a1,a2,a3)    if (a3) *(a3) = 0; LO_CHECK_STATEz2(string,a1,a2)
#define LO_CHECK_STATEz4(string,a1,a2,a3,a4) if (a4) *(a4) = 0; LO_CHECK_STATEz3(string,a1,a2,a3)

#define LO_FINISH()  unlock_state(); }

typedef struct
  {
   IOPCShutdown *request;
   loWchar      *reason;
  } loShutdownConn;

void loShutdownConn_init(loShutdownConn *);

void loShutdownConn_clear(loShutdownConn *);
void loShutdownConn_call(loShutdownConn *);

#define loShutdownConn_init(p) (memset((p), 0, sizeof(loShutdownConn)))

class LightOPCServer : public IOPCServer,
                       public IOPCCommon,
                       public IOPCBrowseServerAddressSpace,
                       public IOPCItemProperties,
                       public loConnPnt1 /*public IConnectionPointContainer,*/
{
     LO_OBJ_XREF;
public:
     unsigned long initphase;
     glGrowingList grl;
     loService *se;
     LightOPCServer *serv_next;
     loCallerx ctxt;

     unsigned serv_key;
     int ldFlags;
     short access_mode;
     HRESULT (*qi_chain)(void *rha, loService *, loClient *,
                         const IID *, LPVOID *);

     loThrControl async; /* On signaling the tasync.state should be = 1
                            2 forces client_scheduler() to call selfdestroy() */
inline void touch_scheduler(void)
            {
             if (0 == async.tstate)
               {
                lw_mutex_lock(&async.lk);
                if (0 == async.tstate) async.tstate = 1;
                lw_conds_signal(&async.cond);
                lw_mutex_unlock(&async.lk);
               }
            }
/* This additional flag is requered for proper hanling of late events
   which has occured in the middle of client_scheduler() loop.
   Such signals will cause zero-time sleep and will be handled on the
   next iteration. */
#if LO_USE_BOTHMODEL
     char ole_initialized;
#endif
     int  shuttingdown; /* locked by async.lk */
     loObjTracker otrk;   /* & otrk.ot_stopped - flags for lock_state() */
     loQueueAsync q_req;
     loQueueBcast q_ret;

     loShutdownConn shutdown_conn; /* locked by async.lk */

     HRESULT  sync_advise(int operation, void **arg, loRqid grp_key);
     HRESULT async_advise(int conn, const IID *iface,
                          LightOPCGroup *grp, unsigned grp_key,
                          IUnknown *pUnk);
inline HRESULT async_unadvise(int conn, const IID *iface,
                              LightOPCGroup *grp, unsigned grp_key)
        { return async_advise(conn, iface, grp, grp_key, 0); }

     /* [un]lock_state() must NOT be virtual ! */
     int lock_state(const char *msg, const IID *riid_nostrict = 0);
                 /* returns 0 if Ok or -1 if out of service */
inline ULONG unlock_state(void)
  { UL_DEBUG((LOG_SR("unlock_state() -> finished: va=%d st=%d sd=%d rc=%d"),      
      loIS_VALID(this), otrk.ot_stopped, shuttingdown, RefCount));
    return Release();}

     void set_state(int oper, int state, const loWchar *reason);
     void client_scheduler(void);

     lw_rwlock lk_remove;
     lw_rwlock lk_all;
#if LO_USE_BOTHMODEL
     int (*lml_rd_lock)(lw_rwlock *lk, DWORD timeout);
     int (*lml_wr_lock)(lw_rwlock *lk, DWORD timeout);
     inline void lock_read(void)   { lml_rd_lock(&lk_all, INFINITE); }
     inline void lock_write(void)  { lml_wr_lock(&lk_all, INFINITE); }
     inline int RD_lock(lw_rwlock *rw)  { return lml_rd_lock(rw, INFINITE); }
     inline int WR_lock(lw_rwlock *rw)  { return lml_wr_lock(rw, INFINITE); }
#else
     inline int RD_lock(lw_rwlock *rw)  { return lw_rw_rdlock(rw); }
     inline int WR_lock(lw_rwlock *rw)  { return lw_rw_wrlock(rw); }
     inline void lock_read(void)
         {
//          UL_DEBUG((LOGID, "RdLock..."));
          lw_rw_rdlock(&lk_all);
  //      UL_DEBUG((LOGID, "...RdLock"));
         }
     inline void lock_write(void)
         {
    //      UL_DEBUG((LOGID, "WrLock..."));
          lw_rw_wrlock(&lk_all);
      //  UL_DEBUG((LOGID, "...WrLock"));
         }
#endif
     inline void unlock(void)
         {
        //  UL_DEBUG((LOGID, "UnLock..."));
          lw_rw_unlock(&lk_all);
          //UL_DEBUG((LOGID, "...UnLock"));
         }

     loStringBuf browsepos;
     lw_mutex    lk_browse;
inline void lock_browse(void)   { lw_mutex_lock(&lk_browse); }
inline void unlock_browse(void) { lw_mutex_unlock(&lk_browse); }

HRESULT set_browsepos(const loWchar *pos, int len = -1);
    int cat_browsepos(const loWchar *cpos);

     void (*release_handle)(void *, loService *, loClient *);
     void  *release_handle_arg;

     OPCSERVERSTATUS ostatus;
     loMilliSec bandwidth_time;

     unsigned long unique_GroupName;
     OPCHANDLE unique_GroupHandle;
     HRESULT mk_unique(loWchar buf[loUNIQUE_LEN], const void *ptr);

     LightOPCServer();
virtual ~LightOPCServer();
     int initialize(loService *serv, int ld_flags, const loVendorInfo *vi);
     void selfdestroy(void);

     int attach(void); /* set the owner */
     int detach(void); /* should set ready = 0 and do some cleanup */

     void clear_all(void);
     LightOPCGroup *by_name(const loWchar *name);
     unsigned by_handle(OPCHANDLE sgh);
     LightOPCGroup *by_handle_g(unsigned sgh);
     void del_all(int force = 0);
	/* returns -1 on errors or ==0/!=0 depend on item's Release() */
     int del(unsigned index, int force = 0);
     unsigned add(LightOPCGroup *grp);

/* IUnknown implementation */
     LONG RefCount;
     STDMETHOD_ (ULONG, AddRef)(void);
     STDMETHOD_ (ULONG, Release)(void);
     STDMETHOD (QueryInterface) (REFIID riid, void **ppv);

/* IOPCCommon implementation */
     char client_name[64]; /* no pointers - no locks */

	 STDMETHOD (SetLocaleID) (LCID dwLcid);
	 STDMETHOD (GetLocaleID) (LCID *dwLcid);
	 STDMETHOD (QueryAvailableLocaleIDs) (DWORD* pdwCount, LCID** pdwLcid);
     STDMETHOD (GetErrorString)(LONG dwError, LPWSTR *ppString);
	 STDMETHOD (SetClientName) (LPCWSTR szClientName);

⌨️ 快捷键说明

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