Example #1
0
std::wstring get_call_stack()
{
	class log_call_stack_walker : public stack_walker
	{
		std::string str_;
	public:
		log_call_stack_walker() : stack_walker() {}

		std::string flush()
		{
			return std::move(str_);
		}
	protected:		
		virtual void OnSymInit(LPCSTR szSearchPath, DWORD symOptions, LPCSTR szUserName)
		{
		}
		virtual void OnLoadModule(LPCSTR img, LPCSTR mod, DWORD64 baseAddr, DWORD size, DWORD result, LPCSTR symType, LPCSTR pdbName, ULONGLONG fileVersion)
		{
		}
		virtual void OnDbgHelpErr(LPCSTR szFuncName, DWORD gle, DWORD64 addr)
		{
		}
		virtual void OnOutput(LPCSTR szText)
		{
			std::string str = szText;

			if(str.find("internal::get_call_stack") == std::string::npos && str.find("stack_walker::ShowCallstack") == std::string::npos)
				str_ += std::move(str);
		}
	};

	static tbb::enumerable_thread_specific<log_call_stack_walker> walkers;
	try
	{
		auto& walker = walkers.local();
		walker.ShowCallstack();
		return u16(walker.flush());
	}
	catch(...)
	{
		return L"!!!";
	}
}
Example #2
0
void DependencyNode::propagateDirtiness( Plug *plugToDirty )
{
	// we're not able to signal anything if there's no node, so just early out
	Node *node = plugToDirty->ancestor<Node>();
	if( !node )
	{
		return;
	}
	
	// we don't emit dirtiness immediately for each plug as we traverse the
	// dependency graph for two reasons :
	//
	// - we don't want to emit dirtiness for the same plug more than once
	// - we don't want to emit dirtiness while the graph may still be being
	//   rewired by slots connected to plugSetSignal() or plugInputChangedSignal()
	//
	// instead we collect all the dirty plugs in a container as we traverse
	// the graph and only when the traversal is complete do we emit the plugDirtiedSignal().
	//
	// the container used is stored per-thread as although it's illegal to be
	// monkeying with a script from multiple threads, it's perfectly legal to
	// be monkeying with a different script in each thread.
	
	DirtyPlugsContainer &dirtyPlugs = g_dirtyPlugsContainers.local();
	
	// if the container is currently empty then we are at the start of a traversal,
	// and will emit plugDirtiedSignal() and empty the container before returning
	// from this function. if the container isn't empty then we are mid-traversal
	// and will just add to it.
	const bool emit = dirtyPlugs.empty();

	Plug *p = plugToDirty;
	while( p )
	{
		dirtyPlugs.insert( p );
		p = p->parent<Plug>();
	}	
	
	// we only propagate dirtiness along leaf level plugs, because
	// they are the only plugs which can be the target of the affects(),
	// and compute() methods.
	if( !plugToDirty->isInstanceOf( (IECore::TypeId)CompoundPlugTypeId ) )
	{
		DependencyNode *dependencyNode = IECore::runTimeCast<DependencyNode>( node );
		if( dependencyNode )
		{
			AffectedPlugsContainer affected;
			dependencyNode->affects( plugToDirty, affected );
			for( AffectedPlugsContainer::const_iterator it=affected.begin(); it!=affected.end(); it++ )
			{
				if( ( *it )->isInstanceOf( (IECore::TypeId)Gaffer::CompoundPlugTypeId ) )
				{
					// DependencyNode::affects() implementations are only allowed to place leaf plugs in the outputs,
					// so we helpfully report any mistakes.
					dirtyPlugs.clear();
					throw IECore::Exception( "Non-leaf plug " + (*it)->fullName() + " cannot be returned by affects()" );
				}
				// cast is ok - AffectedPlugsContainer only holds const pointers so that
				// affects() can be const to discourage implementations from having side effects.
				propagateDirtiness( const_cast<Plug *>( *it ) );
			}
		}
	
		for( Plug::OutputContainer::const_iterator it=plugToDirty->outputs().begin(), eIt=plugToDirty->outputs().end(); it!=eIt; ++it )
		{
			propagateDirtiness( *it );
		}		
	}
	
	if( emit )
	{
		for( size_t i = 0, e = dirtyPlugs.size(); i < e; ++i )
		{
			Plug *plug = dirtyPlugs.get<1>()[i];
			Node *node = plug->node();
			if( node )
			{
				node->plugDirtiedSignal()( plug );
			}
		}
		dirtyPlugs.clear();
	}
}
Example #3
0
		static DirtyPlugs &local()
		{
			static tbb::enumerable_thread_specific<Plug::DirtyPlugs> g_dirtyPlugs;
			return g_dirtyPlugs.local();
		}