aboutsummaryrefslogtreecommitdiff
path: root/Src/timer/timermul.h
blob: 67dcafb20b816ac7ac0661477fd57a773ae5a423 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#ifndef __TIMER_MULTIPLEXER_H
#define __TIMER_MULTIPLEXER_H

#include <bfc/common.h>
#include <bfc/ptrlist.h>
#include <api/dependency/api_dependentviewer.h>

// FG> not too sure how to get a callback for attribute change, if anyone wants to change it be my guest ;)
#define RESOLUTION_CHECK_DELAY 1000 // check for resolution changes every second

// if uioptions CfgItem not found, use this value for resolution
#define DEF_RES 20

// below MAX_TIMER_DELAY, timer are multiplexed using a 'wheel' algorithm (mem used = MAX_TIMER_DELAY/resolution * sizeof(PtrList) + ntimers*sizeof(MultiplexedTimer), but fast (no lookup) )
// above MAX_TIMER_DELAY, resolution drops to MAX_TIMER_DELAY/LOW_RES_DIV and uses ntimers*sizeof(MultiplexedTimer) bytes
#define MAX_TIMER_DELAY 1000  // keep this dividable by LOW_RES_DIV please
#define LOW_RES_DIV        4

class CfgItem;
class api_config;

class TimerMultiplexerClient {
  public:
    virtual void onMultiplexedTimer(void *data, int skip, int mssincelast)=0;
};

class MultiplexedTimer {
  public:
    MultiplexedTimer(int _ms, void *_data) : ms(_ms), data(_data) {
      nexttick=0;
      flag=0;
      lost = 0;
      lastmscount=0;
      lastdelay=0;
    }
    virtual ~MultiplexedTimer() { }

    int ms;
    void *data;
    DWORD nexttick; // only used by low precision timers
    int flag; // only used by hi precision timers
    float lost; // only used by hi precision timers
    DWORD lastmscount;
    int lastdelay;
};

class TimerMultiplexer : public ifc_dependentviewer
{
  public:

    TimerMultiplexer();
    virtual ~TimerMultiplexer();

    virtual void setClient(TimerMultiplexerClient *client);

    virtual void onServerTimer();

    virtual void addTimer(int ms, void *data);
    virtual void removeTimer(void *data);
    virtual void setResolution(int ms);

    virtual void shutdown();
    virtual int getNumTimers();
    virtual int getNumTimersLP();

  private:

    void checkResolution(DWORD now);
    void resetTimer(int newresolution);
    void resetWheel();
    void distributeAll();
    void distribute(MultiplexedTimer *t);
    void runCurSlice(DWORD now);
    void runTimer(DWORD now, DWORD last, MultiplexedTimer *t, PtrList<MultiplexedTimer> *slice, int pos);
    void removeFromWheel(MultiplexedTimer *t);
    void runLowPrecisionTimers(DWORD now);
    void removeFromLowPrecision(MultiplexedTimer *t);
    void doShutdown();
    PtrList<MultiplexedTimer> *getSlice(int n);

    TimerMultiplexerClient *client;
    int resolution;
    bool check_resolution;
    int timerset;

    int curslice;
    int nslices;
    int justexited;
    int firstevent;

    PtrList< PtrList< MultiplexedTimer > > wheel;
    PtrList< MultiplexedTimer > timers;
    PtrList< MultiplexedTimer > lptimers;
    MultiplexedTimer *running_timer;
		int dependentViewer_callback(ifc_dependent *item, const GUID *classguid, int cb, intptr_t param1 = 0, intptr_t param2 = 0, void *ptr = NULL, size_t ptrlen = 0);

  CfgItem *uioptions;
	RECVS_DISPATCH;
};

class MultiplexerServer {
public:
  MultiplexerServer(TimerMultiplexer *mux, UINT tid) : m_mux(mux), m_tid(tid) {}
  virtual ~MultiplexerServer() {}
  TimerMultiplexer *getMultiplexer() { return m_mux; }
  UINT_PTR getId() { return m_tid; }
  void setId(UINT_PTR id) { m_tid = id; }
private:
  TimerMultiplexer *m_mux;
  UINT_PTR m_tid;
};

class MultiplexerServerComparatorTID {
public:
  // comparator for sorting
  static int compareItem(MultiplexerServer *p1, MultiplexerServer* p2) {
    if (p1->getId() < p2->getId()) return -1;
    if (p1->getId() > p2->getId()) return 1;
    return 0;
  }
  // comparator for searching
  static int compareAttrib(const wchar_t *attrib, MultiplexerServer *item) {
    if (*((UINT *)attrib) < item->getId()) return -1;
    if (*((UINT *)attrib) < item->getId()) return 1;
    return 0;
  }
};

class MultiplexerServerComparatorMux{
public:
  // comparator for sorting
  static int compareItem(MultiplexerServer *p1, MultiplexerServer* p2) {
    if (p1->getMultiplexer() < p2->getMultiplexer()) return -1;
    if (p1->getMultiplexer() > p2->getMultiplexer()) return 1;
    return 0;
  }
  // comparator for searching
  static int compareAttrib(const wchar_t *attrib, MultiplexerServer *item) {
    if ((TimerMultiplexer *)attrib < item->getMultiplexer()) return -1;
    if ((TimerMultiplexer *)attrib < item->getMultiplexer()) return 1;
    return 0;
  }
};

#endif