Skip to content

Commit 08c0e94

Browse files
authored
Merge pull request #43 from stevenewald/callbacks
Improve callback abstraction
2 parents 53c4061 + c9bb025 commit 08c0e94

13 files changed

+85
-49
lines changed

include/drivers/button_driver.hpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "drivers/gpio_pin.hpp"
66
#include "drivers/gpio_pin_event.hpp"
77
#include "microbit_v2.h"
8+
#include "scheduler/user_callback_storage.hpp"
89

910
namespace edge::drivers {
1011
class ButtonController {
@@ -17,9 +18,8 @@ class ButtonController {
1718
GPIOPinEvent event_a;
1819
GPIOPinEvent event_b;
1920

20-
using SubscriptionArray = etl::array<ProcessCallbackPtr, MAX_PROCESSES>;
21-
SubscriptionArray a_subscriptions;
22-
SubscriptionArray b_subscriptions;
21+
UserCallbackStorage a_subscriptions;
22+
UserCallbackStorage b_subscriptions;
2323

2424
ButtonController();
2525
~ButtonController() = default;
@@ -35,7 +35,7 @@ class ButtonController {
3535
bool get_button_pressed(ButtonType button_type);
3636

3737
void subscribe_button_press(
38-
ButtonType type, ProcessCallbackPtr callback, uint8_t process_id
38+
ButtonType type, ProcessCallbackPtr callback, ProcessId process_id
3939
);
4040
};
4141
} // namespace edge::drivers

include/drivers/driver_commands.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ etl::optional<int> handle_command(DriverCommand type, int arg1, int arg2, int ar
1313

1414
void handle_subscribe(
1515
DriverSubscribe type, ProcessCallbackPtr callback, int arg1, int arg2,
16-
uint8_t process_id
16+
ProcessId process_id
1717
);
1818

1919
} // namespace edge::drivers

include/faults/fault_handler.hpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#pragma once
22

33
#include "config.hpp"
4+
#include "scheduler/user_callback_storage.hpp"
45
#include "util.hpp"
56

67
namespace edge {
@@ -9,7 +10,7 @@ class FaultHandler {
910
FaultHandler();
1011
~FaultHandler();
1112

12-
etl::array<etl::optional<ProcessCallbackPtr>, MAX_PROCESSES> error_callbacks;
13+
UserCallbackStorage error_callbacks;
1314

1415
public:
1516
FaultHandler(const FaultHandler&) = delete;
@@ -22,6 +23,6 @@ class FaultHandler {
2223
// To be called by raw handlers in raw_fault_handling.cpp
2324
void fault_triggered(FaultType fault_type, uint32_t* stack_ptr);
2425

25-
void set_fault_callback(uint8_t process_id, ProcessCallbackPtr callback_ptr);
26+
void set_fault_callback(ProcessId process_id, ProcessCallbackPtr callback_ptr);
2627
};
2728
} // namespace edge

include/ipc/ipc_manager.hpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
#pragma once
22

33
#include "config.hpp"
4+
#include "scheduler/user_callback_storage.hpp"
45
#include "util.hpp"
56

67
namespace edge {
78
class IPCManager {
89
etl::unordered_map<ProcessName, uint8_t, MAX_PROCESSES> name_to_id;
9-
etl::array<ProcessCallbackPtr, MAX_PROCESSES> ipc_communicators{nullptr};
10+
UserCallbackStorage ipc_communicators{};
1011

1112
IPCManager() = default;
1213
~IPCManager() = default;
@@ -19,7 +20,7 @@ class IPCManager {
1920
static IPCManager& get();
2021

2122
void register_callback(
22-
uint8_t process_id, const ProcessName& process_name, ProcessCallbackPtr callback
23+
ProcessId process_id, const ProcessName& process_name, ProcessCallbackPtr callback
2324
);
2425
void send_message(const ProcessName& destination_name, int value);
2526
};

include/scheduler/pending_process_callbacks.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,10 @@ class PendingProcessCallbacks {
2828
PendingProcessCallbacks& operator=(PendingProcessCallbacks&&) = delete;
2929

3030
void add_ready_callback(
31-
uint8_t process_id, ProcessCallbackPtr callback, int arg1 = 0, int arg2 = 0
31+
ProcessId process_id, ProcessCallbackPtr callback, int arg1 = 0, int arg2 = 0
3232
);
3333

34-
etl::optional<drivers::subscribe_callback> get_ready_callback(uint8_t process_id);
34+
etl::optional<drivers::subscribe_callback> get_ready_callback(ProcessId process_id);
3535

3636
static PendingProcessCallbacks& get();
3737
};
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#pragma once
2+
3+
#include "util.hpp"
4+
5+
namespace edge {
6+
7+
constexpr size_t MAX_CALLBACKS = 128;
8+
9+
class UserCallbackStorage {
10+
etl::unordered_map<ProcessId, ProcessCallbackPtr, MAX_CALLBACKS> callbacks_;
11+
12+
public:
13+
bool has_callback(ProcessId id);
14+
15+
void set_callback(ProcessId id, ProcessCallbackPtr ptr);
16+
17+
void call_callback(ProcessId id, int arg1 = 0, int arg2 = 0);
18+
};
19+
} // namespace edge

include/util.hpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,13 @@
55
namespace edge {
66
[[noreturn]] void panic(const char* reason);
77

8-
using ProcessCallbackPtr = void (*)(int, int);
8+
// Arg1 and arg2 are optional
9+
using ProcessCallbackPtr = void (*)(int arg1, int arg2);
10+
11+
using ProcessId = uint8_t;
12+
913
using ProcessName = etl::string<20>;
14+
1015
enum class FaultType { Usage, Bus, Memory };
1116

1217
struct exception_stack_registers {

src/drivers/button_driver.cpp

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#include "drivers/button_driver.hpp"
22

33
#include "drivers/driver_enums.hpp"
4-
#include "scheduler/pending_process_callbacks.hpp"
4+
#include "scheduler/user_callback_storage.hpp"
55

66
namespace edge::drivers {
77

@@ -25,14 +25,14 @@ ButtonController::ButtonController() :
2525
{}
2626

2727
void ButtonController::subscribe_button_press(
28-
ButtonType type, ProcessCallbackPtr callback, uint8_t process_id
28+
ButtonType type, ProcessCallbackPtr callback, ProcessId process_id
2929
)
3030
{
3131
if (type == ButtonType::A) {
32-
a_subscriptions[process_id] = callback;
32+
a_subscriptions.set_callback(process_id, callback);
3333
}
3434
else if (type == ButtonType::B) {
35-
b_subscriptions[process_id] = callback;
35+
b_subscriptions.set_callback(process_id, callback);
3636
}
3737
}
3838

@@ -48,13 +48,12 @@ bool ButtonController::get_button_pressed(ButtonType button_type)
4848

4949
void ButtonController::handle_button_press(ButtonType type, ButtonState state)
5050
{
51-
SubscriptionArray& button_subscriptions =
51+
UserCallbackStorage& button_subscriptions =
5252
type == ButtonType::A ? a_subscriptions : b_subscriptions;
5353
for (int process_id = 0; process_id < MAX_PROCESSES; process_id++) {
54-
if (button_subscriptions[process_id] != nullptr) {
55-
PendingProcessCallbacks::get().add_ready_callback(
56-
process_id, button_subscriptions[process_id], static_cast<int>(type),
57-
static_cast<int>(state)
54+
if (button_subscriptions.has_callback(process_id)) {
55+
button_subscriptions.call_callback(
56+
process_id, static_cast<int>(type), static_cast<int>(state)
5857
);
5958
}
6059
}

src/drivers/driver_commands.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ etl::optional<int> handle_command(DriverCommand type, int arg1, int arg2, int ar
3636

3737
void handle_subscribe(
3838
DriverSubscribe type, ProcessCallbackPtr callback, int arg1, int arg2,
39-
uint8_t process_id
39+
ProcessId process_id
4040
)
4141
{
4242
switch (type) {

src/faults/fault_handler.cpp

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
#include "faults/fault_handler.hpp"
22

33
#include "nrf52.h"
4-
#include "scheduler/pending_process_callbacks.hpp"
54
#include "scheduler/scheduler.hpp"
65

76
#include <stdio.h>
@@ -49,27 +48,18 @@ FaultHandler& FaultHandler::get()
4948
}
5049

5150
void FaultHandler::set_fault_callback(
52-
uint8_t process_id, ProcessCallbackPtr callback_ptr
51+
ProcessId process_id, ProcessCallbackPtr callback_ptr
5352
)
5453
{
55-
if (error_callbacks[process_id]) {
56-
printf("Process %d already set callback for fault handling\n", process_id);
57-
return;
58-
}
59-
error_callbacks[process_id] = callback_ptr;
54+
error_callbacks.set_callback(process_id, callback_ptr);
6055
}
6156

6257
void FaultHandler::fault_triggered(FaultType fault_type, uint32_t* stack_ptr)
6358
{
64-
uint8_t current_task = scheduler.get_current_task();
65-
if (!error_callbacks[current_task].has_value()) [[unlikely]] {
66-
panic("Error handler not set");
67-
}
68-
6959
stack_ptr[6] = increment_pc(stack_ptr[6]);
70-
PendingProcessCallbacks::get().add_ready_callback(
71-
current_task, error_callbacks[current_task].value(),
72-
static_cast<int>(fault_type)
60+
61+
error_callbacks.call_callback(
62+
scheduler.get_current_task(), static_cast<int>(fault_type)
7363
);
7464
}
7565
} // namespace edge

src/ipc/ipc_manager.cpp

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
#include "ipc/ipc_manager.hpp"
22

3-
#include "scheduler/pending_process_callbacks.hpp"
43
#include "util.hpp"
54

65
#include <stdio.h>
@@ -13,14 +12,10 @@ IPCManager& IPCManager::get()
1312
}
1413

1514
void IPCManager::register_callback(
16-
uint8_t process_id, const ProcessName& new_process_name, ProcessCallbackPtr callback
15+
ProcessId process_id, const ProcessName& new_process_name, ProcessCallbackPtr callback
1716
)
1817
{
19-
if (ipc_communicators[process_id] != nullptr) [[unlikely]] {
20-
panic("IPC registered twice for a process");
21-
}
22-
23-
ipc_communicators[process_id] = callback;
18+
ipc_communicators.set_callback(process_id, callback);
2419
name_to_id[new_process_name] = process_id;
2520
}
2621

@@ -32,8 +27,6 @@ void IPCManager::send_message(const ProcessName& destination_name, int value)
3227
}
3328

3429
auto process_id = name_to_id[destination_name];
35-
auto callback = ipc_communicators[process_id];
36-
PendingProcessCallbacks::get().add_ready_callback(process_id, callback, value);
37-
return;
30+
ipc_communicators.call_callback(process_id, value);
3831
}
3932
} // namespace edge

src/scheduler/pending_process_callbacks.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ PendingProcessCallbacks& PendingProcessCallbacks::get()
1111
}
1212

1313
void PendingProcessCallbacks::add_ready_callback(
14-
uint8_t process_id, ProcessCallbackPtr callback, int arg1, int arg2
14+
ProcessId process_id, ProcessCallbackPtr callback, int arg1, int arg2
1515
)
1616
{
1717
if (ready_callbacks[process_id].size() == MAX_READY_CALLBACKS) {
@@ -22,7 +22,7 @@ void PendingProcessCallbacks::add_ready_callback(
2222
}
2323

2424
etl::optional<drivers::subscribe_callback>
25-
PendingProcessCallbacks::get_ready_callback(uint8_t process_id)
25+
PendingProcessCallbacks::get_ready_callback(ProcessId process_id)
2626
{
2727
if (ready_callbacks[process_id].empty()) {
2828
return etl::nullopt;
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#include "scheduler/user_callback_storage.hpp"
2+
3+
#include "scheduler/pending_process_callbacks.hpp"
4+
5+
namespace edge {
6+
bool UserCallbackStorage::has_callback(ProcessId id)
7+
{
8+
return callbacks_.find(id) != callbacks_.end();
9+
}
10+
11+
void UserCallbackStorage::set_callback(ProcessId id, ProcessCallbackPtr ptr)
12+
{
13+
if (has_callback(id)) [[unlikely]] {
14+
panic("Attempted to set callback when callback already exists");
15+
}
16+
17+
callbacks_[id] = ptr;
18+
}
19+
20+
void UserCallbackStorage::call_callback(ProcessId id, int arg1, int arg2)
21+
{
22+
if (!has_callback(id)) {
23+
panic("Attempted to call callback when it has not been set");
24+
}
25+
26+
PendingProcessCallbacks::get().add_ready_callback(id, callbacks_[id], arg1, arg2);
27+
}
28+
} // namespace edge

0 commit comments

Comments
 (0)