| 
						
						
							
								
							
						
						
					 | 
				
			
			 | 
			 | 
			
				@ -41,23 +41,90 @@ distribution.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				using namespace DFHack;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				namespace DFHack
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    class DFContextMgrPrivate
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    class ContextManager::Private
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        public:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            DFContextMgrPrivate(){};
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            ~DFContextMgrPrivate(){};
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            Private(){};
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            ~Private(){};
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            string xml; // path to xml
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            vector <Context *> contexts;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            ProcessEnumerator * pEnum;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    };
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				class DFHack::BadContexts::Private
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    public:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        Private(){};
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        vector <Context *> bad;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				};
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				BadContexts::BadContexts():d(new Private()){}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				ContextManager::ContextManager (const string path_to_xml) : d (new DFContextMgrPrivate())
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				BadContexts::~BadContexts()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    clear();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    delete d;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				bool BadContexts::Contains(Process* p)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    for(int i = 0; i < d->bad.size(); i++)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        if((d->bad[i])->getProcess() == p)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            return true;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    return false;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				bool BadContexts::Contains(Context* c)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    for(int i = 0; i < d->bad.size(); i++)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        if(d->bad[i] == c)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            return true;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        return false;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				uint32_t BadContexts::size()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    return d->bad.size();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				void BadContexts::clear()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    for(int i = 0; i < d->bad.size(); i++)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        // delete both Process and Context!
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        // process has to be deleted after context, because Context does some
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        // cleanup on delete (detach, etc.)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        Process * to_kill = d->bad[i]->getProcess();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        delete d->bad[i];
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        delete to_kill;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    d->bad.clear();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				void BadContexts::push_back(Context* c)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    if(c)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        d->bad.push_back(c);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				Context * BadContexts::operator[](uint32_t index)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    if(index < d->bad.size())
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        return d->bad[index];
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    return 0;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				ContextManager::ContextManager (const string path_to_xml) : d (new Private())
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    d->pEnum = 0;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    d->xml = QUOT (MEMXML_DATA_PATH);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    d->xml += "/";
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    d->xml += path_to_xml;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    d->pEnum = new ProcessEnumerator(d->xml);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				ContextManager::~ContextManager()
 | 
			
		
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
			
			 | 
			 | 
			
				@ -66,26 +133,76 @@ ContextManager::~ContextManager()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    delete d;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				uint32_t ContextManager::Refresh()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				uint32_t ContextManager::Refresh( BadContexts* bad_contexts )
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    purge();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    if(d->pEnum != 0)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        d->pEnum = new ProcessEnumerator(d->xml);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    // handle expired processes, remove stale Contexts 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        BadProcesses expired;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        // get new list od living and expired Process objects
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        d->pEnum->Refresh(&expired);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        // scan expired, kill contexts if necessary
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        vector <Context*>::iterator it = d->contexts.begin();;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        while(it != d->contexts.end())
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            Process * test = (*it)->getProcess();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            if(expired.Contains(test))
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                // ok. we have an expired context here.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                if(!bad_contexts)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    // with nowhere to put the context, we have to destroy it
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    delete *it;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    // stop tracking it and advance the iterator
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    it = d->contexts.erase(it);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    continue;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                else
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        delete d->pEnum;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        d->pEnum = new ProcessEnumerator(d->xml);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    // we stuff the context into bad_contexts
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    bad_contexts->push_back(*it);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    // stop tracking it and advance the iterator
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    it = d->contexts.erase(it);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    // remove process from the 'expired' container, it is tracked by bad_contexts now
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    // (which is responsible for freeing it).
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    expired.excise(test);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    continue;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    d->pEnum->purge();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    d->pEnum->findProcessess();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            else it++; // not expired, just advance to next one
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        // no expired contexts are in the d->contexts vector now
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        // all processes remaining in 'expired' are now destroyed along with it
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    int numProcesses = d->pEnum->size();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    int numContexts = d->contexts.size();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    vector <Context *> newContexts;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    // enumerate valid processes
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    for(int i = 0; i < numProcesses; i++)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        Process * test = d->pEnum->operator[](i);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        bool exists = false;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        // scan context vector for this process
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        for(int j = 0; j < numContexts; j++)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            if((d->contexts[j])->getProcess() == test)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                // already have that one, skip
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                exists = true;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        if(!exists)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            // new process needs a new context
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            Context * c = new Context(d->pEnum->operator[](i));
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        d->contexts.push_back(c);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            newContexts.push_back(c);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    d->contexts.insert(d->contexts.end(), newContexts.begin(), newContexts.end());
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    return d->contexts.size();
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				uint32_t ContextManager::size()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    return d->contexts.size();
 | 
			
		
		
	
	
		
			
				
					| 
						
							
								
							
						
						
						
					 | 
				
			
			 | 
			 | 
			
				
 
 |