// -*- C++ -*- (c) 2014 Vladimír Štill #include #include #include #include #include #ifndef TOOLS_COMPILE_ENV_H #define TOOLS_COMPILE_ENV_H namespace divine { namespace compile { struct Env { Env() : librariesOnly( false ), useThreads( 1 ), keepBuildDir( false ), dontLink( false ) { } virtual ~Env() = default; struct RunQueue { RunQueue( const RunQueue &o ) : _env( o._env ) { ASSERT( _env != nullptr ); } RunQueue( RunQueue &&o ) : _env( o._env ), _commands( std::move( o._commands ) ), _current( o._current.load() ) { } RunQueue() = delete; friend struct Env; void pushCompilation( std::string file, std::string flags ) { _commands.emplace_back( file, flags ); } void clear() { _commands.clear(); } int size() const { return _commands.size(); } void run( int threads = -1 ) { if ( threads <= 0 ) threads = _env->useThreads; ASSERT( _env ); int extra = threads - 1; ASSERT_LEQ( 0, extra ); _current = 0; std::vector< std::future< void > > thrs; for ( int i = 0; i < extra; ++i ) thrs.emplace_back( std::async( std::launch::async, &RunQueue::_run, this ) ); _run(); for ( auto &t : thrs ) t.get(); // get propagates exceptions clear(); } private: RunQueue( Env *env ) : _env( env ) { ASSERT( env != nullptr ); } Env *_env; std::vector< std::pair< std::string, std::string > > _commands; std::atomic< size_t > _current; void _run() { int job; while ( (job = _current.fetch_add( 1 )) < size() ) _env->compileFile( _commands[ job ].first, _commands[ job ].second ); } }; virtual void compileFile( std::string /* file */, std::string /* flags */ ) = 0; RunQueue getQueue() { return RunQueue( this ); } bool librariesOnly; std::string usePrecompiled; int useThreads; bool keepBuildDir; bool dontLink; std::vector< std::string > input; std::string output; std::string flags; std::string snapshot; std::string stdin; private: std::vector< std::string > _cwdStack; }; } } #endif // TOOLS_COMPILE_ENV_H