#include "table.h" #include #include #include #include // helper functions and variables declaration void advanceStep(int n); void waitStep(int n); void restartMeasuringTime(); double measuredTime(); _Thread_local int k, v, *p; struct table_t *myTable; void thread0(void) { table_init(&myTable, 4, 2); v = table_lookup(myTable, 0); assert(v == INVALID_VAL); table_insert(myTable, 1, 2, &v); assert(v == INVALID_VAL); v = table_lookup(myTable, 1); assert(v == 2); table_insert(myTable, 5, 3, NULL); table_insert(myTable, 9, 4, NULL); v = table_deleteKey(myTable, 1); assert(v == 2); v = table_lookup(myTable, 5); assert(v == 3); v = table_lookup(myTable, 9); assert(v == 4); v = table_lookup(myTable, 1); assert(v == INVALID_VAL); restartMeasuringTime(); advanceStep(1); v = table_awaitAndDelete(myTable, 1); assert(v == 5 && measuredTime() > 0.1); table_insert(myTable, 3, 6, NULL); table_insert(myTable, 4, 7, NULL); table_insert(myTable, 6, 8, NULL); table_insert(myTable, 12, 9, NULL); int s = 2; uint_fast16_t seenKeys = 0; #define expectedKeys (((1<<3)|(1<<4)|(1<<12)|(1<<5)|(1<<6)|(1<<9))) struct table_iterator_t *it = table_begin(myTable); while (table_next(it, &k, &p) == EXIT_SUCCESS) { advanceStep(s++); seenKeys |= 1 << k; if (k == 6) *p = 10; usleep(100000); } assert((seenKeys & expectedKeys) == expectedKeys); assert(s == 8); v = table_lookup(myTable, 6); assert(v == 10); table_destroy(myTable); } void *thread1(void *_) { waitStep(1); usleep(100000); table_insert(myTable, 1, 5, NULL); waitStep(2); v = table_lookup(myTable, 6); assert(v == 8); return NULL; } void *thread2(void *_) { waitStep(3); table_insert(myTable, 19, 10, &v); assert(v == INVALID_VAL); return NULL; } void *thread3(void *_) { waitStep(4); v = table_deleteKey(myTable, 3); assert(v == 6); return NULL; } int main() { void *(*funcs[])(void *) = {thread1, thread2, thread3}; #define count ((sizeof(funcs) / sizeof(*funcs))) pthread_t ids[count]; for (int i = 0; i < count; ++i) pthread_create(&ids[i], NULL, funcs[i], NULL); thread0(); for (int i = 0; i < count; ++i) pthread_join(ids[i], NULL); return 0; } int step; pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t c = PTHREAD_COND_INITIALIZER; void advanceStep(int n) { pthread_mutex_lock(&m); assert(n == step + 1); step = n; pthread_cond_broadcast(&c); pthread_mutex_unlock(&m); } void waitStep(int n) { pthread_mutex_lock(&m); while (step < n) pthread_cond_wait(&c, &m); pthread_mutex_unlock(&m); } _Thread_local struct timespec t; void restartMeasuringTime() { clock_gettime(CLOCK_MONOTONIC, &t); } double measuredTime() { struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now); double elapsed = now.tv_sec - t.tv_sec; elapsed += (now.tv_nsec - t.tv_nsec) / 1e9; return elapsed; }