| 
																	
																	
																		
																			
																		
																	
																	
																 | 
																@ -7,7 +7,10 @@ | 
															
														
														
													
														
															
																 | 
																 | 
																#include <memory>
 | 
																 | 
																 | 
																#include <memory>
 | 
															
														
														
													
														
															
																 | 
																 | 
																#include <cassert>
 | 
																 | 
																 | 
																#include <cassert>
 | 
															
														
														
													
														
															
																 | 
																 | 
																#include <optional>
 | 
																 | 
																 | 
																#include <optional>
 | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																#include <chrono>
 | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																#include <thread>
 | 
															
														
														
													
														
															
																 | 
																 | 
																
 | 
																 | 
																 | 
																
 | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																using namespace std::chrono_literals; | 
															
														
														
													
														
															
																 | 
																 | 
																/**
 | 
																 | 
																 | 
																/**
 | 
															
														
														
													
														
															
																 | 
																 | 
																Pensé en un mundo sin memoria, sin tiempo; consideré la posibilidad de un lenguaje  | 
																 | 
																 | 
																Pensé en un mundo sin memoria, sin tiempo; consideré la posibilidad de un lenguaje  | 
															
														
														
													
														
															
																 | 
																 | 
																que ignorara los sustantivos, un lenguaje de verbos impersonales y de indeclinables  | 
																 | 
																 | 
																que ignorara los sustantivos, un lenguaje de verbos impersonales y de indeclinables  | 
															
														
														
													
												
													
														
															
																| 
																	
																		
																			
																		
																	
																	
																		
																			
																		
																	
																	
																 | 
																@ -72,12 +75,88 @@ namespace mct20 { | 
															
														
														
													
														
															
																 | 
																 | 
																
 | 
																 | 
																 | 
																
 | 
															
														
														
													
														
															
																 | 
																 | 
																		template<typename K, typename V> | 
																 | 
																 | 
																		template<typename K, typename V> | 
															
														
														
													
														
															
																 | 
																 | 
																		class bucket { | 
																 | 
																 | 
																		class bucket { | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																			constexpr static uint32_t delete_mode = 65536; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																			std::atomic<uint32_t> delete_lock; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																
 | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																			void reader_lock() { | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																				while(delete_lock.fetch_add(1) >= delete_mode) { | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																					delete_lock.fetch_sub(1); | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																					std::this_thread::yield(); | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																				} | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																				return; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																			} | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																
 | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																			void writer_lock() { | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																				while(delete_lock.fetch_add(delete_mode) >= delete_mode) { | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																					delete_lock.fetch_sub(delete_mode); | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																					std::this_thread::yield(); | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																				} | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																				while(delete_lock.load() != delete_mode) { | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																				} | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																				return; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																			} | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																
 | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																			void reader_unlock() { | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																				delete_lock.fetch_sub(1); | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																			} | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																
 | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																			void writer_unlock() { | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																				delete_lock.fetch_sub(delete_mode); | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																			} | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																
 | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																			struct RGuard { | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																				bucket& master; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																				RGuard(bucket& m) | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																				: master(m) | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																				{master.reader_lock();} | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																
 | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																				~RGuard() | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																				{master.reader_unlock();} | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																			}; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																
 | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																			struct WGuard { | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																				bucket& master; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																				WGuard(bucket& m) | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																				: master(m) | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																				{master.writer_lock();} | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																
 | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																				~WGuard() | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																				{master.writer_unlock();} | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																			}; | 
															
														
														
													
														
															
																 | 
																 | 
																		public: | 
																 | 
																 | 
																		public: | 
															
														
														
													
														
															
																 | 
																 | 
																			bucket() | 
																 | 
																 | 
																			bucket() | 
															
														
														
													
														
															
																 | 
																 | 
																			: start{nullptr} | 
																 | 
																 | 
																			: start{nullptr} | 
															
														
														
													
														
															
																 | 
																 | 
																			{} | 
																 | 
																 | 
																			{} | 
															
														
														
													
														
															
																 | 
																 | 
																
 | 
																 | 
																 | 
																
 | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																			void remove(size_t hash, const K& key) { | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																				WGuard _g(*this); | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																				auto it = start.load(); | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																				auto prev = &start; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																				do{ | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																					if(it == nullptr) return; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																					while(it->contents.hash != hash) | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																					{ | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																						prev = reinterpret_cast<node_ptr*>(&(it->contents.next)); | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																						it = (node*)it->contents.next.load(); | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																						if(it == nullptr) return; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																					} | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																					if(it->contents.key == key) { | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																						prev->store(reinterpret_cast<node*>(it->contents.next.load())); | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																						it->contents.references.fetch_sub(1); | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																						while(it->contents.references.load()!=0) { | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																							std::this_thread::yield(); | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																						} | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																						delete it->contents.ptr; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																						delete it; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																						return; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																					} | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																					prev = reinterpret_cast<node_ptr*>(&(it->contents.next)); | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																					it = (node*)it->contents.next.load(); | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																				} while(true); | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																			} | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																
 | 
															
														
														
													
														
															
																 | 
																 | 
																			void push(size_t hash, const K& key, const V& value) { | 
																 | 
																 | 
																			void push(size_t hash, const K& key, const V& value) { | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																				RGuard _g(*this); | 
															
														
														
													
														
															
																 | 
																 | 
																				auto t = new node{ | 
																 | 
																 | 
																				auto t = new node{ | 
															
														
														
													
														
															
																 | 
																 | 
																					.contents = node_contents{ | 
																 | 
																 | 
																					.contents = node_contents{ | 
															
														
														
													
														
															
																 | 
																 | 
																						.key{key}, | 
																 | 
																 | 
																						.key{key}, | 
															
														
														
													
												
													
														
															
																| 
																	
																	
																	
																		
																			
																		
																	
																 | 
																@ -101,6 +180,7 @@ namespace mct20 { | 
															
														
														
													
														
															
																 | 
																 | 
																			} | 
																 | 
																 | 
																			} | 
															
														
														
													
														
															
																 | 
																 | 
																
 | 
																 | 
																 | 
																
 | 
															
														
														
													
														
															
																 | 
																 | 
																			std::optional<accessor<V>> get(const size_t hash, const K& key) { | 
																 | 
																 | 
																			std::optional<accessor<V>> get(const size_t hash, const K& key) { | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																				RGuard _g(*this); | 
															
														
														
													
														
															
																 | 
																 | 
																				auto v = start.load(); | 
																 | 
																 | 
																				auto v = start.load(); | 
															
														
														
													
														
															
																 | 
																 | 
																				while(v) { | 
																 | 
																 | 
																				while(v) { | 
															
														
														
													
														
															
																 | 
																 | 
																					if(v->contents.references.fetch_add(1)!=0) | 
																 | 
																 | 
																					if(v->contents.references.fetch_add(1)!=0) | 
															
														
														
													
												
													
														
															
																| 
																	
																		
																			
																		
																	
																	
																		
																			
																		
																	
																	
																 | 
																@ -186,6 +266,16 @@ public: | 
															
														
														
													
														
															
																 | 
																 | 
																		return; | 
																 | 
																 | 
																		return; | 
															
														
														
													
														
															
																 | 
																 | 
																	} | 
																 | 
																 | 
																	} | 
															
														
														
													
														
															
																 | 
																 | 
																
 | 
																 | 
																 | 
																
 | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																	void remove(const K& key) { | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																		const auto l = hash{}(key); | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																		auto& ref = buckets[l%bucket_count]; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																		ref.remove(l, key); | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																		const auto l2 = _details_::rotl(l, sizeof(size_t)*4); | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																		auto& ref2 = buckets[l2%bucket_count]; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																		ref2.remove(l2, key); | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																		return; | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																	} | 
															
														
														
													
														
															
																 | 
																 | 
																 | 
																 | 
																 | 
																
 | 
															
														
														
													
														
															
																 | 
																 | 
																	lfhmap() { | 
																 | 
																 | 
																	lfhmap() { | 
															
														
														
													
														
															
																 | 
																 | 
																		for(auto& a : buckets) { | 
																 | 
																 | 
																		for(auto& a : buckets) { | 
															
														
														
													
														
															
																 | 
																 | 
																			a.start = nullptr; | 
																 | 
																 | 
																			a.start = nullptr; | 
															
														
														
													
												
													
														
															
																| 
																	
																		
																			
																		
																	
																	
																	
																 | 
																
 |