Blame utils.h

71057f
#ifndef UTILS_H
71057f
#define UTILS_H
71057f
71057f
71057f
#include <cassert></cassert>
51b3f0
#include <cstdio></cstdio>
71057f
71057f
#include <atomic></atomic>
71057f
#include <thread></thread>
51b3f0
#include <chrono></chrono>
51b3f0
51b3f0
51b3f0
#define ShowDebugMSG(...) do { \
51b3f0
	printf("DEBUG %10ld %s:%s:%d:", \
51b3f0
		std::chrono::duration_cast<std::chrono::milliseconds>( \</std::chrono::milliseconds>
51b3f0
			std::chrono::steady_clock::now().time_since_epoch() ).count(), \
51b3f0
		__FILE__, __func__, __LINE__); \
51b3f0
	printf(" " __VA_ARGS__); \
51b3f0
	printf("\n"); \
51b3f0
	fflush(stdout); \
51b3f0
} while(0)
51b3f0
51b3f0
#define HideDebugMSG(...) do {} while(0)
51b3f0
71057f
71057f
71057f
class ReadProtector {
71057f
private:
71057f
	std::atomic<int> enters;</int>
71057f
	std::atomic<int> exits;</int>
71057f
	
71057f
public:
71057f
	inline ReadProtector(): enters(0), exits(0) { }
71057f
	inline ~ReadProtector() { assert(!(enters - exits)); }
71057f
	inline void lock() { enters++; }
71057f
	inline void unlock() { exits++; }
71057f
	inline void wait() const {
71057f
		int en = enters;
71057f
		while(en - exits > 0) std::this_thread::yield();
71057f
	}
71057f
};
71057f
71057f
71057f
class ReadLock {
71057f
private:
71057f
	ReadProtector &protector;
71057f
	ReadLock(const ReadLock&) = delete;
71057f
public:
71057f
	inline explicit ReadLock(ReadProtector &protector): protector(protector) { protector.lock(); }
71057f
	inline ~ReadLock() { protector.unlock(); }
71057f
};
71057f
71057f
71057f
71057f
71057f
template<typename t*="" t,="" t::*nextfield=""></typename>
71057f
class ChainFuncs {
71057f
private:
71057f
	ChainFuncs() { }
71057f
71057f
public:
71057f
	typedef T Type;
71057f
	static constexpr Type* Type::*Next = NextField;
71057f
	
71057f
	static inline void push(Type* &first, Type &item)
71057f
		{ assert(!(item.*Next)); item.*Next = first; first = &item; }
71057f
	static inline void push(std::atomic<type*> &first, Type &item)</type*>
71057f
		{ assert(!(item.*Next)); item.*Next = first; while(!first.compare_exchange_weak(item.*Next, &item)); }
71057f
	
71057f
	static inline Type* pop(Type* &first) {
71057f
		Type *item = first;
71057f
		if (!item) return nullptr;
71057f
		first = item->next;
71057f
		item->next = nullptr;
71057f
		return item;
71057f
	}
71057f
	static inline Type* pop(std::atomic<type*> &first) {</type*>
71057f
		Type *item = first;
71057f
		do {
71057f
			if (!item) return nullptr;
71057f
		} while(!first.compare_exchange_weak(item, item->*Next));
71057f
		item->next = nullptr;
71057f
		return item;
71057f
	}
71057f
	
71057f
	static inline void invert(Type* &first) {
71057f
		if (Type *curr = first) {
71057f
			Type *prev = nullptr;
71057f
			while(Type *next = curr->*Next)
71057f
				{ curr->*Next = prev; prev = curr; curr = next; }
71057f
			first = curr;
71057f
		}
71057f
	}
71057f
	static inline Type* inverted(Type *first)
71057f
		{ invert(first); return first; }
71057f
};
71057f
71057f
71057f
// multhreaded input, single threaded output
71057f
// simultaneus read and write are allowed
71057f
template<typename t*="" t,="" t::*nextfield=""></typename>
71057f
class QueueMISO {
71057f
public:
71057f
	typedef T Type;
71057f
	typedef ChainFuncs<type, nextfield=""> Funcs;</type,>
71057f
	static constexpr Type* Type::*Next = NextField;
71057f
	
71057f
private:
71057f
	std::atomic<type*> pushed;</type*>
71057f
	Type *first;
71057f
	
71057f
public:
71057f
	inline QueueMISO():
71057f
		pushed(nullptr), first() { }
71057f
	inline ~QueueMISO()
71057f
		{ assert(!pushed && !first); }
71057f
	inline void push(Type &item)
71057f
		{ Funcs::push(pushed, item); }
71057f
	inline Type& pop()
71057f
		{ assert(first); return *Funcs::pop(first); }
71057f
	inline void unpop(Type &item)
71057f
		{ return Funcs::push(first, item); }
71057f
	inline Type *peek()
71057f
		{ return first ? first : (first = Funcs::inverted(pushed.exchange(nullptr))); }
71057f
};
71057f
71057f
71057f
template<typename t*="" t,="" t::*nextfield=""></typename>
71057f
class CounteredQueueMISO: public QueueMISO<t, nextfield=""> {</t,>
71057f
public:
71057f
	typedef T Type;
71057f
	typedef QueueMISO<type, nextfield=""> Queue;</type,>
71057f
	
71057f
private:
71057f
	std::atomic<int> counter;</int>
71057f
	
71057f
public:
71057f
	inline CounteredQueueMISO():
71057f
		counter(0) { }
71057f
	inline ~CounteredQueueMISO()
71057f
		{ assert(!counter); }
71057f
	inline void push(Type &item)
71057f
		{ Queue::push(item); counter++; }
71057f
	inline Type& pop()
6ebd3b
		{ Type &item = Queue::pop(); counter--; return item; }
6ebd3b
	inline void unpop(Type &item)
6ebd3b
		{ return Queue::unpop(item); counter++; }
71057f
	inline int count() const
71057f
		{ return counter; }
71057f
};
71057f
71057f
71057f
#endif