24 September 2007 12:57 PM
9 Comments
How to tell if code is being run inside a CFTHREAD tag
One restriction I ran into today when doing some ColdFusion8 specific performance enhancements to Transfer with <cfthread> is that you can't make a child thread within an already created <cfthread>, so something like:<cfthread action="run" name="a">
<cfthread action="run" name="b">
</cfthread>
</cfthread>
Will end up with lots of errors in your logs saying things like:Error","cfthread-1","09/24/07","12:03:42",,"A: Thread B cannot be created. Child threads are not supported."
Which is probably not what you actually want, as you would most likely like for you code to actually execute.
I'm not a huge fan of this limitation, but I can kind of understand where the engineers are coming from - they don't want us CF developers to shoot ourselves in the foot with ridiculously spawning multi threaded applications.
So, in my current situation, I wasn't too fussed if I had a whole, brand new thread, but where my code was being run, I was so far down the stack of method calls, I have no way of knowing if the original call had come from a standard ColdFusion thread, or if it had come from a <cfthread> create thread, and both of which were highly possible. However, if the execution wasn't coming from a <cfthread> created thread, I wanted to execute my code inside a <cfthread> statement, as I didn't care what the results where, and it would be faster for the end user just to have the code run asynchronously.
If that just made your head hurt, I basically have a series of method calls that look like:
A()
- makes a <cfthread> call, and calls C()
B()
- Does some work...
- Calls C() from the current thread.
C()
- makes a <cfthread> call, and then does some work
This is an over simplification of the process (mine is far more levels deep), but gives you an idea of the trouble I was facing - the method call could go through A() or through B(), and at the level of C() I wasn't aware of whether or not I had started on the base ColdFusion thread or not.
I could have done this passing a parameter all the way down the method chain to tell it if it should fire asynchronously, but that seemed like a lot of extra work, and would have put a level of complexity within the whole process, and any other process that was related to this, that it didn't seem like the appropriate course of action.
So I thought to myself - there has to be a way to find out if the current thread is a regular, ColdFusion thread, or if it is a <cfthread> invoked thread, and funnily enough, skipping into some Java, there is!
The first thing we have to do, is get access to the java.lang.Thread object:
Thread = createObject("java", "java.lang.Thread");
Now, the Thread object, has a great method
'currentThread()',
which returns the current thread that the executing code is on:currentThread = Thread.currentThread();
What is good to know, is that Threads in Java can exist in
ThreadGroups,
which is a handy way of grouping Threads together for common operations, and
other clever things. The nice thing here, is that ThreadGroups have a
method called
'getName()'
which returns the name of the ThreadGroup.Strangely enough, <cfthread> created threads live inside the ThreadGroup named 'cfthread'! So now we can compare this against the name of the current Thread's ThreadGroup
if(currentThread.getThreadGroup().getName() eq "cfthread")
{
//do something...
}
We can also wrap this up nicely into a quick little UDF:
<cffunction name="amInCFThread" hint="returns 'true' if the current thread is a cfthread, returns false otherwise" access="public"returntype="boolean" output="false">
<cfscript>
var Thread = createObject("java","java.lang.Thread");
if(Thread.currentThread().getThreadGroup().getName() eq "cfthread")
{
return true;
}
return false;
</cfscript>
</cffunction>
This function returns 'true' if the currently executing code is inside a
<cfthread>, and 'false' if it is not.So now, in my function C() I can have:
C()
if(amInCFThread())
{
// run code
}
else
{
// make <cfthread> and run code.
}
And continue on my merry way!Pretty handy if I'm not sure if my <cfthread>'d code will end up being run by other ColdFusion created threads or not.





