<commit_before>#include "asyncwatcher.h"

size_t AsyncWatcher::insert(std::atomic_flag* flag, std::function<void()> func) {
	bool stahp = stop();
	auto it = std::find_if(triggers.begin(),triggers.end(),
		[flag](const decltype(*triggers.begin())& v)->bool {return v.first == flag;});
	size_t retval;
	if(it != triggers.end()) {
		it->second.push_back(func);
		retval = std::distance(triggers.begin(),it);
	}
	else {
		retval = triggers.size();
		triggers.emplace_back(flag,std::vector<decltype(func)>({func}));
	}
	if(stahp)
		run();
	return retval;
}

bool AsyncWatcher::erase(std::atomic_flag* flag, size_t first, size_t last) {
	bool stahp = stop();
	auto it = std::find_if(triggers.begin(),triggers.end(),
		[flag](const decltype(*triggers.begin())& v)->bool {return v.first == flag;});
	if(it != triggers.end()) {
		first = first>it->second.size()?it->second.size():first;
		last = last>it->second.size()?it->second.size():last;
		it->second.erase(it->second.begin()+first,it->second.end()-last);
		bool cleared = false;
		if(it->second.empty()) {
			triggers.erase(it);
			cleared = true;
		}
		if(stahp)
			run();
		return cleared;
	} else if(stahp)
		run();
	return true;
}

size_t AsyncWatcher::count(std::atomic_flag* flag) const {
	auto it = std::find_if(triggers.begin(),triggers.end(),
		[flag](const decltype(*triggers.begin())& v)->bool {return v.first == flag;});
	if(it != triggers.end())
		return it->second.size();
	return 0;

}
void AsyncWatcher::run() {
	runFlag.test_and_set();
	runner = std::move(std::thread([this]{
		do {
			for(auto& elem : triggers) {
				if(!elem.first->test_and_set()) {
					for(auto& e : elem.second)
						e();
					std::this_thread::yield();
				}
			}
			std::this_thread::yield();
		} while(runFlag.test_and_set());
	}));
}

bool AsyncWatcher::stop() {
	bool retval = runFlag.test_and_set();
	runFlag.clear();
	if(retval)
		runner.join();
	return retval;<commit_msg>joinable() is actually checked now in asyncwatcher.<commit_after>#include "asyncwatcher.h"

size_t AsyncWatcher::insert(std::atomic_flag* flag, std::function<void()> func) {
	bool stahp = stop();
	auto it = std::find_if(triggers.begin(),triggers.end(),
		[flag](const decltype(*triggers.begin())& v)->bool {return v.first == flag;});
	size_t retval;
	if(it != triggers.end()) {
		it->second.push_back(func);
		retval = std::distance(triggers.begin(),it);
	}
	else {
		retval = triggers.size();
		triggers.emplace_back(flag,std::vector<decltype(func)>({func}));
		flag->test_and_set();
	}
	if(stahp)
		run();
	return retval;
}

bool AsyncWatcher::erase(std::atomic_flag* flag, size_t first, size_t last) {
	bool stahp = stop();
	auto it = std::find_if(triggers.begin(),triggers.end(),
		[flag](const decltype(*triggers.begin())& v)->bool {return v.first == flag;});
	if(it != triggers.end()) {
		first = first>it->second.size()?it->second.size():first;
		last = last>it->second.size()?it->second.size():last;
		it->second.erase(it->second.begin()+first,it->second.end()-last);
		bool cleared = false;
		if(it->second.empty()) {
			triggers.erase(it);
			cleared = true;
		}
		if(stahp)
			run();
		return cleared;
	} else if(stahp)
		run();
	return true;
}

size_t AsyncWatcher::count(std::atomic_flag* flag) const {
	auto it = std::find_if(triggers.begin(),triggers.end(),
		[flag](const decltype(*triggers.begin())& v)->bool {return v.first == flag;});
	if(it != triggers.end())
		return it->second.size();
	return 0;

}
void AsyncWatcher::run() {
	runFlag.test_and_set();
	runner = std::move(std::thread([this]{
		do {
			for(auto& elem : triggers) {
				if(!elem.first->test_and_set()) {
					for(auto& e : elem.second)
						e();
					std::this_thread::yield();
				}
			}
			std::this_thread::yield();
		} while(runFlag.test_and_set());
	}));
}

bool AsyncWatcher::stop() {
	bool retval = runFlag.test_and_set();
	runFlag.clear();
	if(retval && runner.joinable())
		runner.join();
	return retval;
{'fraction_non_alphanumeric': 0.2054095432508293, 'fraction_numerical': 0.0005103342689461597, 'mean_word_length': 4.790251107828656, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 40, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3058719', 'n_tokens_mistral': 1585, 'n_tokens_neox': 1476, 'n_words': 251}