Skip to content

Commit

Permalink
WIP: Template Singleton make_ functions (#132)
Browse files Browse the repository at this point in the history
* Template NoteTxn Singleton `make_` function
* Template NoteLog Singleton `make_` function
* Template NoteI2c Singleton `make_` function
  • Loading branch information
zfields authored Feb 25, 2025
1 parent 2efe303 commit 663921d
Show file tree
Hide file tree
Showing 17 changed files with 188 additions and 90 deletions.
11 changes: 2 additions & 9 deletions src/NoteI2c.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,6 @@
class NoteI2c
{
public:
/**************************************************************************/
/*!
@brief Type used to abstract specific hardware implementation types.
*/
/**************************************************************************/
typedef void * param_t;

virtual ~NoteI2c(void) {}

Expand Down Expand Up @@ -94,8 +88,7 @@ class NoteI2c
the platform specific I2C implementation.
*/
/******************************************************************************/
NoteI2c * make_note_i2c (
NoteI2c::param_t i2c_parameters
);
template <typename T> NoteI2c * make_note_i2c (T & i2c_parameters);
NoteI2c * make_note_i2c (nullptr_t);

#endif // NOTE_I2C_HPP
38 changes: 29 additions & 9 deletions src/NoteI2c_Arduino.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,37 @@
static const char *i2cerr = "i2c {io}";
#endif

// Singleton instance of the NoteI2c_Arduino class
namespace instance {
inline NoteI2c* & note_i2c (void) {
static NoteI2c* note_i2c = nullptr;
return note_i2c;
}
};

NoteI2c *
make_note_i2c (
NoteI2c::param_t i2c_parameters_
nullptr_t
) {
NoteI2c* & note_i2c = instance::note_i2c();
if (note_i2c) {
delete note_i2c;
note_i2c = nullptr;
}
return note_i2c;
}

template <typename T>
NoteI2c *
make_note_i2c (
T & i2c_parameters_
)
{
static NoteI2c * note_i2c = nullptr;
if (!i2c_parameters_) {
if (note_i2c) {
delete note_i2c;
note_i2c = nullptr;
}
} else if (!note_i2c) {
note_i2c = new NoteI2c_Arduino(*reinterpret_cast<TwoWire *>(i2c_parameters_));
NoteI2c* & note_i2c = instance::note_i2c();
if (!note_i2c) {
note_i2c = new NoteI2c_Arduino(i2c_parameters_);
}

return note_i2c;
}

Expand Down Expand Up @@ -182,3 +199,6 @@ NoteI2c_Arduino::transmit (

return result;
}

// Explicitly instantiate the template function for the supported types
template NoteI2c * make_note_i2c<TwoWire>(TwoWire &);
11 changes: 2 additions & 9 deletions src/NoteLog.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,6 @@
class NoteLog
{
public:
/**************************************************************************/
/*!
@brief Type used to abstract specific hardware implementation types.
*/
/**************************************************************************/
typedef void * param_t;

virtual ~NoteLog(void) {}

Expand All @@ -36,8 +30,7 @@ class NoteLog
the platform specific log output implementation.
*/
/******************************************************************************/
NoteLog * make_note_log (
NoteLog::param_t log_parameters
);
template <typename T> NoteLog * make_note_log (T & log_parameters);
NoteLog * make_note_log (nullptr_t);

#endif // NOTE_LOG_HPP
41 changes: 30 additions & 11 deletions src/NoteLog_Arduino.cpp
Original file line number Diff line number Diff line change
@@ -1,19 +1,35 @@
#include "NoteLog_Arduino.hpp"

// Singleton instance of the NoteLog_Arduino class
namespace instance {
inline NoteLog* & note_log (void) {
static NoteLog* note_log = nullptr;
return note_log;
}
};

NoteLog *
make_note_log (
NoteLog::param_t log_parameters_
)
{
static NoteLog * note_log = nullptr;
if (!log_parameters_) {
if (note_log) {
delete note_log;
note_log = nullptr;
}
} else if (!note_log) {
note_log = new NoteLog_Arduino(reinterpret_cast<Stream *>(log_parameters_));
nullptr_t
) {
NoteLog* & note_log = instance::note_log();
if (note_log) {
delete note_log;
note_log = nullptr;
}
return note_log;
}

template <typename T>
NoteLog *
make_note_log (
T & log_parameters_
) {
NoteLog* & note_log = instance::note_log();
if (!note_log) {
note_log = new NoteLog_Arduino(reinterpret_cast<T *>(&log_parameters_));
}

return note_log;
}

Expand All @@ -35,3 +51,6 @@ NoteLog_Arduino::print (

return result;
}

// Explicitly instantiate the template function for the supported types
template NoteLog * make_note_log<Stream>(Stream &);
11 changes: 2 additions & 9 deletions src/NoteTxn.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,6 @@
class NoteTxn
{
public:
/**************************************************************************/
/*!
@brief Type used to abstract specific hardware implementation types.
*/
/**************************************************************************/
typedef void * param_t;

virtual ~NoteTxn(void) {}

Expand Down Expand Up @@ -44,8 +38,7 @@ class NoteTxn
the platform specific transaction implementation.
*/
/******************************************************************************/
NoteTxn * make_note_txn (
NoteTxn::param_t txn_parameters
);
template<typename T> NoteTxn * make_note_txn (T & txn_parameters);
NoteTxn * make_note_txn (nullptr_t);

#endif // NOTE_TXN_HPP
40 changes: 33 additions & 7 deletions src/NoteTxn_Arduino.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,43 @@
#include "mock/mock-parameters.hpp"
#endif

// Singleton instance of the NoteTxn_Arduino class
namespace instance {
inline NoteTxn* & note_txn (void) {
static NoteTxn* note_txn = nullptr;
return note_txn;
}
};

NoteTxn *
make_note_txn (
NoteTxn::param_t txn_parameters_
)
{
static NoteTxn * note_txn = nullptr;
if (!txn_parameters_) {
nullptr_t
) {
NoteTxn* & note_txn = instance::note_txn();
if (note_txn) {
delete note_txn;
note_txn = nullptr;
}
return note_txn;
}

template <typename T>
NoteTxn *
make_note_txn (
T & txn_pins_
) {
NoteTxn* & note_txn = instance::note_txn();

if (txn_pins_[0] == txn_pins_[1]) {
// Invalid tuple invokes deletion
if (note_txn) {
delete note_txn;
note_txn = nullptr;
}
} else if (!note_txn) {
const uint8_t * txn_pins = reinterpret_cast<uint8_t *>(txn_parameters_);
note_txn = new NoteTxn_Arduino(txn_pins[0], txn_pins[1]);
note_txn = new NoteTxn_Arduino(txn_pins_[0], txn_pins_[1]);
}

return note_txn;
}

Expand Down Expand Up @@ -80,3 +102,7 @@ NoteTxn_Arduino::stop (
// Float RTX pin
::pinMode(_rtx_pin, INPUT);
}

// Explicitly instantiate the template function for array types
template NoteTxn * make_note_txn<uint8_t[2]>(uint8_t(&)[2]);
template NoteTxn * make_note_txn<const uint8_t[2]>(const uint8_t(&)[2]);
4 changes: 2 additions & 2 deletions src/Notecard.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ class Notecard
inline void begin(uint32_t i2cAddress = NOTE_I2C_ADDR_DEFAULT,
uint32_t i2cMax = NOTE_I2C_MAX_DEFAULT,
TwoWire &wirePort = Wire) {
begin(make_note_i2c(&wirePort), i2cAddress, i2cMax);
begin(make_note_i2c(wirePort), i2cAddress, i2cMax);
}
inline void begin(HardwareSerial &serial, uint32_t speed = 9600) {
MakeNoteSerial_ArduinoParameters<HardwareSerial> arduino_parameters(serial, speed);
Expand All @@ -76,7 +76,7 @@ class Notecard
}
#endif
inline void setDebugOutputStream(Stream &dbgserial) {
setDebugOutputStream(make_note_log(&dbgserial));
setDebugOutputStream(make_note_log(dbgserial));
}
inline void setTransactionPins(uint8_t ctx_pin, uint8_t rtx_pin) {
uint8_t txn_pins[2] = {ctx_pin, rtx_pin};
Expand Down
8 changes: 4 additions & 4 deletions test/NoteI2c_Arduino.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ int test_make_note_i2c_instantiates_notei2c_object()
NoteI2c * notei2c = nullptr;

// Action
notei2c = make_note_i2c(reinterpret_cast<NoteI2c::param_t>(&Wire));
notei2c = make_note_i2c(Wire);

// Assert
if (nullptr != notei2c)
Expand All @@ -42,10 +42,10 @@ int test_make_note_i2c_enforces_singleton_by_returning_same_notei2c_object_for_a
int result;

// Arrange
NoteI2c * const notei2c_1 = make_note_i2c(reinterpret_cast<NoteI2c::param_t>(&Wire));
NoteI2c * const notei2c_1 = make_note_i2c(Wire);

// Action
NoteI2c * const notei2c_2 = make_note_i2c(reinterpret_cast<NoteI2c::param_t>(&Wire));
NoteI2c * const notei2c_2 = make_note_i2c(Wire);

// Assert
if (notei2c_1 == notei2c_2)
Expand All @@ -72,7 +72,7 @@ int test_make_note_i2c_deletes_singleton_when_nullptr_is_passed_as_parameter()
int result;

// Arrange
NoteI2c * notei2c = make_note_i2c(reinterpret_cast<NoteI2c::param_t>(&Wire));
NoteI2c * notei2c = make_note_i2c(Wire);
assert(notei2c);

// Action
Expand Down
11 changes: 7 additions & 4 deletions test/NoteLog_Arduino.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ int test_make_note_log_instantiates_notelog_object()

// Arrange
NoteLog * notelog = nullptr;
Stream & serial_stream = Serial;

// Action
notelog = make_note_log(reinterpret_cast<NoteLog::param_t>(&Serial));
notelog = make_note_log(serial_stream);

// Assert
if (nullptr != notelog)
Expand All @@ -42,10 +43,11 @@ int test_make_note_log_enforces_singleton_by_returning_same_notelog_object_for_a
int result;

// Arrange
NoteLog * const notelog_1 = make_note_log(reinterpret_cast<NoteLog::param_t>(&Serial));
Stream & serial_stream = Serial;
NoteLog * const notelog_1 = make_note_log(serial_stream);

// Action
NoteLog * const notelog_2 = make_note_log(reinterpret_cast<NoteLog::param_t>(&Serial));
NoteLog * const notelog_2 = make_note_log(serial_stream);

// Assert
if (notelog_1 == notelog_2)
Expand All @@ -72,7 +74,8 @@ int test_make_note_log_deletes_singleton_when_nullptr_is_passed_as_parameter()
int result;

// Arrange
NoteLog * notelog = make_note_log(reinterpret_cast<NoteLog::param_t>(&Serial));
Stream & serial_stream = Serial;
NoteLog * notelog = make_note_log(serial_stream);
assert(notelog);

// Action
Expand Down
23 changes: 13 additions & 10 deletions test/NoteTxn_Arduino.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ int test_make_note_txn_instantiates_notetxn_object()
uint8_t txn_pins[2] = {19, 79};

// Action
notetxn = make_note_txn(reinterpret_cast<NoteTxn::param_t>(txn_pins));
notetxn = make_note_txn(txn_pins);

// Assert
if (nullptr != notetxn)
Expand All @@ -32,7 +32,8 @@ int test_make_note_txn_instantiates_notetxn_object()
}

// Clean-up
make_note_txn(nullptr);
uint8_t invalid_pins[2] = {0};
make_note_txn(invalid_pins);

return result;
}
Expand All @@ -43,11 +44,11 @@ int test_make_note_txn_enforces_singleton_by_returning_same_notetxn_object_for_a

// Arrange
uint8_t txn_pins_1[2] = {19, 79};
NoteTxn * const notetxn_1 = make_note_txn(reinterpret_cast<NoteTxn::param_t>(txn_pins_1));
NoteTxn * const notetxn_1 = make_note_txn(txn_pins_1);

// Action
uint8_t txn_pins_2[2] = {9, 17};
NoteTxn * const notetxn_2 = make_note_txn(reinterpret_cast<NoteTxn::param_t>(txn_pins_2));
NoteTxn * const notetxn_2 = make_note_txn(txn_pins_2);

// Assert
if (notetxn_1 == notetxn_2)
Expand All @@ -63,23 +64,25 @@ int test_make_note_txn_enforces_singleton_by_returning_same_notetxn_object_for_a
}

// Clean-up
make_note_txn(nullptr);
uint8_t invalid_pins[2] = {0};
make_note_txn(invalid_pins);

return result;
}

//int test_make_note_txn_returns_nullptr_when_nullptr_is_passed_as_parameter()
int test_make_note_txn_deletes_singleton_when_nullptr_is_passed_as_parameter()
//int test_make_note_txn_returns_nullptr_when_same_pins_are_passed_as_parameter()
int test_make_note_txn_deletes_singleton_when_same_pins_are_passed_as_parameter()
{
int result;

// Arrange
uint8_t txn_pins[2] = {19, 79};
NoteTxn * notetxn = make_note_txn(reinterpret_cast<NoteTxn::param_t>(txn_pins));
NoteTxn * notetxn = make_note_txn(txn_pins);
assert(notetxn);

// Action
notetxn = make_note_txn(nullptr);
uint8_t invalid_pins[2] = {0};
notetxn = make_note_txn(invalid_pins);

// Assert
if (nullptr == notetxn)
Expand Down Expand Up @@ -605,7 +608,7 @@ int main(void)
TestFunction tests[] = {
{test_make_note_txn_instantiates_notetxn_object, "test_make_note_txn_instantiates_notetxn_object"},
{test_make_note_txn_enforces_singleton_by_returning_same_notetxn_object_for_all_calls, "test_make_note_txn_enforces_singleton_by_returning_same_notetxn_object_for_all_calls"},
{test_make_note_txn_deletes_singleton_when_nullptr_is_passed_as_parameter, "test_make_note_txn_deletes_singleton_when_nullptr_is_passed_as_parameter"},
{test_make_note_txn_deletes_singleton_when_same_pins_are_passed_as_parameter, "test_make_note_txn_deletes_singleton_when_same_pins_are_passed_as_parameter"},
{test_notetxn_arduino_constructor_floats_ctx_pin, "test_notetxn_arduino_constructor_floats_ctx_pin"},
{test_notetxn_arduino_constructor_floats_rtx_pin, "test_notetxn_arduino_constructor_floats_rtx_pin"},
{test_notetxn_arduino_start_initially_configures_ctx_pin_as_input_pullup, "test_notetxn_arduino_start_initially_configures_ctx_pin_as_input_pullup"},
Expand Down
Loading

0 comments on commit 663921d

Please sign in to comment.