Skip to content
This repository was archived by the owner on Aug 19, 2023. It is now read-only.

Commit b4956e1

Browse files
committed
Core classes and examples
1 parent 81fe517 commit b4956e1

File tree

12 files changed

+709
-0
lines changed

12 files changed

+709
-0
lines changed
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//
2+
// Nexus_OS.cpp
3+
//
4+
5+
//#include "Nexus_OS.h"
6+
7+
#include "Nexus_OS/Nexus_Task.cpp"
8+
9+
namespace Nexus {
10+
11+
class Scheduler Scheduler;
12+
13+
Event Message::None = Event(false);
14+
15+
}

Arduino/libraries/Nexus_OS/Nexus_OS.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//
2+
// Nexus.h
3+
//
4+
5+
#include <Arduino.h>
6+
7+
#include "Nexus_OS/Nexus_Symbol.h"
8+
#include "Nexus_OS/Nexus_Message.h"
9+
#include "Nexus_OS/Nexus_Task.h"
10+
#include "Nexus_OS/Nexus_Scheduler.h"
11+
#include "Nexus_OS/Nexus_Terminal.h"
12+
13+
namespace Nexus {
14+
15+
extern class Scheduler Scheduler;
16+
17+
}
18+
19+
/*
20+
21+
9 Bytes
22+
19 Bytes First 'new'
23+
24+
*/
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
//
2+
// Message.h
3+
//
4+
5+
namespace Nexus {
6+
7+
template<typename Type>
8+
struct TypeInfo {
9+
10+
static void *GetType() { return reinterpret_cast<void *>(&GetType); }
11+
12+
};
13+
14+
class Event {
15+
16+
public:
17+
18+
Event(bool valid = true) : _valid(valid) { }
19+
20+
operator bool() const
21+
{
22+
return _valid;
23+
}
24+
25+
bool _valid;
26+
27+
};
28+
29+
class Message {
30+
31+
public:
32+
33+
static Event None;
34+
35+
template<typename DataType>
36+
Message(const DataType& event) : _event(event), _type(TypeInfo<DataType>::GetType())
37+
{ }
38+
39+
template<typename DataType>
40+
const DataType& get() const
41+
{
42+
if (TypeInfo<DataType>::GetType() == _type)
43+
{
44+
return static_cast<const DataType&>(_event);
45+
}
46+
47+
return static_cast<const DataType&>(None);
48+
}
49+
50+
private:
51+
52+
const Event& _event;
53+
const void *_type;
54+
55+
};
56+
57+
}
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
//
2+
// Nexus_Scheduler.h
3+
//
4+
5+
#ifndef __Nexus_Scheduler__
6+
#define __Nexus_Scheduler__
7+
8+
namespace Nexus {
9+
10+
/**
11+
12+
Coordinates adding, removing and scheduling coros and tasks
13+
14+
*/
15+
16+
class Scheduler {
17+
18+
public:
19+
20+
void addCoro(Coro *coro)
21+
{
22+
coro->_next = _coros;
23+
24+
_coros = coro;
25+
}
26+
27+
void addTask(Task *task)
28+
{
29+
task->_next = _tasks;
30+
31+
_tasks = task;
32+
}
33+
34+
// void addTask(Task* newTask)
35+
// {
36+
// Task* task = _tasks;
37+
38+
// while (task == NULL)
39+
// {
40+
// task = task->getNext();
41+
// }
42+
43+
// if (task)
44+
// task->_next = newTask;
45+
// else
46+
// _tasks = newTask;
47+
// }
48+
49+
Task* getTasks() { return _tasks; }
50+
51+
void send(Task& task, const Message& message)
52+
{
53+
if (!task._sleep)
54+
{
55+
task._run(task, message);
56+
}
57+
}
58+
59+
void tick(uint32_t msecs)
60+
{
61+
for (Coro *prev = NULL, *coro = _coros; coro != NULL; coro = coro->getNext())
62+
{
63+
coro->_run(*coro, Message(Event()));
64+
}
65+
66+
for (Task *prev = NULL, *task = _tasks; task != NULL; task = task->getNext())
67+
{
68+
if (msecs >= task->_timeout)
69+
{
70+
//TimeoutEvent event;
71+
72+
//task->run(Message(event));
73+
//send(*task, Message());
74+
task->_run(*task, Message(Event()));
75+
}
76+
77+
if (task->_context == NULL)
78+
{
79+
if (prev)
80+
prev->_next = task->_next;
81+
else
82+
_tasks = (Task *)task->_next;
83+
84+
task = prev;
85+
}
86+
else prev = task;
87+
}
88+
}
89+
90+
private:
91+
92+
Coro *_coros;
93+
Task *_tasks;
94+
95+
};
96+
97+
}
98+
99+
#endif
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
//
2+
// Symbol
3+
//
4+
5+
#ifndef __Nexus_Symbol__
6+
#define __Nexus_Symbol__
7+
8+
namespace Nexus {
9+
10+
/**
11+
12+
Make Flash strings easier to work with and promote their use
13+
14+
*/
15+
16+
class symbol {
17+
18+
public:
19+
20+
symbol(const __FlashStringHelper *string) :
21+
_string(reinterpret_cast<const char *>(string))
22+
{ }
23+
24+
private:
25+
26+
const char *_string;
27+
28+
};
29+
30+
}
31+
32+
#endif
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
//
2+
// Nexus_Task.cpp
3+
//
4+
5+
#include "../Nexus_OS.h"
6+
7+
namespace Nexus {
8+
9+
void Task::send(const Message& message)
10+
{
11+
Scheduler.send(*this, message);
12+
}
13+
14+
}
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
//
2+
// Nexus_Task.h
3+
//
4+
5+
#ifndef __Nexus_Task__
6+
#define __Nexus_Task__
7+
8+
#include <Arduino.h>
9+
#include <limits.h>
10+
11+
#define MERGE_LINE(line) label_##line
12+
#define LABEL_LINE(line) MERGE_LINE(line)
13+
14+
#define coro_enter if (_context) goto *_context;
15+
#define coro_yield() _context = &&LABEL_LINE(__LINE__); return; LABEL_LINE(__LINE__):
16+
#define coro_exit _context = NULL; return;
17+
18+
#define task_enter coro_enter
19+
#define task_sleep(msecs) _timeout = millis() + msecs; _sleep = true; coro_yield()
20+
#define task_yield() _timeout = 0; _sleep = false; coro_yield()
21+
#define task_wait() _timeout = LONG_MAX; _sleep = false; coro_yield()
22+
#define task_wait4(msecs) _timeout = millis() + msecs; _sleep = false; coro_yield()
23+
#define task_exit coro_exit
24+
25+
namespace Nexus {
26+
27+
/**
28+
29+
Used by the scheduler to provide cooperative multi-threading
30+
31+
*/
32+
33+
class Coro {
34+
35+
public:
36+
37+
friend class Scheduler;
38+
39+
typedef void (*TickFunc)(Coro& coro, const Message& message);
40+
41+
Coro(TickFunc run) : _run(run), _context(NULL), _next(NULL) { }
42+
43+
Coro* getNext() { return _next; }
44+
45+
protected:
46+
47+
TickFunc _run;
48+
49+
void *_context;
50+
Coro *_next;
51+
52+
};
53+
54+
/**
55+
56+
Helper class to avoid virtual function vtable memory overhead
57+
58+
*/
59+
60+
template<typename T>
61+
struct TaskHelper {
62+
63+
static void run(Coro& task, const Message& message)
64+
{
65+
static_cast<T *>(&task)->run(message);
66+
}
67+
68+
};
69+
70+
/**
71+
72+
A named coro that supports sleeping for a set amount of time
73+
74+
*/
75+
76+
class Task : public Coro {
77+
78+
public:
79+
80+
friend class Scheduler;
81+
82+
Task(TickFunc run, symbol name) : Coro(run),
83+
_name(name), _timeout(0), _sleep(false)
84+
{ }
85+
86+
void send(const Message& message);
87+
88+
Task* getNext() { return static_cast<Task*>(Coro::getNext()); }
89+
90+
protected:
91+
92+
const symbol _name;
93+
uint32_t _timeout : 31;
94+
bool _sleep : 1;
95+
96+
};
97+
98+
}
99+
100+
#endif

0 commit comments

Comments
 (0)