template<typename T, typename Context, uint32_t MaxNumberOfContext = 500>
class iox::concurrent::TACO< T, Context, MaxNumberOfContext >
TACO is an acronym for Thread Aware exChange Ownership. Exchanging data between thread needs some synchonization mechanism. This can be done with a mutex or atomics. If the data structure is larger than 64 bit or if more than one value need to be accessed in a synchronized manner, a mutex would be the only option. The TACO is a wait-free alternative to the mutex. Data can be exchanged between threads. The TACO is like a SoFi with one element, but with the possibility to read/write from multiple threads.
- Parameters
-
T | DataType to be stored |
Context | Enum class with all the thread context that access the TACO. The enum must start with 0, must have ascending values and the last vaule must be called END_OF_LIST. |
#include "iceoryx_utils/internal/concurrent/taco.hpp"
#include <cstdint>
#include <iostream>
#include <thread>
constexpr std::uint64_t TotalCount{1000000};
struct SyncedData
{
std::uint64_t decrementCounter{TotalCount};
std::uint64_t incrementCounter{0};
};
enum class ThreadContext : uint32_t
{
Hardy,
Laurel,
END_OF_LIST
};
int main()
{
concurrent::TACO<SyncedData, ThreadContext> taco(concurrent::TACOMode::DenyDataFromSameContext);
constexpr auto producerContext {ThreadContext::Hardy};
constexpr auto consumerContext {ThreadContext::Laurel};
auto producer = std::thread([&] {
SyncedData data;
while (data.decrementCounter != 0)
{
data.decrementCounter--;
data.incrementCounter++;
taco.store(data, producerContext);
}
});
auto consumer = std::thread([&] {
SyncedData data;
do
{
auto retVal = taco.take(consumerContext);
if (retVal.has_value())
{
data = *retVal;
if(data.decrementCounter + data.incrementCounter != TotalCount)
{
std::cout << "Error! Counter not synchronized!" << std::endl;
}
}
} while (data.decrementCounter != 0);
});
producer.join();
consumer.join();
std::cout << "Finished!" << std::endl;
return 0;
}