diff --git a/cpp/particles/lock_free_bool_array.hpp b/cpp/particles/lock_free_bool_array.hpp index 593b600679be9320789ca3d18edbb47376b2716a..bfcd48880cfc6308f63afe235f0528b1a927f68b 100644 --- a/cpp/particles/lock_free_bool_array.hpp +++ b/cpp/particles/lock_free_bool_array.hpp @@ -32,18 +32,30 @@ #include <cstdio> #include <omp.h> - class lock_free_bool_array{ static const int Available = 0; static const int Busy = 1; static const int NoOwner = -1; +#ifdef __INTEL_COMPILER + struct Locker { + Locker(){ + omp_init_nest_lock(&lock); + } + ~Locker(){ + omp_destroy_nest_lock(&lock); + } + omp_nest_lock_t lock; + }; +#else struct Locker { - Locker() : lock(Available), ownerId(NoOwner), counter(0) {} + Locker() : lock(Available), ownerId(NoOwner), counter(0) { + } std::atomic_int lock; std::atomic_int ownerId; int counter; }; +#endif std::vector<std::unique_ptr<Locker>> keys; @@ -58,27 +70,36 @@ public: #ifndef NDEBUG ~lock_free_bool_array(){ for(auto& k : keys){ +#ifdef __INTEL_COMPILER +#else assert(k->lock.load() == Available); assert(k->ownerId.load() == NoOwner); +#endif } } #endif + +#ifdef __INTEL_COMPILER + void lock(const long int inKey){ + Locker* k = keys[inKey%keys.size()].get(); + omp_set_nest_lock(&k->lock); + } + + void unlock(const long int inKey){ + Locker* k = keys[inKey%keys.size()].get(); + omp_unset_nest_lock(&k->lock); + } +#else void lock(const long int inKey){ Locker* k = keys[inKey%keys.size()].get(); if(k->ownerId.load() != omp_get_thread_num()){ int localBusy = Busy;// Intel complains if we pass a const as last param int expected = Available; -#ifdef __INTEL_COMPILER - while(!__sync_val_compare_and_swap((int*)&k->lock, expected, localBusy)){ -#else while(!std::atomic_compare_exchange_strong(&k->lock, &expected, localBusy)){ -#endif usleep(1); expected = Available; } -#ifdef __INTEL_COMPILER assert(k->ownerId.load() == NoOwner); -#endif k->ownerId.store(omp_get_thread_num()); k->counter = 0; // must remain } @@ -99,6 +120,7 @@ public: k->lock.store(Available); } } +#endif }; #endif