Created
June 1, 2021 10:04
-
-
Save madmongo1/cb4d9770d458f9860dde438aca5068b4 to your computer and use it in GitHub Desktop.
Atomic transfer between polymorphic producer and consumer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// @brief The result of attemping an atomic produce, consume or produce and | |
/// consume. | |
struct io_transfer_result | |
{ | |
/// 1 if the transfer completed | |
unsigned char success : 1 = 0; | |
/// 1 if the consumer is in the completed state | |
unsigned char consumed : 1 = 0; | |
/// 1 if the prodicer is in the completed state | |
unsigned char produced : 1 = 0; | |
}; | |
// clang-format off | |
/// @brief Attempt to transfer the contents of the producer to the consumer | |
/// | |
/// The function will keep attempting delivery until either delivery occurs or | |
/// one or other of the producer and consumer enters the committed state. | |
/// The transfer, it occurs will be atomic - i.e. the producer will not give up | |
/// its value if the consumer is not in a state to accept it. | |
/// The return value is a an @see io_transfer_result indicating the final state | |
/// of the producer and consumer and whether the value was transferred. | |
/// Only the following return value combinations are possible: | |
/// | |
/// success | consumed | produced | Description | |
/// ------- | -------- | -------- | ----------- | |
/// 1 | 1 | 1 | The transfer occurred. Both producer and consumer can be safely discarded. | |
/// 0 | 1 | 1 | The transfer did not occur. Both producer and consumer should be discarded. | |
/// 0 | 0 | 1 | The transfer did not occur. The producer should be discarded. The consumer is still awaiting a value. | |
/// 0 | 1 | 0 | The transfer did not occur. The consumer should be discarded. The producer still holds a value. | |
/// | |
/// @tparam ValueType Is the type of value being transferred | |
/// @param producer is a reference to the producer object | |
/// @param consumer is a reference to the consumer object | |
/// @return The result of the atomic transfer | |
// clang-format on | |
template < class ValueType > | |
io_transfer_result | |
transfer_producer_to_consumer(produce_op_interface< ValueType > &producer, | |
consume_op_interface< ValueType > &consumer) | |
{ | |
again: | |
auto result = io_transfer_result(); | |
switch (consumer.reserve()) | |
{ | |
case io_op_action_code::action_completed: | |
result.consumed = true; | |
goto done; | |
case io_op_action_code::action_busy: | |
BOOST_CHANNELS_BUSY_WAIT(); | |
goto again; | |
case io_op_action_code::action_reserved: | |
switch (producer.reserve()) | |
{ | |
case io_op_action_code::action_completed: | |
consumer.release(); | |
result.produced = 1; | |
goto done; | |
case io_op_action_code::action_busy: | |
consumer.release(); | |
BOOST_CHANNELS_BUSY_WAIT(); | |
goto again; | |
case io_op_action_code::action_reserved: | |
// success case | |
consumer.commit(producer.consume()); | |
result.produced = 1; | |
result.consumed = 1; | |
result.success = 1; | |
break; | |
} | |
} | |
done: | |
return result; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment