Skip to content

Commit

Permalink
Event Identify Global Fix Comments, Add Delete Self Option (#535)
Browse files Browse the repository at this point in the history
* Fix comments.

* Add option to delete self (one-shot).
  • Loading branch information
bakerstu authored Apr 11, 2021
1 parent 1f57f21 commit 873d99c
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 7 deletions.
18 changes: 18 additions & 0 deletions src/openlcb/EventIdentifyGlobal.cxxtest
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,24 @@ TEST_F(EventIdentifyGlobalTest, Arm)
sleep_helper(100);
}

TEST_F(EventIdentifyGlobalTest, ArmDeleteSelf)
{
::testing::Sequence s1;

// test coverage for this is limited because we loose track of the
// pointer for "self" for the object.
flow_->arm(true);

expect_packet(":X1997022AN;").Times(0).InSequence(s1);
sleep_helper(1500 + generate_random() - 50);

expect_packet(":X1997022AN;").Times(1).InSequence(s1);
sleep_helper(100);

// prevent crash of test since pointer is no longer valid.
flow_.release();
}

TEST_F(EventIdentifyGlobalTest, ArmMultipleTimes)
{
::testing::Sequence s1;
Expand Down
21 changes: 14 additions & 7 deletions src/openlcb/EventIdentifyGlobal.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,11 @@ namespace openlcb
/// Helper object for producing an Event Identify Global message. Once armed,
/// will produce an Event Identify Global message on the node's interface
/// at a pseudo random time between 1.500 and 2.011 seconds in the future. The
/// randomness comes from the 9 least significant bits of the Node ID and aids
/// in reducing the likeliness of multiple nodes of the same design producing
/// the same Event Identify Global message unnecessarily.
/// randomness comes a hash of the Node ID and aids in reducing the likeliness
/// of multiple nodes of the same design producing the same Event Identify
/// Global message unnecessarily. If another node produces the Event Identify
/// Global first (after arm but before timeout), then we abort the state
/// machine early.
class EventIdentifyGlobal : public StateFlowBase, private Atomic
{
public:
Expand All @@ -59,6 +61,7 @@ public:
, timer_(this)
, node_(node)
, aborted_(false)
, deleteSelf_(false)
{
node_->iface()->dispatcher()->register_handler(
&eventIdentifyGlobalHandler_, Defs::MTI_EVENTS_IDENTIFY_GLOBAL,
Expand All @@ -74,12 +77,15 @@ public:
}

/// Arm the EventIdentifyGlobal request. Multi-thread safe.
void arm()
/// @param delete_self true if the object should delete itself on next
/// state flow completion (one-shot).
void arm(bool delete_self = false)
{
AtomicHolder h(this);
if (is_terminated())
{
aborted_ = false;
deleteSelf_ = delete_self;
start_flow(STATE(entry));
}
}
Expand All @@ -97,10 +103,10 @@ private:
/// Entry/reset point into state machine.
Action entry()
{
// get a pseudo random number between 1.500 and 2.011 seconds
uint64_t h = node_->node_id() * 0x1c19a66d;
uint32_t hh = h ^ (h >> 32);
hh = hh ^ (hh >> 12) ^ (hh >> 24);
// get a pseudo random number between 1.500 and 2.011 seconds
long long timeout_msec = 1500 + (hh & 0x1FF);

return sleep_and_call(
Expand All @@ -118,7 +124,7 @@ private:
if (aborted_)
{
// no need to send Event Identify Global, already detected one
return exit();
return deleteSelf_ ? delete_this() : exit();
}
}

Expand All @@ -142,14 +148,15 @@ private:
Defs::MTI_EVENTS_IDENTIFY_GLOBAL, node_->node_id(), EMPTY_PAYLOAD);
node_->iface()->global_message_write_flow()->send(b);

return exit();
return deleteSelf_ ? delete_this() : exit();
}

/// handler for incoming messages
MessageHandler::GenericHandler eventIdentifyGlobalHandler_;
StateFlowTimer timer_; ///< timer object for handling the timeout
Node *node_; ///< node to send message from
uint8_t aborted_ : 1; ///< true if message received, abort need to send
uint8_t deleteSelf_ : 1; ///< delete object upon state flow exit (one-shot)
};

} // namespace openlcb
Expand Down

0 comments on commit 873d99c

Please sign in to comment.