Being Thread Safe in Coldbox/Coldfusion
Thread safe never crossed my mind. I never put CFC in the application scope to allow quicker execution (bypassing the createobject function). But now that my office has implemented ColdBox, it cache's a lot for you, including its handlers - which are CFCs. Well, we got bit by that evil words "THREAD SAFE". Our code WASN'T... yes including my code.
So what does that mean. Well I'll try to do a quick explanation, thread safe is any variable that is dedicated to a SINGLE user will NOT be shared to other users. For example, in a object a "private" variable is NOT thread safe. So if many users use the same object (implementation of a class), then we must make sure the variables being passed around are LOCAL to that function. Therefore, in a CFC (depending on language) you must force your function variables to be LOCAL to the function only.
In CF8 use of the VAR keyword provides this
<cfset var myLocalVar = "" />
In CF9 the use of the scope LOCAL provides this
<cfset local.mylocalvar="" />
So for those of us still on CF8, i recommend using the following.
<cfset local=StructNew() />
<cfset var local=StructNew() /> *reader Jason found mistake in my post*
and then the rest of the code you can use
<cfset local.myLocalVar = "" />
without using the VAR keyword.
Also, as Sean Corfield commented below, using this methodology will NOT cause conflict with CF9 local scope.
Also, here is another blog post on the subject
So what does that mean. Well I'll try to do a quick explanation, thread safe is any variable that is dedicated to a SINGLE user will NOT be shared to other users. For example, in a object a "private" variable is NOT thread safe. So if many users use the same object (implementation of a class), then we must make sure the variables being passed around are LOCAL to that function. Therefore, in a CFC (depending on language) you must force your function variables to be LOCAL to the function only.
In CF8 use of the VAR keyword provides this
<cfset var myLocalVar = "" />
In CF9 the use of the scope LOCAL provides this
<cfset local.mylocalvar="" />
So for those of us still on CF8, i recommend using the following.
<cfset var local=StructNew() /> *reader Jason found mistake in my post*
and then the rest of the code you can use
<cfset local.myLocalVar = "" />
without using the VAR keyword.
Also, as Sean Corfield commented below, using this methodology will NOT cause conflict with CF9 local scope.
Also, here is another blog post on the subject
Good simplification for us CF8 users as well as a way to start writing forward-compatible code.
ReplyDeleteTwo comments on the topic:
The struct "local" will still need to be var'd to make it local to the thread/function. Otherwise, it will be called "local" but not local across threads. See your last paragraph - I think your example should be: "cfset var local=structnew()" Can't seem to insert the brackets - thanks blogger! :(
In addition, declaring the "local" variable outside of a cffunction will probably cause variable collisions across functions as we tend to use similar naming conventions (ie loop indexes, etc.). I'm supposing you don't mean doing that, as you stated to put the "local" declaration within the cffunction?
Also, any restrictions/conflicts with the CF9 "local"? Will declaring "local" as structnew() or var'ing it in a cffunction throw an error in CF9 since the local scope is already implicit?
CF9 will simply ignore cfset var local = structNew() so it's safe to use in both CF8 and CF9 and Railo.
ReplyDeleteCF8 requires all var declarations at the top of the function. Railo has allowed var declarations anywhere in a function for quite some time. CF9 now allows var declarations anywhere as well.
great 2 comments... those 2 points were suppose to be in the original blog post. I'm going back in now to edit. :-\
ReplyDeleteJason, I was not intending for the local scope to be defined outside the cffunction tag... I did mean to use the VAR decleration!
ReplyDelete