48 lines
		
	
	
	
		
			942 B
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			48 lines
		
	
	
	
		
			942 B
		
	
	
	
		
			C++
		
	
	
	
	
	
| #include <exception>
 | |
| #include <functional>
 | |
| #include <mutex>
 | |
| 
 | |
| namespace nix {
 | |
| 
 | |
| /* A helper class for lazily-initialized variables.
 | |
| 
 | |
|      Lazy<T> var([]() { return value; });
 | |
| 
 | |
|    declares a variable of type T that is initialized to 'value' (in a
 | |
|    thread-safe way) on first use, that is, when var() is first
 | |
|    called. If the initialiser code throws an exception, then all
 | |
|    subsequent calls to var() will rethrow that exception. */
 | |
| template<typename T>
 | |
| class Lazy
 | |
| {
 | |
| 
 | |
|     typedef std::function<T()> Init;
 | |
| 
 | |
|     Init init;
 | |
| 
 | |
|     std::once_flag done;
 | |
| 
 | |
|     T value;
 | |
| 
 | |
|     std::exception_ptr ex;
 | |
| 
 | |
| public:
 | |
| 
 | |
|     Lazy(Init init) : init(init)
 | |
|     { }
 | |
| 
 | |
|     const T & operator () ()
 | |
|     {
 | |
|         std::call_once(done, [&]() {
 | |
|             try {
 | |
|                 value = init();
 | |
|             } catch (...) {
 | |
|                 ex = std::current_exception();
 | |
|             }
 | |
|         });
 | |
|         if (ex) std::rethrow_exception(ex);
 | |
|         return value;
 | |
|     }
 | |
| };
 | |
| 
 | |
| }
 |