Skip to content

Commit 5294ec8

Browse files
committed
pybricks.pupdevices.lwp3device: Use finalizers.
Finish an old todo about using finalizers to clean up observe data and lwp3 notification buffer.
1 parent acbbae9 commit 5294ec8

File tree

7 files changed

+38
-41
lines changed

7 files changed

+38
-41
lines changed

bricks/_common/micropython.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -423,9 +423,6 @@ void pbsys_main_run_program(pbsys_main_program_t *program) {
423423
}
424424

425425
void pbsys_main_run_program_cleanup(void) {
426-
427-
pb_package_pybricks_deinit();
428-
429426
gc_sweep_all();
430427
mp_deinit();
431428
}

bricks/virtualhub/mp_port.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,6 @@ void pb_virtualhub_port_init(void) {
8686

8787
// MICROPY_PORT_DEINIT_FUNC
8888
void pb_virtualhub_port_deinit(void) {
89-
90-
pb_package_pybricks_deinit();
9189
}
9290

9391
// Implementation for MICROPY_EVENT_POLL_HOOK

pybricks/common.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
#include <pybricks/common/pb_type_device.h>
2727

2828
void pb_package_pybricks_init(bool import_all);
29-
void pb_package_pybricks_deinit(void);
3029

3130
#if PYBRICKS_PY_COMMON_BLE
3231
mp_obj_t pb_type_BLE_new(mp_obj_t broadcast_channel_in, mp_obj_t observe_channels_in);

pybricks/common/pb_type_ble.c

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,11 @@ typedef enum {
9191
* is not allocated in the table.
9292
*/
9393
static observed_data_t *lookup_observed_data(uint8_t channel) {
94+
95+
if (!observed_data) {
96+
return NULL;
97+
}
98+
9499
for (size_t i = 0; i < num_observed_data; i++) {
95100
observed_data_t *data = &observed_data[i];
96101

@@ -502,8 +507,16 @@ static mp_obj_t pb_module_ble_version(mp_obj_t self_in) {
502507
}
503508
static MP_DEFINE_CONST_FUN_OBJ_1(pb_module_ble_version_obj, pb_module_ble_version);
504509

510+
mp_obj_t pb_module_ble_data_close(mp_obj_t self_in) {
511+
observed_data = NULL;
512+
num_observed_data = 0;
513+
return mp_const_none;
514+
}
515+
MP_DEFINE_CONST_FUN_OBJ_1(pb_module_ble_data_close_obj, pb_module_ble_data_close);
516+
505517
static const mp_rom_map_elem_t common_BLE_locals_dict_table[] = {
506518
{ MP_ROM_QSTR(MP_QSTR_broadcast), MP_ROM_PTR(&pb_module_ble_broadcast_obj) },
519+
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&pb_module_ble_data_close_obj) },
507520
{ MP_ROM_QSTR(MP_QSTR_observe), MP_ROM_PTR(&pb_module_ble_observe_obj) },
508521
{ MP_ROM_QSTR(MP_QSTR_signal_strength), MP_ROM_PTR(&pb_module_ble_signal_strength_obj) },
509522
{ MP_ROM_QSTR(MP_QSTR_version), MP_ROM_PTR(&pb_module_ble_version_obj) },
@@ -544,8 +557,7 @@ mp_obj_t pb_type_BLE_new(mp_obj_t broadcast_channel_in, mp_obj_t observe_channel
544557
mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("Bluetooth not enabled"));
545558
}
546559
#endif // PBSYS_CONFIG_BLUETOOTH_TOGGLE
547-
548-
pb_obj_BLE_t *self = mp_obj_malloc_var(pb_obj_BLE_t, observed_data, observed_data_t, num_observe_channels, &pb_type_BLE);
560+
pb_obj_BLE_t *self = mp_obj_malloc_var_with_finaliser(pb_obj_BLE_t, observed_data_t, num_observe_channels, &pb_type_BLE);
549561
self->broadcast_channel = broadcast_channel_in;
550562

551563
for (mp_int_t i = 0; i < num_observe_channels; i++) {
@@ -577,10 +589,4 @@ mp_obj_t pb_type_BLE_new(mp_obj_t broadcast_channel_in, mp_obj_t observe_channel
577589
return MP_OBJ_FROM_PTR(self);
578590
}
579591

580-
void pb_type_ble_start_cleanup(void) {
581-
582-
observed_data = NULL;
583-
num_observed_data = 0;
584-
}
585-
586592
#endif // PYBRICKS_PY_COMMON_BLE

pybricks/iodevices/pb_type_iodevices_lwp3device.c

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -396,12 +396,6 @@ static mp_obj_t pb_lwp3device_connect(mp_obj_t self_in, mp_obj_t name_in, mp_obj
396396
return pb_type_async_wait_or_await(&config, &lwp3device->iter, true);
397397
}
398398

399-
void pb_type_lwp3device_start_cleanup(void) {
400-
401-
#if PYBRICKS_PY_IODEVICES
402-
MP_STATE_PORT(notification_buffer) = NULL;
403-
#endif
404-
}
405399

406400
mp_obj_t pb_type_remote_button_pressed(void) {
407401
pb_lwp3device_t *remote = &pb_lwp3device_singleton;
@@ -530,10 +524,13 @@ MP_DEFINE_CONST_OBJ_TYPE(pb_type_pupdevices_Remote,
530524

531525
#if PYBRICKS_PY_IODEVICES
532526

527+
// pointer to dynamically allocated memory - needed for driver callback
528+
static uint8_t *notification_buffer;
529+
533530
static pbio_pybricks_error_t handle_lwp3_generic_notification(const uint8_t *value, uint32_t size) {
534531
pb_lwp3device_t *self = &pb_lwp3device_singleton;
535532

536-
if (!MP_STATE_PORT(notification_buffer) || !self->noti_num) {
533+
if (!notification_buffer || !self->noti_num) {
537534
// Allocated data not ready, but no error.
538535
return PBIO_PYBRICKS_ERROR_OK;
539536
}
@@ -543,7 +540,7 @@ static pbio_pybricks_error_t handle_lwp3_generic_notification(const uint8_t *val
543540
self->noti_idx_read = (self->noti_idx_read + 1) % self->noti_num;
544541
}
545542

546-
memcpy(&MP_STATE_PORT(notification_buffer)[self->noti_idx_write * LWP3_MAX_MESSAGE_SIZE], &value[0], (size < LWP3_MAX_MESSAGE_SIZE) ? size : LWP3_MAX_MESSAGE_SIZE);
543+
memcpy(&notification_buffer[self->noti_idx_write * LWP3_MAX_MESSAGE_SIZE], &value[0], (size < LWP3_MAX_MESSAGE_SIZE) ? size : LWP3_MAX_MESSAGE_SIZE);
547544
self->noti_idx_write = (self->noti_idx_write + 1) % self->noti_num;
548545

549546
// After writing it is full if the _next_ write will override the
@@ -553,6 +550,11 @@ static pbio_pybricks_error_t handle_lwp3_generic_notification(const uint8_t *val
553550
return PBIO_PYBRICKS_ERROR_OK;
554551
}
555552

553+
typedef struct {
554+
mp_obj_base_t base;
555+
uint8_t notification_buffer[];
556+
} lwp3_device_obj_t;
557+
556558
static mp_obj_t pb_type_iodevices_LWP3Device_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
557559
PB_PARSE_ARGS_CLASS(n_args, n_kw, args,
558560
PB_ARG_REQUIRED(hub_kind),
@@ -561,7 +563,7 @@ static mp_obj_t pb_type_iodevices_LWP3Device_make_new(const mp_obj_type_t *type,
561563
PB_ARG_DEFAULT_FALSE(pair),
562564
PB_ARG_DEFAULT_INT(num_notifications, 8));
563565

564-
mp_obj_base_t *obj = mp_obj_malloc(mp_obj_base_t, type);
566+
565567
pb_lwp3device_t *self = &pb_lwp3device_singleton;
566568

567569
uint8_t hub_kind = pb_obj_get_positive_int(hub_kind_in);
@@ -570,11 +572,13 @@ static mp_obj_t pb_type_iodevices_LWP3Device_make_new(const mp_obj_type_t *type,
570572
self->noti_num = mp_obj_get_int(num_notifications_in);
571573
self->noti_num = self->noti_num > 0 ? self->noti_num : 1;
572574

573-
if (MP_STATE_PORT(notification_buffer)) {
575+
if (notification_buffer) {
574576
mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("Can use only one LWP3Device"));
575577
}
576578

577-
MP_STATE_PORT(notification_buffer) = m_malloc0(LWP3_MAX_MESSAGE_SIZE * self->noti_num);
579+
lwp3_device_obj_t *obj = mp_obj_malloc_var_with_finaliser(lwp3_device_obj_t, uint8_t, LWP3_MAX_MESSAGE_SIZE * self->noti_num, type);
580+
notification_buffer = obj->notification_buffer;
581+
memset(notification_buffer, 0, LWP3_MAX_MESSAGE_SIZE * self->noti_num);
578582
self->noti_idx_read = 0;
579583
self->noti_idx_write = 0;
580584
self->noti_data_full = false;
@@ -608,7 +612,7 @@ static mp_obj_t lwp3device_read(mp_obj_t self_in) {
608612

609613
pb_lwp3device_assert_connected();
610614

611-
if (!self->noti_num || !MP_STATE_PORT(notification_buffer)) {
615+
if (!self->noti_num || !notification_buffer) {
612616
pb_assert(PBIO_ERROR_FAILED);
613617
}
614618

@@ -622,7 +626,7 @@ static mp_obj_t lwp3device_read(mp_obj_t self_in) {
622626
self->noti_idx_read = (self->noti_idx_read + 1) % self->noti_num;
623627

624628
// First byte is the size.
625-
uint8_t len = MP_STATE_PORT(notification_buffer)[index * LWP3_MAX_MESSAGE_SIZE];
629+
uint8_t len = notification_buffer[index * LWP3_MAX_MESSAGE_SIZE];
626630
if (len < LWP3_HEADER_SIZE || len > LWP3_MAX_MESSAGE_SIZE) {
627631
// This is rare but it can happen sometimes. It is better to just
628632
// ignore it rather than raise and crash the user application.
@@ -632,11 +636,17 @@ static mp_obj_t lwp3device_read(mp_obj_t self_in) {
632636
// Allocation of the return object may drive the runloop and process
633637
// new incoming messages, so copy data atomically before that happens.
634638
uint8_t message[LWP3_MAX_MESSAGE_SIZE];
635-
memcpy(message, &MP_STATE_PORT(notification_buffer)[index * LWP3_MAX_MESSAGE_SIZE], len);
639+
memcpy(message, &notification_buffer[index * LWP3_MAX_MESSAGE_SIZE], len);
636640
return mp_obj_new_bytes(message, len);
637641
}
638642
static MP_DEFINE_CONST_FUN_OBJ_1(lwp3device_read_obj, lwp3device_read);
639643

644+
mp_obj_t lwp3device_data_close(mp_obj_t self_in) {
645+
notification_buffer = NULL;
646+
return mp_const_none;
647+
}
648+
MP_DEFINE_CONST_FUN_OBJ_1(lwp3device_data_close_obj, lwp3device_data_close);
649+
640650
static const mp_rom_map_elem_t pb_type_iodevices_LWP3Device_locals_dict_table[] = {
641651
{ MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&pb_lwp3device_disconnect_obj) },
642652
{ MP_ROM_QSTR(MP_QSTR_name), MP_ROM_PTR(&pb_lwp3device_name_obj) },

pybricks/pupdevices.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ extern const mp_obj_type_t pb_type_pupdevices_TiltSensor;
2525
extern const mp_obj_type_t pb_type_pupdevices_UltrasonicSensor;
2626

2727
pb_type_device_obj_base_t *pupdevices_ColorDistanceSensor__get_device(mp_obj_t obj);
28-
void pb_type_lwp3device_start_cleanup(void);
2928

3029
#endif // PYBRICKS_PY_PUPDEVICES
3130

pybricks/pybricks.c

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -190,15 +190,3 @@ void pb_package_pybricks_init(bool import_all) {
190190
pb_module_tools_init();
191191
}
192192
#endif // PYBRICKS_OPT_COMPILER
193-
194-
// REVISIT: move these to object finalizers if we enable finalizers in the GC
195-
void pb_package_pybricks_deinit(void) {
196-
197-
#if PYBRICKS_PY_COMMON_BLE
198-
pb_type_ble_start_cleanup();
199-
#endif
200-
201-
#if PYBRICKS_PY_PUPDEVICES_REMOTE
202-
pb_type_lwp3device_start_cleanup();
203-
#endif
204-
}

0 commit comments

Comments
 (0)