-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathticker.cpp
97 lines (88 loc) · 2.2 KB
/
ticker.cpp
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
#include "ticker.h"
#include <stdio.h>
#include <assert.h>
#ifdef __cplusplus
extern "C" {
#endif
_CRTIMP void __cdecl _wassert(__in_z const wchar_t * _Message, __in_z const wchar_t *_File, __in unsigned _Line);
#ifdef __cplusplus
}
#endif
#define release_assert(_Expression) (void)( (!!(_Expression)) || (_wassert(_CRT_WIDE(#_Expression), _CRT_WIDE(__FILE__), __LINE__), 0) )
#ifndef TICKER_OTPT_MT
static DWORD g_ticker_tlsidx = TLS_OUT_OF_INDEXES;
#endif
typedef struct {
} stop_indicate_exception_t;
ticker::ticker(void)
{
#ifdef TICKER_OTPT_MT
g_ticker_tlsidx = TLS_OUT_OF_INDEXES;
#endif
if (g_ticker_tlsidx == TLS_OUT_OF_INDEXES) {
g_ticker_tlsidx = TlsAlloc();
TlsSetValue(g_ticker_tlsidx, LPVOID(this));
}
m_status = NULL_STATUS;
}
ticker::~ticker(void)
{
release_assert(m_status == NULL_STATUS && "ticker not properly stoped");
if (g_ticker_tlsidx != TLS_OUT_OF_INDEXES) {
ticker* root = (ticker*)(TlsGetValue(g_ticker_tlsidx));
if (root == this) {
BOOL ret = TlsFree(g_ticker_tlsidx);
g_ticker_tlsidx = TLS_OUT_OF_INDEXES;
}
}
}
VOID CALLBACK ticker::_perform_proc( PVOID lpParameter )
{
ticker *self = static_cast<ticker*>(lpParameter);
assert(self && "ticker point invalid");
try {
self->perform();
} catch (stop_indicate_exception_t& e) {
e;
}
self->m_status = ticker::CLEANUP_STATUS;
SwitchToFiber(self->m_scheduler_fiber);
}
bool ticker::tick(bool stop)
{
if (stop) {
if (m_status == ticker::NULL_STATUS) return true;
m_status = ticker::CLEANUP_STATUS;
SwitchToFiber(m_performer_fiber);
}
bool finished = false;
switch (m_status) {
case NULL_STATUS:
if (TlsGetValue(g_ticker_tlsidx) == this) {
ConvertThreadToFiber(NULL);
}
m_scheduler_fiber = GetCurrentFiber();
m_performer_fiber = CreateFiber(0, ticker::_perform_proc, this);
m_status = WORKING_STATUS;
break;
case WORKING_STATUS:
SwitchToFiber(m_performer_fiber);
break;
case CLEANUP_STATUS:
cleanup();
DeleteFiber(m_performer_fiber);
m_status = NULL_STATUS;
finished = true;
break;
default:
break;
}
return finished;
};
void ticker::yield()
{
SwitchToFiber(m_scheduler_fiber);
if (m_status == CLEANUP_STATUS) {
throw stop_indicate_exception_t();
}
}