idle: Add an idle queue
The idle queue is used to schedule tasks ... later. This code was mostly adoted from a reference TDD experiment by Josh Larson (themutatedshrimp@gmail.com). Thanks Josh! Signed-off-by: Anna Schumaker <schumaker.anna@gmail.com>
This commit is contained in:
parent
5f30a71c55
commit
f417b48df8
3
config
3
config
|
@ -28,6 +28,7 @@ class Config:
|
|||
self.FILE = False
|
||||
self.FILTER = False
|
||||
self.GROUP = False
|
||||
self.IDLE = False
|
||||
self.INDEX = False
|
||||
self.TEST = False
|
||||
|
||||
|
@ -40,6 +41,7 @@ class Config:
|
|||
if self.FILE: env.Append( CCFLAGS = [ "-DCONFIG_FILE" ])
|
||||
if self.FILTER: env.Append( CCFLAGS = [ "-DCONFIG_FILTER" ])
|
||||
if self.GROUP: env.Append( CCFLAGS = [ "-DCONFIG_GROUP" ])
|
||||
if self.IDLE: env.Append( CCFLAGS = [ "-DCONFIG_IDLE" ])
|
||||
if self.INDEX: env.Append( CCFLAGS = [ "-DCONFIG_INDEX" ])
|
||||
if self.TEST: env.Append( CCFLAGS = [ "-DCONFIG_TEST" ])
|
||||
|
||||
|
@ -48,6 +50,7 @@ class Config:
|
|||
self.FILE = False
|
||||
self.FILTER = False
|
||||
self.GROUP = False
|
||||
self.IDLE = False
|
||||
self.INDEX = False
|
||||
self.TEST = False
|
||||
self.reconfigure()
|
||||
|
|
|
@ -13,8 +13,17 @@ Idle queue: (lib/idle.cpp)
|
|||
tasks must inherit from the IdleBase class so that multiple templated
|
||||
IdleTask pointers can be placed on the same idle queue.
|
||||
|
||||
Creating an idle queue in idle.hpp will create a new queue for every
|
||||
file that idle.h is included in. I want to have a single, shared
|
||||
idle queue used by the entire application so to get around this the
|
||||
IdleBase class is used and implemented in lib/idle.cpp.
|
||||
|
||||
- IdleBase:
|
||||
class IdleBase {
|
||||
private:
|
||||
schedule();
|
||||
|
||||
public:
|
||||
IdleBase();
|
||||
~IdleBase();
|
||||
virtual void run() = 0;
|
||||
|
@ -24,30 +33,34 @@ Idle queue: (lib/idle.cpp)
|
|||
template <class T>
|
||||
class IdleTask : IdleBase {
|
||||
private:
|
||||
void (*func)(T *);
|
||||
T *data;
|
||||
void (*func)(T &);
|
||||
T &data;
|
||||
|
||||
public:
|
||||
IdleTask(void (*)(T *), T *);
|
||||
IdleTask(void (*)(T &), T);
|
||||
void run();
|
||||
};
|
||||
|
||||
- Queue:
|
||||
deque(IdleBase *> idle_queue;
|
||||
queue<IdleBase *> idle_queue;
|
||||
float queued = 0.0
|
||||
float serviced = 0.0
|
||||
|
||||
- API:
|
||||
void IdleBase :: schedule();
|
||||
Add the idle task to the idle queue. This should be called
|
||||
by the IdleTask constructor.
|
||||
queued++;
|
||||
|
||||
template <class T>
|
||||
void idle :: schedule(void (*)(T *), T *);
|
||||
Schedule a function to run later (queued++). This should
|
||||
be written in the idle.hpp file since it is a function
|
||||
template.
|
||||
static inline void idle :: schedule(void (*)(T &), T);
|
||||
Create a new IdleTask to run the function later.
|
||||
|
||||
bool idle :: run_task()
|
||||
If there are tasks on the queue:
|
||||
run the next task
|
||||
scheduled++
|
||||
If there are still tasks on the queue:
|
||||
return true
|
||||
else:
|
||||
queued = 0
|
||||
|
@ -56,4 +69,5 @@ Idle queue: (lib/idle.cpp)
|
|||
|
||||
float idle :: get_progress()
|
||||
Return (serviced / queued) to the caller. If there are no
|
||||
tasks, return 1.0 to indicate that the queue is finished.
|
||||
tasks, return 1.0 to indicate that the queue is finished (and
|
||||
to avoid a divide-by-zero error).
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright 2013 (c) Anna Schumaker.
|
||||
*/
|
||||
#ifndef OCARINA_IDLE_H
|
||||
#define OCARINA_IDLE_H
|
||||
|
||||
namespace idle
|
||||
{
|
||||
|
||||
class IdleBase {
|
||||
protected:
|
||||
void schedule();
|
||||
public:
|
||||
IdleBase();
|
||||
virtual ~IdleBase();
|
||||
virtual void run() = 0;
|
||||
};
|
||||
|
||||
|
||||
template <class T>
|
||||
class IdleTask : public IdleBase {
|
||||
private:
|
||||
void (*func)(T &);
|
||||
T data;
|
||||
public:
|
||||
IdleTask(void (*)(T &), T);
|
||||
~IdleTask();
|
||||
void run();
|
||||
};
|
||||
|
||||
|
||||
template <class T>
|
||||
static inline void schedule(void (*func)(T &), T param)
|
||||
{
|
||||
new IdleTask<T>(func, param);
|
||||
}
|
||||
|
||||
bool run_task();
|
||||
float get_progress();
|
||||
|
||||
};
|
||||
|
||||
#include "idle.hpp"
|
||||
|
||||
#endif /* OCARINA_IDLE_H */
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright 2013 (c) Anna Schumaker.
|
||||
*
|
||||
* DO NOT INCLUDE THIS FILE DIRECTLY. THIS IS A TEMPLATE DEFINITION FILE
|
||||
* AND ONLY MEANT TO BE INCLUDED BY include/idle.h!
|
||||
*/
|
||||
#ifndef OCARINA_IDLE_HPP
|
||||
#define OCARINA_IDLE_HPP
|
||||
|
||||
template <class T>
|
||||
idle :: IdleTask<T> :: IdleTask(void (*fn)(T &), T param)
|
||||
: func(fn), data(param)
|
||||
{
|
||||
IdleBase :: schedule();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
idle :: IdleTask<T> :: ~IdleTask()
|
||||
{
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void idle :: IdleTask<T> :: run()
|
||||
{
|
||||
func(data);
|
||||
}
|
||||
|
||||
#endif /* OCARINA_IDLE_HPP */
|
|
@ -27,6 +27,10 @@ if CONFIG.FILE:
|
|||
CONFIG.package("glib-2.0")
|
||||
build += [ env.Object("file.cpp") ]
|
||||
|
||||
if CONFIG.IDLE:
|
||||
build += [ env.Object("idle.cpp") ]
|
||||
|
||||
####################
|
||||
|
||||
if CONFIG.TEST:
|
||||
build += [ env.Object("test.cpp") ]
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright 2013 (c) Anna Schumaker.
|
||||
*/
|
||||
#include <idle.h>
|
||||
|
||||
#include <queue>
|
||||
|
||||
static std::queue<idle :: IdleBase *> idle_queue;
|
||||
static float queued = 0;
|
||||
static float serviced = 0;
|
||||
|
||||
idle :: IdleBase :: IdleBase()
|
||||
{
|
||||
}
|
||||
|
||||
idle :: IdleBase :: ~IdleBase()
|
||||
{
|
||||
}
|
||||
|
||||
void idle :: IdleBase :: schedule()
|
||||
{
|
||||
idle_queue.push(this);
|
||||
queued++;
|
||||
}
|
||||
|
||||
|
||||
bool idle :: run_task()
|
||||
{
|
||||
if (idle_queue.size() > 0) {
|
||||
idle_queue.front()->run();
|
||||
delete idle_queue.front();
|
||||
idle_queue.pop();
|
||||
serviced++;
|
||||
}
|
||||
|
||||
if (idle_queue.size() > 0)
|
||||
return true;
|
||||
|
||||
queued = 0;
|
||||
serviced = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
float idle :: get_progress()
|
||||
{
|
||||
if (idle_queue.size() == 0)
|
||||
return 1;
|
||||
return serviced / queued;
|
||||
}
|
|
@ -43,7 +43,7 @@ Export("Test")
|
|||
|
||||
|
||||
# Read SConscript files
|
||||
scripts = [ "basic", "database", "file", "filter", "group", "index" ]
|
||||
scripts = [ "basic", "database", "file", "filter", "group", "idle", "index" ]
|
||||
for s in scripts:
|
||||
CONFIG.reset()
|
||||
CONFIG.TEST = True
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
#!/usr/bin/python
|
||||
Import("Test", "CONFIG")
|
||||
|
||||
CONFIG.IDLE = True
|
||||
|
||||
Test("idle", "idle.cpp")
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright 2013 (c) Anna Schumaker.
|
||||
*/
|
||||
#include <idle.h>
|
||||
#include <print.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
struct TestStruct {
|
||||
int i;
|
||||
unsigned int u;
|
||||
char c;
|
||||
std::string s;
|
||||
};
|
||||
|
||||
static void test_0(unsigned int &i)
|
||||
{
|
||||
print("Test 0: %u\n", i);
|
||||
}
|
||||
|
||||
static void test_1(int &i)
|
||||
{
|
||||
print("Test 1: %d\n", i);
|
||||
}
|
||||
|
||||
static void test_2(char &i)
|
||||
{
|
||||
print("Test 2: %c\n", i);
|
||||
}
|
||||
|
||||
static void test_3(std::string &str)
|
||||
{
|
||||
print("Test 3: %s\n", str.c_str());
|
||||
}
|
||||
|
||||
static void test_4(TestStruct &struc)
|
||||
{
|
||||
print("Test 4: %d %u %c %s\n", struc.i, struc.u, struc.c, struc.s.c_str());
|
||||
}
|
||||
|
||||
static void test_5(TestStruct *&struc)
|
||||
{
|
||||
print("Test 5: %d %u %c %s\n", struc->i, struc->u, struc->c, struc->s.c_str());
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
std::string string = "This is a string";
|
||||
TestStruct struc1 = { -4, 4, 'd', "This is another string", };
|
||||
TestStruct struc2 = { -5, 5, 'e', "This is yet another string", };
|
||||
|
||||
idle :: schedule(test_0, (unsigned int) 0);
|
||||
idle :: schedule(test_1, 1);
|
||||
idle :: schedule(test_2, 'b');
|
||||
idle :: schedule(test_3, string);
|
||||
idle :: schedule(test_4, struc1);
|
||||
idle :: schedule(test_5, &struc2);
|
||||
|
||||
do {
|
||||
print("Idle queue progress: %f\n", idle :: get_progress());
|
||||
} while (idle :: run_task() == true);
|
||||
print("Idle queue progress: %f\n", idle :: get_progress());
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
Idle queue progress: 0.000000
|
||||
Test 0: 0
|
||||
Idle queue progress: 0.166667
|
||||
Test 1: 1
|
||||
Idle queue progress: 0.333333
|
||||
Test 2: b
|
||||
Idle queue progress: 0.500000
|
||||
Test 3: This is a string
|
||||
Idle queue progress: 0.666667
|
||||
Test 4: -4 4 d This is another string
|
||||
Idle queue progress: 0.833333
|
||||
Test 5: -5 5 e This is yet another string
|
||||
Idle queue progress: 1.000000
|
Loading…
Reference in New Issue