Ben Nadel
On User Experience (UX) Design, JavaScript, ColdFusion, Node.js, Life, and Love.
I am the chief technical officer at InVision App, Inc - a prototyping and collaboration platform for designers, built by designers. I also rock out in JavaScript and ColdFusion 24x7.
Meanwhile on Twitter
Loading latest tweet...
Ben Nadel at CFinNC 2009 (Raleigh, North Carolina) with:

ColdFusion CFThread Tag Body Executes As A Function Call

By Ben Nadel on
Tags: ColdFusion

A few years ago at CFUNITED, I was talking to Rupesh Kumar about the new CFThread features he built into ColdFusion 8. In the conversation (which may have been a presentation), Rupesh mentioned that the CFThread tag body actually executes as a function call. At the time, I didn't put much thought into that; but, with ColdFusion 9's new implicit LOCAL scope for function execution, I thought it might be time to play around a bit.

After trying a few CFDump and CFSet calls, I was quickly able to confirm that CFThread does, in fact, execute as a function call, complete with an arguments scope and the implicit local scope. Here is the test code that I ran:

  • <!--- Launch a parallel thread. --->
  • <cfthread
  • name="localTest"
  • action="run"
  • girl="Tricia">
  •  
  • <!---
  • The GIRL attribute is actually passed as part of the
  • Attributes collection.
  • --->
  • <cfset thread.attributesGirl = attributes.girl />
  •  
  • <!---
  • The Attributes collection is actually passed as an
  • argument to this thread Function. As such, we can access
  • it via the arguments.
  • --->
  • <cfset thread.argumentsGirl = arguments.attributes.girl />
  •  
  • <!---
  • Both the attributes are arguments are actually part of
  • the implicit LOCAL scope now part of the ColdFusion
  • scope collection.
  • --->
  • <cfset thread.localGirl = local.attributes.girl />
  •  
  • <!---
  • Because this is actually a function call, we can use
  • the new CF9 function to get the hidden name of the
  • thread function.
  • --->
  • <cfset thread.calledName = getFunctionCalledName() />
  •  
  • </cfthread>
  •  
  •  
  • <!--- Join the thread so we can examine it. --->
  • <cfthread action="join" />
  •  
  •  
  • <!--- Output the thread object. --->
  • <cfdump
  • var="#cfthread.localTest#"
  • label="Thread Local"
  • />

As you can see, I am testing the existence and functionality of the attributes scope, arguments scope, and local scope as well as the use of ColdFusion 9's new method, getFunctionCalledName(). When running the code above and rejoining the thread, we get the following CFDump output (I have hidden the irrelevant properties):

 
 
 
 
 
 
ColdFusion's CFThread Tag Body Executes As A Function Call. 
 
 
 

As you can see, I was able to access the name, "Tricia," using the attributes, arguments, and local scopes.

This seems like one of this things that is interesting, but entirely not useful in any practical sense. Even knowing this, I don't think there is any way in which I would change the way I currently code my CFThread tags. Even the use of the local scope appears to be unnecessary - non-scoped values are automatically placed into the implicit local scope whether or not the VAR keyword is used during variable definition. Actually, that's probably the most interesting part of this exploration - in a standard function, non-var'd variables are placed, by default, into the page's Variables scope, not the function local scope; so, in this respect, CFThread functions behave different that standard ColdFusion functions.




Reader Comments

Makes sense -- multithreading in most operating system-level programming languages (C, Perl, etc) is generally done with functions:

Perl: new Thread \&subroutine;
C++ with pthreads: pthread_create(info, attr, function, funargs);

Some languages want you to create an entirely new class just for the thread. Java's built-in threading (java.lang.thread) is one example of this, as are Python and the Boost library for C++.

Java:
class MyThread extends Thread { ... }
MyThread thread = new MyThread(args);
thread.start();

You can see from the Java example, even though it's an entire class, you still pass in arguments just like you would a regular function (albeit in the ctor).

But ... to get around the fact that you can write non-OO CF code and still use threads, I'd imagine that the internals for cfthread work like so:

1. Parser/compiler sees a cfthread and:
a. Silently bundles it inside a function wrapper, with arguments for the current page context, etc.
b. Inserts a stub class that takes, as an argument, the unique name of the wrapped function. This stub class extends Thread or implements Runnable (another way to do threads in Java, but very similar).
2. The JVM hits the stub class and runs it as a thread, which in turn calls out to the wrapped CF code, giving it a page context, etc. This stub could also be the watchdog function that will kill a thread if it hits its timeout, or if you pause or stop the thread, etc.

It's total speculation, and they could have gone in an entirely different direction, but that's how it works in my head.

Reply to this Comment

@Rick,

Sounds cool - you have a much more diverse programming background that me, so I will just take that as fact. The one thing that seems to be special about the Thread functions is that the "non-scoped" default memory space is the Local scope, where as in the rest of ColdFusion, it is the Variables scope. Unless, of course, they are some how invoking the method with the "local" scope being its bound-scope as well.

I am not sure how the thread has access to the Variables scope, however; it is not being passed as part of the arguments collection. The whole binding behind threads is very fascinating.

Reply to this Comment

Post A Comment

You — Get Out Of My Dreams, Get Into My Comments
Live in the Now
Oops!
Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.