One restriction I ran into today when doing some ColdFusion8 specific
performance enhancements to
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">
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
- makes a <cfthread> call, and calls C()
- Does some work…
- Calls C() from the current thread.
- 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
Thread = createObject("java", "java.lang.Thread");
Now, the Thread object, has a great method
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
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
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
if(currentThread.getThreadGroup().getName() eq "cfthread")
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"
var Thread = createObject("java",
if(Thread.currentThread().getThreadGroup().getName() eq "cfthread")
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:
// run code
// 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.