Do variables inside Application.cfc functions need scoping? - coldfusion

Question for the crowd. We are very strict on our team about scoping local variables inside functions in our CFC's. Recently though the question of scoping variables inside Application.cfc came up. Are unscoped variables in functions like onRequestStart() at the same risk for being accessed by other sessions running concurrently as we know that local variables in functions in other components are? Or are they somehow treated differently because of the nature of the functions in Application.cfc?

Your question borders on two entirely separate questions (both of which are important to clarify and address). These two questions are:
Should I scope my variables correctly when referring to them (ie. APPLICATION.settings vs. SESSION.settings).
The short answer to this is: Yes. It makes for cleaner, more readable / managable code, and prevents variable scope clashes that you may encounter later when variable names are re-used.
If you create APPLICATION.settings and SESSION.settings, but attempt to refer to them without scope (ie. <cfset myvar = settings />), you're going to have variable clash issues, as they'll be poured into VARIABLES by default--since neither APPLICATION nor SESSION are examined to resolve scope ambiguity.
The second question is:
Should I be worried about variables that are accessed in Application.cfc that could be potentially be shared by multiple users in a concurrent environment?
The short answer to this is: Yes. You should know & understand the ramifications of how your shared variables are accessed, and <CFLOCK> them where appropriate.
Unfortunately, exactly when and where you lock your shared variables is often never clarified to the CF community, so let me sum it up:
onApplicationStart() single-threads access to the APPLICATION scope. You do not need to lock APPLICATION vars that are read/written within this method.
onSessionStart() single-threads access to the SESSION scope. Same answer as before.
If you provide any kind of mechanism that accesses SESSION or APPLICATION from within the onRequestStart() method--or any other template afterwards (such as a URL reload parameter that directly calls onApplicationStart() )--all bets are off--you must now properly handle the locking of your shared variable reads and writes.

Related

Are global variables constantly updated

I know global variables are bad, however I have a checksettings function which is run every tick. http://pastebin.com/54yp4vuW The paste bin contains some of the check setting function. Before I added the GetPrivateProfileIntA everything worked fine. Now when I run it, it lags like hell. I can only assume this is because it is constantly loading the files. So my question is, are global variables constantly updated. (ie if I put this in global var will it stop the lag)
Thanks :)
Assuming I'm interpreting your question correctly, then no, global variables are not constantly updated unless you explicitly do so in code. So yes, putting those calls in global variables will get rid of the lag.
You haven't provided any details about the design but globals are visible across the entire application and get updated when they are written into.
Multiple processes/threads reading that global variable would then read the same updated value.
But synchronizing reads/writes requires the use of synchronization mechanisms such as mutexes, condition variables etc etc.
In your case you need to decide when to call GetPrivateProfileIntA() for all those settings.
Are all those settings constantly updated or only a fraction of those? Identify the ones which need to be monitored periodically and only load those.
And if a setting is stateful meaning all objects of the class refer to a single copy of the setting then I would use static class variables instead of plain global variables.
Alternately you could make a JIT call to GetPrivateProfileIntA() where needed and not bother about storing the setting in a global variable.

the variable with the same name in multi threads environment

I have a Class File. I created two threads A and B. In A and B, each thread, I create an auto varible File myfile. And then A and B will operate it. Is that secure? Will it lead to the inconsistent of data?
From the pure memory ressource perspective, it will depend on the scope of your File variables :
If they are local function variables, you are good to go. Each thread of execution owns it own stack, totally separate from other threads, where it create local variables.
If they are static, you are referring to the same global address.
From the file access perspective, it will depends if it is the same file, and if you are writing to it or not.
No, that shouldn't be a problem, simply because each instance of your thread has it's own instance of the variable.
Examine the addresses of the variables to be sure, if they differ (which they will if I understand you correctly), you're fine.
Inconsistencies between threads will only occur, if two threads concurrently access the same variable. Not just 'the same name', but really the same variable.
Now, if the variable was global and both threads were to access it, you'd need some sort of mutual exclusion to prevent data corruption, but auto-variables are safe.
The variables will be distint from each other as each thread will have its own stack, and each instance of the variable will live on that stack.
However, it sounds like you're accessing an underlying filesystem file. If it's the same file and one or both of the threads are writing to the file then this may cause data consistency issues. You'll need to consult the documentation for your operating system to see what it says. If both threads are just reading from the same file then you'll be fine.

coldfusion CFM Variables scope

I have previously asked a question regarding cf scopes on cfm pages (happy that I understand CFC scopes and potential issues), but am still not clear on the variables scope.
In the answers to my previous question, it was suggested that there are no thread safety issues using cfm pages, and you won't get the scenario where two different users access the same page and have race conditions or thread safety probs (even if I just leave my variables in the default cfm variables scope, and that the variables scope for each user will be isolated and independent (here is my last question Coldfusion Scopes Clarification)
However, I have read this blog post http://blog.alexkyprianou.com/2010/09/20/variables-scope-in-coldfusion/ regarding the use of functions on a cfm page and using the variables scope and that seems to suggest a scenario whereby the variables scope is shared between multiple users (I understand this problem in the context of CFCs - them being more akin to java classes and the variables scope being instance variables, so has thread safety issues if the CFC is shared/application scope/singleton) but this seems counter to previous answers - if a variable put in the variables scope by a function on a cfm page can be accessed by other users, then surely variables placed in variables scope directly in cfm page code is the same?
I was hoping for some clear docs and guides but have not really been able to find definitive explanations of the different scopes and where they are available.
Thanks!
Dan is correct, and the blog article being referenced in the question is simply wrong. Dan's code demonstrates it, and I have written-up and tested this thoroughly on my blog (it was too big to go here).
The bottom line is the variables scope in a CFM is safe from this sort of race condition because the variables scope for each request is different memory. So one variables.foo is not the same as the other variables.foo, so neither ever intersect.
The same applies to objects in the variables scope: their internal variables scope is a distinct entity, so any number of requests can instantiate a CFC in the request's variables scope, and the CFC instances' variables scopes are all discrete entities too.
The only time the variables scope can participate in a race condition is the variables scope of an object stored in a shared scope. Because all references to that shared-scope object will be referencing the same object in memory, so the same object's variables scope in memory.
Functions outside of a CFC accessing the variables scope won't have thread safety issues when 2 requests run the code, but if you use cfthread or other parallel features, you could still have problems with the variables scope being changed and this can cause race conditions. Often this mistake can occur with a variable you use a lot like maybe in a for loop, the "i" variable.
for(i=1;i<10;i++){t=arr[i]; }
But then another function does this while the first is running:
for(i=1;i<20;i++){t=arr[i]; }
The "i" variable needs to become a local variable to help make it thread-safe. You don't want the first loop to be able to go above 10 by mistake and this is hard to debug many times. I had to fix a ton of "i" variables and others to make my functions thread-safe everywhere when I started caching objects and using cfthread more extensively.
You can also avoid needing to lock by never changing existing objects. You can instead to the work on copies of them. This makes the data "immutable". CFML doesn't have official support for making immutable objects more efficiently, but you can make copies easily.
http://en.wikipedia.org/wiki/Immutable_object
Simple example of thread safe change to an application scope variable:
var temp=structnew();
// build complete object
temp.myValue=true;
// set complete object to application scope variable
application.myObject=temp;
Writing to any shared object is often dangerous since variables may be undefined or partially constructed. I always construct the complete object and set it to the shared variable at the end like the example above. This makes thread-safety easy if it isn't too expensive to re-create the data. The variables scope in CFC is similar to private member variables in other languages. If you modify data in shared objects, you'd might to use CFLOCK if you can't make copies instead.
Some of the confusion about coldfusion scopes is related to shared scopes in coldfusion 5 and earlier being less reliable. They had serious thread safety problems that could cause data corruption or crashes. Two threads were in certain conditions able to write to the same memory at the same time if you didn't lock correctly. Current CFML engines are able to write to struct keys without the chance of corruption / crashes. You just can't be sure which data will be actually end up as the value without some consideration of thread-safety now, but it generally won't become corrupted unless you are dealing with non-cfml object types like CFX, Java and others. A thread-safety mistake could still lead to an infinite loop which could hang the request until it times out, but it shouldn't crash unless it ran out of memory.
I think the blog is misleading. However, if you want to see for yourself, write a page with his function. Make it look something like this.
<cffunction name="test" returntype="void">
<cfscript>
foo = now();
sleep(3 * 60 * 1000); // should be 3 minutes
writedump(foo);
</cfscript>
<cffunction>
<cfdump var="#now()#">
<cfset test()>
Run the page. During the 3 minutes, open another browser or tab and run it again. Go back to where you first ran it and wait for the results. If there is no significant difference between the two outputs, then your second page request did not affect your first one.
Note that I have not tried it myself but my bet would be on the 2nd request not affecting the first one.

Parallelizing a library with lots of global variables

I'm currently using QT (4) to parallelize a non-threadsafe library that's written in C by non-programmers, and thus has a lot of global variables. The threads don't need to interact or share data, they each just call a bunch of methods of the library and then at the end the library gives an output that is used further.
The problem is, though, that global variables are per default shared between threads, causing the library to crash in different places. There are two ways to fix this:
Refactor the entire library to not use global variables (ouch), or find a way to make global variables non-shared, or find a third magic way.
Is the latter an option with QT or standard (C++01) C++?
Using thread local storage is a way to make global variables non-shared. Starting point for that, with links to details for different implementations:
http://en.wikipedia.org/wiki/Thread-local_storage
You can't "unshare" global variables. The only available option for parallelization (bar refactoring) is to have multiple processes instead of multiple threads. Preferably pooled.
Create a singleton that is responsible for synchronizing the access to the global variables. The global variables become members of the new singleton class and can be accessed by methods that have the same names as your current global variables so you don't need to change code all over the place.

In ColdFusion, variables are resolved in what order?

I have little impression about variables resolve order, but I can't find it in the CFML Reference or ColdFusion Dev Guide. Can anyone help?
Scope Order
The canonical scope order for ColdFusion 9 is:
Local (only inside CFCs and UDFs)
Arguments (only inside CFCs and UDFs)
Thread local (only inside threads)
Query (only inside a query loop)
Thread (only inside threads and templates that call threads)
Variables
CGI
Cffile
URL
Form
Cookie
Client
You can see Adobe's documentation on this in Developing ColdFusion 9 Applications.
However, some scopes are only available in certain contexts, so the order that scopes are searched is different, depending upon the context of the code.
Inside CFML (no threads)
Variables
CGI
Cffile
URL
Form
Cookie
Client
Inside a CFC (no threads)
Local
Arguments
Query (only inside a query loop)
Variables
CGI
Cffile
URL
Form
Cookie
Client
Best Practice
As Al Everett notes in his answer, it is considered best practice to always scope variables. Explicit scoping produces less ambiguous code and is usually faster. Anytime you don't scope a variable, you risk getting a variable from a scope that you didn't intend to.
When the variable you are accessing is in the first scope in the search order, it is actually slightly faster to leave the variable un-scoped. This is because each dot in a variable name incurs a small cost as ColdFusion resolves it. For example, in a CFC method it is slightly faster to access myVar than local.myVar. This only applies to:
local scoped variables inside a CFC or UDF
Thread local scoped variables inside a thread
variables scoped variables inside CFML
In all other circumstances it is faster (and clearer) to explicitly declare the scope.
Use of this technique should be considered bad practice. You should only use this technique in performance-critical code, where you can guarantee that the variable always exists in the intended scope. Keep in mind that it comes at the cost of increased ambiguity.
It is a generally accepted best practice to always scope your variables for two main reasons:
Performance - CF doesn't need to find the variable by searching through the scopes in turn
Accuracy - if two variables have the same name in different scopes, you may not get the one you were expecting
That said, here's the order variable scopes are searched:
Function local (VAR keyword)
Thread local (CFTHREAD)
Query results
Function ARGUMENTS
Local VARIABLES
CGI variables
FILE variables
URL parameters
FORM fields
COOKIE values
CLIENT variables
EDIT: It's also telling to note what scopes are not searched: SESSION, SERVER, APPLICATION