/*
 * This file declares and defines a C++ wrapper class around omp_lock_t.
 */

#ifdef ATC_OPENMP
	#include <omp.h>
#endif

namespace atc {
	
	/*
	 * This class is a C++ wrapper around the C struct omp_lock_t from OpenMP, designed to automatically and safely handle initialization and destruction, avoiding memory leaks.
	 * If ATC_OPENMP is undefined, the class methods will be empty, so this class and its methods can be used without further checks in code, even when OpenMP is disabled.
	 */
	class Lock {
	public:
	
		// First, the constructor/destructor. When OpenMP is disabled, these can all be default.
		
		#ifdef ATC_OPENMP
			// Initializes the OpenMP lock
			Lock() {
				omp_init_lock(&lock);
			}
			// Destroys the OpenMP lock
			~Lock() {
				omp_destroy_lock(&lock);
			}
		#else
			Lock() = default;
			~Lock() = default;
		#endif
		
		// The other special methods can be disabled, since copying a lock doesn't make much sense (a lock should probably be unique and not have copies laying around the program ...)
		// Move semantics make sense, but we don't need them for now so they're not implemented.
		
		Lock(const Lock& other) = delete;
		Lock& operator=(const Lock& other) = delete;
		Lock(Lock&& other) = delete;
		Lock& operator=(Lock&& other) = delete;
		
		// OpenMP wrapper functions: these need to be empty if OpenMP is disabled
		
		// Wait and set the internal lock
		void set() {
			#ifdef ATC_OPENMP
				omp_set_lock(&lock);
			#endif
		}
		// Release the internal lock
		void unset() {
			#ifdef ATC_OPENMP
				omp_unset_lock(&lock);
			#endif
		}
		
	private:
		#ifdef ATC_OPENMP
			omp_lock_t lock;
		#endif
	};
}
