Initial community commit
This commit is contained in:
parent
537bcbc862
commit
fc06254474
16440 changed files with 4239995 additions and 2 deletions
47
Src/Wasabi/api/timer/api_timer.h
Normal file
47
Src/Wasabi/api/timer/api_timer.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
#ifndef __TIMER_API_H
|
||||
#define __TIMER_API_H
|
||||
|
||||
// Under linux, the Timer API requires the Linux API
|
||||
|
||||
#include <bfc/dispatch.h>
|
||||
#include <bfc/platform/platform.h>
|
||||
|
||||
class TimerClient;
|
||||
|
||||
#ifdef _WIN32
|
||||
typedef UINT_PTR TimerToken ;
|
||||
#elif defined(__APPLE__)
|
||||
typedef EventLoopTimerRef TimerToken;
|
||||
#else
|
||||
#error port me!
|
||||
#endif
|
||||
|
||||
class timer_api : public Dispatchable
|
||||
{
|
||||
public:
|
||||
TimerToken timer_add(TimerClient *client, intptr_t id, int ms);
|
||||
void timer_remove(TimerClient *client, TimerToken token);
|
||||
|
||||
enum {
|
||||
TIMER_API_ADD = 1,
|
||||
TIMER_API_REMOVE = 11,
|
||||
};
|
||||
};
|
||||
|
||||
inline TimerToken timer_api::timer_add(TimerClient *client, intptr_t id, int ms)
|
||||
{
|
||||
return _call(TIMER_API_ADD, (TimerToken)0, client, id, ms);
|
||||
}
|
||||
|
||||
inline void timer_api::timer_remove(TimerClient *client, TimerToken token)
|
||||
{
|
||||
_voidcall(TIMER_API_REMOVE, client, token);
|
||||
}
|
||||
|
||||
// {3130D81C-AE1F-4954-9765-698473B627B0}
|
||||
static const GUID timerApiServiceGuid =
|
||||
{ 0x3130d81c, 0xae1f, 0x4954, { 0x97, 0x65, 0x69, 0x84, 0x73, 0xb6, 0x27, 0xb0 } };
|
||||
|
||||
extern timer_api *timerApi;
|
||||
|
||||
#endif
|
38
Src/Wasabi/api/timer/osx_timer.cpp
Normal file
38
Src/Wasabi/api/timer/osx_timer.cpp
Normal file
|
@ -0,0 +1,38 @@
|
|||
#include "osx_timer.h"
|
||||
#include <api/timer/timerclient.h>
|
||||
|
||||
timer_api *timerApi = NULL;
|
||||
|
||||
|
||||
TimerApi::TimerApi()
|
||||
{
|
||||
mainEventLoop = GetMainEventLoop();
|
||||
}
|
||||
|
||||
static void WasabiTimerProc(EventLoopTimerRef inTimer, void * inUserData)
|
||||
{
|
||||
TimerClient *client = (TimerClient *)inUserData;
|
||||
if (client)
|
||||
client->timerclient_timerCallback(inTimer);
|
||||
}
|
||||
|
||||
|
||||
TimerToken TimerApi::timer_add(TimerClient *client, int id, int ms)
|
||||
{
|
||||
EventLoopTimerRef token;
|
||||
OSStatus err = InstallEventLoopTimer(mainEventLoop,
|
||||
(float)ms/1000.0f,
|
||||
(float)ms/1000.0f,
|
||||
WasabiTimerProc,
|
||||
client,
|
||||
&token);
|
||||
if (err == noErr)
|
||||
return token;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void TimerApi::timer_remove(TimerClient *client, TimerToken token)
|
||||
{
|
||||
RemoveEventLoopTimer(token);
|
||||
}
|
17
Src/Wasabi/api/timer/osx_timer.h
Normal file
17
Src/Wasabi/api/timer/osx_timer.h
Normal file
|
@ -0,0 +1,17 @@
|
|||
#ifndef NULLSOFT_WASABI_OSX_TIMER_H
|
||||
#define NULLSOFT_WASABI_OSX_TIMER_H
|
||||
|
||||
#include <api/timer/api_timer.h>
|
||||
|
||||
class TimerApi : public timer_apiI
|
||||
{
|
||||
public:
|
||||
TimerApi();
|
||||
TimerToken timer_add(TimerClient *client, int id, int ms);
|
||||
void timer_remove(TimerClient *client, TimerToken);
|
||||
private:
|
||||
EventLoopRef mainEventLoop;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
108
Src/Wasabi/api/timer/timerclient.cpp
Normal file
108
Src/Wasabi/api/timer/timerclient.cpp
Normal file
|
@ -0,0 +1,108 @@
|
|||
#include "api.h"
|
||||
#include <api/timer/api_timer.h>
|
||||
#include <api/timer/timerclient.h>
|
||||
|
||||
#define CBCLASS TimerClientI
|
||||
START_DISPATCH;
|
||||
// this one doesn't map directly so that we can catch deferredcb timers
|
||||
VCB(TIMERCLIENT_TIMERCALLBACK, timerclient_handleDeferredCallback);
|
||||
CB(TIMERCLIENT_GETMASTERCLIENT, timerclient_getMasterClient);
|
||||
VCB(TIMERCLIENT_ONMASTERMUX, timerclient_onMasterClientMultiplex);
|
||||
CB(TIMERCLIENT_GETDEPPTR, timerclient_getDependencyPtr);
|
||||
CB(TIMERCLIENT_GETSKIPPED, timerclient_getSkipped);
|
||||
VCB(TIMERCLIENT_SETSKIPPED, timerclient_setSkipped);
|
||||
VCB(TIMERCLIENT_POSTDEFERREDCB , timerclient_postDeferredCallback);
|
||||
CB(TIMERCLIENT_ONDEFERREDCB , timerclient_onDeferredCallback);
|
||||
CB(TIMERCLIENT_GETNAME, timerclient_getName);
|
||||
END_DISPATCH;
|
||||
|
||||
TimerClientI::TimerClientI()
|
||||
: skipped(0), timerdelay(0), disallowset(0)
|
||||
{ }
|
||||
|
||||
TimerClientI::~TimerClientI()
|
||||
{
|
||||
disallowset = 1;
|
||||
if (cbs.getNumItems() > 0)
|
||||
{
|
||||
TimerToken token;
|
||||
if (tokens.reverseGetItem(DEFERREDCB_TIMERID, &token)) // TODO: it would be nice to have a combo get/del, so we don't have to search twice
|
||||
{
|
||||
WASABI_API_TIMER->timer_remove(this, token);
|
||||
tokens.delItem(token);
|
||||
}
|
||||
}
|
||||
cbs.deleteAll();
|
||||
}
|
||||
|
||||
int TimerClientI::timerclient_setTimer(intptr_t id, int ms)
|
||||
{
|
||||
if (disallowset) return 0;
|
||||
ASSERTPR(id > 0, "A timer id cannot be <= 0");
|
||||
ASSERTPR(id != DEFERREDCB_TIMERID, "please chose another timer id");
|
||||
TimerToken token = WASABI_API_TIMER->timer_add(this, id, ms);
|
||||
tokens.addItem(token, id);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int TimerClientI::timerclient_killTimer(intptr_t id)
|
||||
{
|
||||
TimerToken token;
|
||||
if (tokens.reverseGetItem(id, &token)) // TODO: it would be nice to have a combo get/del, so we don't have to search twice
|
||||
{
|
||||
WASABI_API_TIMER->timer_remove(this, token);
|
||||
tokens.delItem(token);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void TimerClientI::timerclient_postDeferredCallback(intptr_t param1, intptr_t param2, int mindelay)
|
||||
{
|
||||
if (disallowset) return ;
|
||||
for (int i = 0;i < cbs.getNumItems();i++)
|
||||
{
|
||||
deferred_callback *cb = cbs.enumItem(i);
|
||||
if (cb->param1 == param1 && cb->param2 == param2)
|
||||
{
|
||||
cbs.removeByPos(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
deferred_callback *c = new deferred_callback;
|
||||
c->origin = this;
|
||||
c->param1 = param1;
|
||||
c->param2 = param2;
|
||||
cbs.addItem(c);
|
||||
TimerToken token = WASABI_API_TIMER->timer_add(this, DEFERREDCB_TIMERID, MAX(1, mindelay));
|
||||
tokens.addItem(token, DEFERREDCB_TIMERID);
|
||||
}
|
||||
|
||||
void TimerClientI::timerclient_handleDeferredCallback(TimerToken token)
|
||||
{
|
||||
// let deriving class handle it. note we call into here even if
|
||||
// it's the deferred cb id, since older versions did that too,
|
||||
// expecting the user to call down on the method.
|
||||
|
||||
#ifdef WIN64
|
||||
LPARAM id;
|
||||
#else
|
||||
intptr_t id;
|
||||
#endif
|
||||
if (tokens.getItem(token, &id))
|
||||
{
|
||||
timerclient_timerCallback((int)id);
|
||||
|
||||
// process our deferred cb id
|
||||
if (id == DEFERREDCB_TIMERID)
|
||||
{
|
||||
WASABI_API_TIMER->timer_remove(this, token);
|
||||
PtrList<deferred_callback> temp(cbs);
|
||||
cbs.removeAll();
|
||||
foreach(temp)
|
||||
deferred_callback *c = temp.getfor();
|
||||
c->origin->timerclient_onDeferredCallback(c->param1, c->param2);
|
||||
delete c;
|
||||
endfor
|
||||
}
|
||||
}
|
||||
}
|
183
Src/Wasabi/api/timer/timerclient.h
Normal file
183
Src/Wasabi/api/timer/timerclient.h
Normal file
|
@ -0,0 +1,183 @@
|
|||
#ifndef __TIMER_CLIENT_H
|
||||
#define __TIMER_CLIENT_H
|
||||
|
||||
#include <bfc/dispatch.h>
|
||||
#include <bfc/common.h>
|
||||
#include <bfc/depend.h>
|
||||
#include <map>
|
||||
|
||||
#define DEFERREDCB_TIMERID -2
|
||||
|
||||
class TimerClient;
|
||||
|
||||
#ifdef _WIN32
|
||||
typedef UINT_PTR TimerToken ;
|
||||
#elif defined(__APPLE__)
|
||||
typedef EventLoopTimerRef TimerToken;
|
||||
#else
|
||||
#error port me!
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
TimerClient *origin;
|
||||
intptr_t param1;
|
||||
intptr_t param2;
|
||||
} deferred_callback;
|
||||
|
||||
class NOVTABLE TimerClient : public Dispatchable
|
||||
{
|
||||
protected:
|
||||
TimerClient() { }
|
||||
|
||||
public:
|
||||
int timerclient_setTimer(int id, int ms);
|
||||
int timerclient_killTimer(int id);
|
||||
void timerclient_postDeferredCallback(intptr_t param1, intptr_t param2=0, int mindelay=0);
|
||||
int timerclient_onDeferredCallback(intptr_t param1, intptr_t param2);
|
||||
void timerclient_timerCallback(TimerToken token);
|
||||
|
||||
TimerClient *timerclient_getMasterClient();
|
||||
void timerclient_onMasterClientMultiplex();
|
||||
api_dependent *timerclient_getDependencyPtr();
|
||||
void timerclient_setSkipped(int s);
|
||||
int timerclient_getSkipped();
|
||||
void timerclient_setTimerDelay(int td);
|
||||
int timerclient_getTimerDelay();
|
||||
const wchar_t *timerclient_getName();
|
||||
|
||||
enum {
|
||||
TIMERCLIENT_TIMERCALLBACK = 101,
|
||||
TIMERCLIENT_SETTIMER = 110,
|
||||
TIMERCLIENT_KILLTIMER = 120,
|
||||
TIMERCLIENT_GETMASTERCLIENT = 130,
|
||||
TIMERCLIENT_ONMASTERMUX = 140,
|
||||
TIMERCLIENT_GETDEPPTR = 150,
|
||||
TIMERCLIENT_SETSKIPPED = 160,
|
||||
TIMERCLIENT_GETSKIPPED = 170,
|
||||
TIMERCLIENT_SETTIMERDELAY = 180,
|
||||
TIMERCLIENT_GETTIMERDELAY = 190,
|
||||
TIMERCLIENT_POSTDEFERREDCB = 200,
|
||||
TIMERCLIENT_ONDEFERREDCB = 210,
|
||||
TIMERCLIENT_GETNAME = 220,
|
||||
};
|
||||
};
|
||||
|
||||
inline void TimerClient::timerclient_timerCallback(TimerToken token) {
|
||||
_voidcall(TIMERCLIENT_TIMERCALLBACK, token);
|
||||
}
|
||||
|
||||
inline int TimerClient::timerclient_setTimer(int id, int ms) {
|
||||
return _call(TIMERCLIENT_SETTIMER, 0, id, ms);
|
||||
}
|
||||
|
||||
inline int TimerClient::timerclient_killTimer(int id) {
|
||||
return _call(TIMERCLIENT_KILLTIMER, 0, id);
|
||||
}
|
||||
|
||||
inline TimerClient *TimerClient::timerclient_getMasterClient() {
|
||||
return _call(TIMERCLIENT_GETMASTERCLIENT, (TimerClient *)NULL);
|
||||
}
|
||||
|
||||
inline void TimerClient::timerclient_onMasterClientMultiplex() {
|
||||
_voidcall(TIMERCLIENT_ONMASTERMUX);
|
||||
}
|
||||
|
||||
inline api_dependent *TimerClient::timerclient_getDependencyPtr() {
|
||||
return _call(TIMERCLIENT_GETDEPPTR, (api_dependent *)NULL);
|
||||
}
|
||||
|
||||
inline void TimerClient::timerclient_setSkipped(int s) {
|
||||
_voidcall(TIMERCLIENT_SETSKIPPED, s);
|
||||
}
|
||||
|
||||
inline int TimerClient::timerclient_getSkipped() {
|
||||
return _call(TIMERCLIENT_GETSKIPPED, 0);
|
||||
}
|
||||
|
||||
inline void TimerClient::timerclient_setTimerDelay(int td) {
|
||||
_voidcall(TIMERCLIENT_SETTIMERDELAY, td);
|
||||
}
|
||||
|
||||
inline int TimerClient::timerclient_getTimerDelay() {
|
||||
return _call(TIMERCLIENT_GETTIMERDELAY, 0);
|
||||
}
|
||||
|
||||
inline void TimerClient::timerclient_postDeferredCallback(intptr_t param1, intptr_t param2, int mindelay) {
|
||||
_voidcall(TIMERCLIENT_POSTDEFERREDCB, param1, param2, mindelay);
|
||||
}
|
||||
|
||||
inline int TimerClient::timerclient_onDeferredCallback(intptr_t param1, intptr_t param2) {
|
||||
return _call(TIMERCLIENT_ONDEFERREDCB, 0, param1, param2);
|
||||
}
|
||||
|
||||
inline const wchar_t *TimerClient::timerclient_getName() {
|
||||
return _call(TIMERCLIENT_GETNAME, (const wchar_t *)NULL);
|
||||
}
|
||||
|
||||
class NOVTABLE TimerClientI : public TimerClient {
|
||||
protected:
|
||||
TimerClientI();
|
||||
|
||||
public:
|
||||
virtual ~TimerClientI();
|
||||
|
||||
virtual int timerclient_setTimer(intptr_t id, int ms);
|
||||
virtual int timerclient_killTimer(intptr_t id);
|
||||
|
||||
// override this to catch your timer events
|
||||
virtual void timerclient_timerCallback(int id) { }
|
||||
|
||||
virtual TimerClient *timerclient_getMasterClient() { return NULL; }
|
||||
virtual void timerclient_onMasterClientMultiplex() { };
|
||||
virtual api_dependent *timerclient_getDependencyPtr()=0;
|
||||
virtual void timerclient_setSkipped(int s) { skipped = s; }
|
||||
virtual int timerclient_getSkipped() { return skipped; }
|
||||
virtual void timerclient_setTimerDelay(int td) { timerdelay = td; }
|
||||
virtual int timerclient_getTimerDelay() { return timerdelay; }
|
||||
virtual void timerclient_postDeferredCallback(intptr_t param1, intptr_t param2=0, int mindelay=0);
|
||||
virtual int timerclient_onDeferredCallback(intptr_t param1, intptr_t param2) { return 1; };
|
||||
virtual const wchar_t *timerclient_getName() { return NULL; }
|
||||
|
||||
protected:
|
||||
RECVS_DISPATCH;
|
||||
|
||||
private:
|
||||
virtual void timerclient_handleDeferredCallback(TimerToken token);
|
||||
|
||||
int skipped;
|
||||
int timerdelay;
|
||||
int disallowset;
|
||||
PtrList<deferred_callback> cbs;
|
||||
#ifdef _WIN32
|
||||
class TokenMap
|
||||
{
|
||||
public:
|
||||
void delItem(TimerToken) {}
|
||||
bool reverseGetItem(intptr_t id, TimerToken *token)
|
||||
{
|
||||
*token = id;
|
||||
return true;
|
||||
}
|
||||
bool getItem(TimerToken token, intptr_t *id)
|
||||
{
|
||||
*id = token;
|
||||
return true;
|
||||
}
|
||||
void addItem(TimerToken, intptr_t) {}
|
||||
};
|
||||
#else
|
||||
typedef std::map<TimerToken, intptr_t> TokenMap;
|
||||
#endif
|
||||
TokenMap tokens;
|
||||
};
|
||||
|
||||
class NOVTABLE TimerClientDI : public TimerClientI, public DependentI {
|
||||
protected:
|
||||
TimerClientDI() { }
|
||||
|
||||
public:
|
||||
api_dependent *timerclient_getDependencyPtr() { return this; }
|
||||
};
|
||||
|
||||
|
||||
#endif
|
62
Src/Wasabi/api/timer/timeslicer.cpp
Normal file
62
Src/Wasabi/api/timer/timeslicer.cpp
Normal file
|
@ -0,0 +1,62 @@
|
|||
#include "precomp.h"
|
||||
#include "timeslicer.h"
|
||||
|
||||
#define TIMER_SLICE 0x7816
|
||||
|
||||
TimeSlicer::TimeSlicer(int percent_cpu_usage/* =50 */, int slice_duration/* =-1 */) {
|
||||
max_cpu_usage = MIN((float)percent_cpu_usage, 99.0f) / 100.0f;
|
||||
duration = slice_duration;
|
||||
started = 0;
|
||||
slicecount = 0;
|
||||
firstslicetime = -1;
|
||||
}
|
||||
|
||||
TimeSlicer::~TimeSlicer() {
|
||||
}
|
||||
|
||||
void TimeSlicer::startSlicer() {
|
||||
if (started) return;
|
||||
started = 1;
|
||||
timerclient_setTimer(TIMER_SLICE, duration);
|
||||
onSlicerStart();
|
||||
timerclient_timerCallback(TIMER_SLICE);
|
||||
}
|
||||
|
||||
void TimeSlicer::stopSlicer() {
|
||||
if (!started) return;
|
||||
started = 0;
|
||||
timerclient_killTimer(TIMER_SLICE);
|
||||
onSlicerStop();
|
||||
firstslicetime = -1;
|
||||
}
|
||||
|
||||
void TimeSlicer::onSlicerStop() {
|
||||
}
|
||||
|
||||
void TimeSlicer::onSlicerStart() {
|
||||
}
|
||||
|
||||
int TimeSlicer::isSlicerStarted() {
|
||||
return started;
|
||||
}
|
||||
|
||||
void TimeSlicer::timerclient_timerCallback(int id) {
|
||||
if (id == TIMER_SLICE) {
|
||||
DWORD now = Std::getTickCount();
|
||||
runSlice(now, now + (int)((float)duration * max_cpu_usage));
|
||||
} else
|
||||
TimerClient::timerclient_timerCallback(id);
|
||||
}
|
||||
|
||||
void TimeSlicer::runSlice(DWORD start, DWORD stopwhen) {
|
||||
DWORD now = Std::getTickCount();
|
||||
slicecount = 0;
|
||||
onBeginSliceBatch();
|
||||
if (slicecount == 0 && firstslicetime != -1) stopwhen = now + firstslicetime;
|
||||
while (Std::getTickCount() < stopwhen) {
|
||||
onSlice();
|
||||
slicecount++;
|
||||
if (!started) break; // got aborted
|
||||
}
|
||||
onEndSliceBatch();
|
||||
}
|
64
Src/Wasabi/api/timer/timeslicer.h
Normal file
64
Src/Wasabi/api/timer/timeslicer.h
Normal file
|
@ -0,0 +1,64 @@
|
|||
#ifndef __TIMESLICER_H
|
||||
#define __TIMESLICER_H
|
||||
|
||||
// TimeSlicer allows you to create a background job to perform while not blocking
|
||||
// the main GUI thread. You give it the max percentage of CPU it should use, call star()
|
||||
// and it'll start calling onSlice as many times as it can without using more cpu than requested
|
||||
//
|
||||
// To use this class, you need to break down your job into multiple tiny chunks that
|
||||
// you perform in onSlice. Typical uses include adding files to or filtering entries from
|
||||
// the database, driving state machines, etc.
|
||||
//
|
||||
// onSlice will be called multiple times per timer.
|
||||
|
||||
#include "timerclient.h"
|
||||
|
||||
enum {
|
||||
GRANULARITY_EXTRALOW = 20,
|
||||
GRANULARITY_LOW = 50,
|
||||
GRANULARITY_MEDIUM = 100,
|
||||
GRANULARITY_HIGH = 250,
|
||||
GRANULARITY_EXTRAHIGH = 1000,
|
||||
};
|
||||
|
||||
class TimeSlicer : public TimerClientI {
|
||||
public:
|
||||
|
||||
TimeSlicer(int percent_cpu_usage=25, int slice_duration=GRANULARITY_LOW);
|
||||
virtual ~TimeSlicer();
|
||||
|
||||
virtual void timerclient_timerCallback(int id);
|
||||
|
||||
void startSlicer();
|
||||
void stopSlicer();
|
||||
int isSlicerStarted();
|
||||
|
||||
virtual void onSlicerStart();
|
||||
virtual void onSlicerStop();
|
||||
virtual void onBeginSliceBatch() {}
|
||||
virtual void onEndSliceBatch() {}
|
||||
api_dependent *timerclient_getDependencyPtr() { return timeslicer_getDependencyPtr(); }
|
||||
virtual api_dependent *timeslicer_getDependencyPtr()=0;
|
||||
virtual void setFirstSliceMinTime(int ms) { firstslicetime = ms; }
|
||||
virtual int getSliceCount() { return slicecount; }
|
||||
|
||||
|
||||
// override this to do your work
|
||||
virtual void onSlice() { }
|
||||
|
||||
private:
|
||||
|
||||
virtual void runSlice(DWORD start, DWORD stopwhen);
|
||||
float max_cpu_usage;
|
||||
int duration;
|
||||
int started;
|
||||
int firstslicetime;
|
||||
int slicecount;
|
||||
};
|
||||
|
||||
class TimeSlicerD : public TimeSlicer, public DependentI {
|
||||
public:
|
||||
virtual api_dependent *timeslicer_getDependencyPtr() { return this; }
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Add table
Add a link
Reference in a new issue