bool TestRenameExclusive(void) { BEGIN_TEST; for (size_t i = 0; i < kIterCount; i++) { // Test case of renaming from a single source. ASSERT_EQ(mkdir("::rename_start", 0666), 0); ASSERT_TRUE((thread_action_test<10, 1>([](void* arg) { if (rename("::rename_start", "::rename_end") == 0) { return kSuccess; } else if (errno == ENOENT) { return kFailure; } return kUnexpectedFailure; }))); ASSERT_EQ(rmdir("::rename_end"), 0); // Test case of renaming from multiple sources at once, // to a single destination std::atomic<uint32_t> ctr{0}; ASSERT_TRUE((thread_action_test<10, 1>([](void* arg) { auto ctr = reinterpret_cast<std::atomic<uint32_t>*>(arg); char start[128]; snprintf(start, sizeof(start) - 1, "::rename_start_%u", ctr->fetch_add(1)); if (mkdir(start, 0666)) { return kUnexpectedFailure; } // Give the target a child, so it cannot be overwritten as a target char child[256]; snprintf(child, sizeof(child) - 1, "%s/child", start); if (mkdir(child, 0666)) { return kUnexpectedFailure; } if (rename(start, "::rename_end") == 0) { return kSuccess; } else if (errno == ENOTEMPTY || errno == EEXIST) { return rmdir(child) == 0 && rmdir(start) == 0 ? kFailure : kUnexpectedFailure; } return kUnexpectedFailure; }, &ctr))); DIR* dir = opendir("::rename_end"); ASSERT_NONNULL(dir); struct dirent* de; while ((de = readdir(dir)) && de != nullptr) { unlinkat(dirfd(dir), de->d_name, AT_REMOVEDIR); } ASSERT_EQ(closedir(dir), 0); ASSERT_EQ(rmdir("::rename_end"), 0); } END_TEST; }
bool TestRenameOverwrite(void) { BEGIN_TEST; for (size_t i = 0; i < kIterCount; i++) { // Test case of renaming from multiple sources at once, // to a single destination std::atomic<uint32_t> ctr{0}; ASSERT_TRUE((thread_action_test<10, 10>([](void* arg) { auto ctr = reinterpret_cast<std::atomic<uint32_t>*>(arg); char start[128]; snprintf(start, sizeof(start) - 1, "::rename_start_%u", ctr->fetch_add(1)); if (mkdir(start, 0666)) { return kUnexpectedFailure; } if (rename(start, "::rename_end") == 0) { return kSuccess; } return kUnexpectedFailure; }, &ctr))); ASSERT_EQ(rmdir("::rename_end"), 0); } END_TEST; }
void ThreadPool::submitBarrier() { //Promises are not copyable, so we save a pointer and delete it later, after the barrier. auto promise = new std::promise<void>(); std::shared_future<void> future(promise->get_future()); auto counter = new std::atomic<int>(); counter->store(0); int goal = thread_count; auto barrierJob = [counter, promise, future, goal] () { int currentCounter = counter->fetch_add(1); //increment by one and get the current counter. if(currentCounter == goal-1) { //we're finished. promise->set_value(); delete promise; //we're done, this isn't needed anymore. //We got here, so we're the last one to manipulate the counter. delete counter; } else { //Otherwise, we wait for all the other barriers. future.wait(); } }; for(int i = 0; i < thread_count; i++) submitJob(barrierJob); }
void increase_member (int n) { for (int i=0; i<n; ++i) fetch_add(1); }
static void timer_diag_cb2(timer_t* timer, zx_time_t now, void* arg) { auto timer_count = static_cast<fbl::atomic<size_t>*>(arg); timer_count->fetch_add(1); thread_preempt_set_pending(); }
long long operator++(int) { return fetch_add(1); }
long long operator--(int) { return fetch_add(-1); }
__host__ __device__ int_type operator+=(int_type val) volatile { return fetch_add(val) + val; }
__host__ __device__ int_type operator++(int) volatile { return fetch_add(1); }
static inline Type fetch_sub(volatile Type& storage, Type value) { typedef typename AtomicStorageType<4, true>::Type SignedType; return fetch_add(storage, static_cast<Type>(-static_cast<SignedType>(value))); }
T operator += (add_type value) { return fetch_add(value) + value; }
T operator ++ () { return fetch_add(1) + 1; }