-
Notifications
You must be signed in to change notification settings - Fork 27
Implementation of mechanisms for synchronisation of memory access at the knowledge level #483
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 5 commits
9d8d7fa
bbd5206
1d0fc23
29cd498
84f8bac
ba1ff66
6e28a24
1a5d43d
2967adc
a4df08d
c433d47
06a7dcb
a418e36
5ca1034
c3e7cb1
f97767e
fd3440b
8e01f63
96e1c8f
af0f29a
ae7903c
e6e59d8
795c295
61b1539
cfd7d8d
6cf6c41
90fb0e5
8f972be
6143ff4
63c29a9
6c0bcee
40e6e49
fbea119
04b869b
2d56991
7f4f263
271ad88
21f83c7
1a46dac
9e5440d
37dd131
a32c7e4
43a1959
9d6304b
9cc97a1
2ce15b7
5ce3646
6310a81
e71d400
0911739
8d97092
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| #include "sc_element_version.h" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| #ifndef SC_ELEMENT_VERSION_H | ||
| #define SC_ELEMENT_VERSION_H | ||
|
|
||
| #include "sc-core/sc_types.h" | ||
|
|
||
| typedef struct sc_element_version { | ||
| void* data; | ||
| sc_uint64 version_id; | ||
| struct sc_element_version* prev_version; | ||
| struct sc_element_version* next_version; | ||
| sc_bool is_committed; | ||
| } sc_element_version; | ||
|
|
||
| #endif |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,24 @@ | ||||||
| #include "sc_transaction.h" | ||||||
|
|
||||||
| #include <sc-core/sc-base/sc_allocator.h> | ||||||
|
|
||||||
| sc_transaction* sc_transaction_create(const sc_uint64* txn_id) { | ||||||
| sc_transaction *txn = sc_mem_new(sc_transaction, 1); | ||||||
| if (txn == NULL) { | ||||||
| return NULL; | ||||||
| } | ||||||
|
|
||||||
| txn->transaction_id = *txn_id; | ||||||
| txn->is_committed = SC_FALSE; | ||||||
| txn->element_count = 0; | ||||||
| sc_list_init(&txn->elements); | ||||||
| return txn; | ||||||
| } | ||||||
|
|
||||||
| void sc_transaction_destroy(sc_transaction* txn) { | ||||||
| if (txn != NULL) { | ||||||
| sc_list_clear(txn->elements); | ||||||
|
||||||
| sc_list_clear(txn->elements); | |
| sc_list_destroy(txn->elements); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| #ifndef SC_TRANSACTION_H | ||
| #define SC_TRANSACTION_H | ||
|
|
||
| #include <sc-core/sc-container/sc_list.h> | ||
|
||
|
|
||
| typedef struct sc_transaction { | ||
| sc_uint64 transaction_id; | ||
| sc_bool is_committed; | ||
| sc_list* elements; | ||
| sc_uint32 element_count; | ||
| } sc_transaction; | ||
|
|
||
| sc_transaction* sc_transaction_create(const sc_uint64* txn_id); | ||
| // create a new transaction | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We use another style for code strings
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What exactly should be adjusted to match the required code style? |
||
| void sc_transaction_destroy(sc_transaction* txn); | ||
| // destroy the given transaction | ||
|
|
||
| void sc_transaction_add_element(sc_transaction* txn, sc_element* element); | ||
| // add element to track in transaction (based on "touched" elements, manager will try to commit or rollback transaction) | ||
| void sc_transaction_commit(sc_transaction* txn); | ||
| // apply all operations of the transaction on sc-memory | ||
| void sc_transaction_rollback(sc_transaction* txn); | ||
| // rollback the transaction operations | ||
|
|
||
| sc_bool sc_transaction_validate(sc_transaction* txn); | ||
| // check if the transaction can be applied based on element versions and free segments | ||
| void sc_transaction_merge(sc_transaction* txn); | ||
| // check versions of all elements in the transaction and try to merge them | ||
| void sc_transaction_apply(sc_transaction* txn); | ||
| // apply all operations (merged versions, allocated spaces) to sc-memory | ||
| void sc_transaction_clear(sc_transaction* txn); | ||
| // deletes all transaction items and clears them without performing a commit | ||
|
|
||
| #endif | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| #include "sc_transaction_manager.h" | ||
|
|
||
| #include <sc-core/sc-base/sc_allocator.h> | ||
|
|
||
| sc_transaction_manager * transaction_manager = null_ptr; | ||
|
|
||
| sc_transaction_manager* sc_transaction_manager_initialize() { | ||
| if (sc_transaction_manager_is_initialized()) { | ||
| return transaction_manager; | ||
| } | ||
|
|
||
| transaction_manager = sc_mem_new(sc_transaction_manager, 1); | ||
| if (!sc_transaction_manager_is_initialized()) { | ||
| return null_ptr; | ||
| } | ||
|
|
||
| transaction_manager->current_sc_transaction = null_ptr; | ||
| sc_queue_init(transaction_manager->sc_transaction_queue); | ||
| sc_monitor_init(transaction_manager->sc_monitor); | ||
| transaction_manager->transaction_counter = 0; | ||
|
|
||
| return transaction_manager; | ||
| } | ||
|
|
||
| sc_bool sc_transaction_manager_is_initialized() { | ||
| return transaction_manager != null_ptr; | ||
| } | ||
|
|
||
| void sc_transaction_shutdown() { | ||
| if (transaction_manager != null_ptr) { | ||
| sc_transaction_manager_destroy(); | ||
| } | ||
| } | ||
|
|
||
| void sc_transaction_manager_destroy() { | ||
| if (transaction_manager != null_ptr) { | ||
| sc_monitor_acquire_write(transaction_manager->sc_monitor); | ||
| sc_queue_destroy(transaction_manager->sc_transaction_queue); | ||
| sc_monitor_release_write(transaction_manager->sc_monitor); | ||
|
|
||
| sc_monitor_destroy(transaction_manager->sc_monitor); | ||
|
|
||
| sc_mem_free(transaction_manager); | ||
| transaction_manager = null_ptr; | ||
| } | ||
| } | ||
|
|
||
| sc_transaction* sc_transaction_manager_transaction_new() { | ||
| if (!sc_transaction_manager_is_initialized()) { | ||
| return null_ptr; | ||
| } | ||
|
|
||
| sc_monitor_acquire_write(transaction_manager->sc_monitor); | ||
| const sc_uint64 txn_id = transaction_manager->transaction_counter++; | ||
| sc_monitor_release_write(transaction_manager->sc_monitor); | ||
|
|
||
| return sc_transaction_create(&txn_id); | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,31 @@ | ||||||
| #ifndef SC_TRANSACTION_MANAGER_H | ||||||
| #define SC_TRANSACTION_MANAGER_H | ||||||
|
|
||||||
| #include "sc_transaction.h" | ||||||
| #include "sc-store/sc-base/sc_monitor_private.h" | ||||||
|
|
||||||
| typedef struct sc_transaction_manager { | ||||||
| sc_transaction*current_sc_transaction; | ||||||
|
||||||
| sc_transaction*current_sc_transaction; | |
| sc_transaction* current_sc_transaction; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,95 @@ | ||
| #include <gtest/gtest.h> | ||
| #include <pthread.h> | ||
| #include <sc-memory/test/sc_test.hpp> | ||
|
|
||
| extern "C" { | ||
| #include <sc-store/sc-transaction/sc_transaction_manager.h> | ||
| } | ||
|
|
||
| struct TransactionThreadData { | ||
| transaction_manager* manager; | ||
| int thread_id; | ||
| }; | ||
|
|
||
| void* transaction_thread(void* arg) { | ||
| auto* data = static_cast<TransactionThreadData*>(arg); | ||
| transaction_manager* manager = data->manager; | ||
|
|
||
| sc_element_version version = {}; | ||
| log_version_change(manager, &version); | ||
|
|
||
| if (data->thread_id % 2 == 0) { | ||
| commit_transaction(manager); | ||
| } else { | ||
| rollback_transaction(manager); | ||
| } | ||
|
|
||
| return nullptr; | ||
| } | ||
|
|
||
| TEST_F(ScMemoryTest, MultiThreadedTransactionTest) { | ||
| transaction_manager manager; | ||
| initialize_transaction_manager(&manager); | ||
|
|
||
| const int NUM_THREADS = 10; | ||
| pthread_t threads[NUM_THREADS]; | ||
| TransactionThreadData thread_data[NUM_THREADS]; | ||
|
|
||
| for (int i = 0; i < NUM_THREADS; ++i) { | ||
| thread_data[i].manager = &manager; | ||
| thread_data[i].thread_id = i; | ||
| pthread_create(&threads[i], nullptr, transaction_thread, &thread_data[i]); | ||
| } | ||
|
|
||
| for (int i = 0; i < NUM_THREADS; ++i) { | ||
| pthread_join(threads[i], nullptr); | ||
| } | ||
|
|
||
| EXPECT_EQ(manager.current_transaction, nullptr); | ||
|
||
|
|
||
| EXPECT_NE(manager.log_head, nullptr); | ||
| } | ||
|
|
||
| TEST_F(ScMemoryTest, MultiThreadedTransactionLogTest) { | ||
| transaction_manager manager; | ||
| initialize_transaction_manager(&manager); | ||
|
|
||
| const int NUM_THREADS = 5; | ||
| pthread_t threads[NUM_THREADS]; | ||
| TransactionThreadData thread_data[NUM_THREADS]; | ||
|
|
||
| for (int i = 0; i < NUM_THREADS; ++i) { | ||
| thread_data[i].manager = &manager; | ||
| thread_data[i].thread_id = i; | ||
| pthread_create(&threads[i], nullptr, transaction_thread, &thread_data[i]); | ||
| } | ||
|
|
||
| for (int i = 0; i < NUM_THREADS; ++i) { | ||
| pthread_join(threads[i], nullptr); | ||
| } | ||
|
|
||
| EXPECT_NE(manager.log_head, nullptr); | ||
| } | ||
|
|
||
| TEST_F(ScMemoryTest, TransactionManagerTests) { | ||
| transaction_manager manager; | ||
| initialize_transaction_manager(&manager); | ||
|
|
||
| const int NUM_THREADS = 20; | ||
| pthread_t threads[NUM_THREADS]; | ||
| TransactionThreadData thread_data[NUM_THREADS]; | ||
|
|
||
| for (int i = 0; i < NUM_THREADS; ++i) { | ||
| thread_data[i].manager = &manager; | ||
| thread_data[i].thread_id = i; | ||
| pthread_create(&threads[i], nullptr, transaction_thread, &thread_data[i]); | ||
| } | ||
|
|
||
| for (int i = 0; i < NUM_THREADS; ++i) { | ||
| pthread_join(threads[i], nullptr); | ||
| } | ||
|
|
||
| EXPECT_EQ(manager.current_transaction, nullptr); | ||
|
|
||
| EXPECT_NE(manager.log_head, nullptr); | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.