diff --git a/src/transactions/engine.hpp b/src/transactions/engine.hpp index 812bb7f04..5f647b23e 100644 --- a/src/transactions/engine.hpp +++ b/src/transactions/engine.hpp @@ -21,7 +21,7 @@ class Engine : Lockable<SpinLock> { public: using sptr = std::shared_ptr<Engine>; - Engine() : counter(1) {} + Engine() : counter(0) {} // Begins transaction and runs given functions in same atomic step. // Functions will be given Transaction& @@ -77,9 +77,15 @@ class Engine : Lockable<SpinLock> { finalize(t); } - Id last_known_active() { + /* + *@brief Return oldest active transaction in the active transaction pool. In + *case none exist return None. + *@return Id of transaction + */ + Option<Id> oldest_active() { auto guard = this->acquire_unique(); - return active.front(); + if (active.size() == 0) return Option<Id>(); + return Option<Id>(active.front()); } // total number of transactions started from the beginning of time diff --git a/tests/concurrent/transaction_engine.cpp b/tests/concurrent/transaction_engine.cpp index 67befdde9..d8f5e41c3 100644 --- a/tests/concurrent/transaction_engine.cpp +++ b/tests/concurrent/transaction_engine.cpp @@ -31,15 +31,14 @@ int main() { for (int i = 0; i < THREADS; ++i) threads.push_back(std::thread(f, i, TRANSACTIONS)); - for (auto& thread : threads) thread.join(); + for (auto &thread : threads) thread.join(); uint64_t sum_computed = 0; for (int i = 0; i < THREADS; ++i) sum_computed += sums[i]; uint64_t sum_actual = 0; - for (uint64_t i = 2; i <= THREADS * TRANSACTIONS + 1; ++i) sum_actual += i; - // the range is strange because the first transaction gets transaction id 2 + for (uint64_t i = 1; i <= THREADS * TRANSACTIONS; ++i) sum_actual += i; std::cout << sum_computed << " " << sum_actual << std::endl; permanent_assert(sum_computed == sum_actual, "sums have to be the same"); diff --git a/tests/unit/transaction_engine.cpp b/tests/unit/transaction_engine.cpp new file mode 100644 index 000000000..4a5ed06e4 --- /dev/null +++ b/tests/unit/transaction_engine.cpp @@ -0,0 +1,58 @@ +#include "gtest/gtest.h" + +#include <vector> + +#include "transactions/engine.hpp" +#include "transactions/transaction.hpp" + +TEST(Engine, Count) { + tx::Engine eng; + EXPECT_EQ(eng.count(), 0); +} + +TEST(Engine, CountFive) { + tx::Engine eng; + EXPECT_EQ(eng.count(), (uint64_t)0); + std::vector<tx::Transaction *> V; + for (int i = 0; i < 5; ++i) { + V.push_back(eng.begin()); + EXPECT_EQ(eng.count(), (uint64_t)(i + 1)); + } + EXPECT_EQ(eng.size(), (uint64_t)5); + for (int i = 0; i < 5; ++i) V[i]->commit(); + EXPECT_EQ(eng.count(), (uint64_t)5); +} + +TEST(Engine, LastKnownActiveEmpty) { + tx::Engine eng; + EXPECT_EQ(eng.oldest_active().is_present(), false); +} + +TEST(Engine, LastKnownActive) { + tx::Engine eng; + std::vector<tx::Transaction *> V; + for (int i = 0; i < 5; ++i) { + V.push_back(eng.begin()); + EXPECT_EQ(eng.size(), (size_t)i + 1); + } + for (int i = 0; i < 5; ++i) { + EXPECT_EQ(eng.oldest_active().get(), Id(i + 1)); + V[i]->commit(); + } + EXPECT_EQ(eng.oldest_active().is_present(), false); +} + +TEST(Engine, Size) { + tx::Engine eng; + std::vector<tx::Transaction *> V; + for (int i = 0; i < 5; ++i) { + V.push_back(eng.begin()); + EXPECT_EQ(eng.size(), (size_t)i + 1); + } + for (int i = 0; i < 5; ++i) V[i]->commit(); +} + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +}