I've been doing great with my JS self-training. I'm stoked since I finally learned functions, and, or, calling functions, etc. I'm even excited because I sorted everything by user editable variables, non user variables, and created functions for everything else. So I have a question I'm trying to figure out. I am adding error codes to all my editable variables. My reasoning is that I know I won't always be in this position, job, life, etc, so I want to make sure that if someone new comes along, they will be able to edit and go. If they put alskjdfl where a 1, 2 or 3 should go, I'd like to return an error. I'm nerding out and adding my own error numbers for fun. Then if the user is smart enough they can view source on the JS code and see my notes as to why the error is displaying. Oh by the way, this is all internal documents, so I'm not worried about the web.
Below is the code. Basically, if I go to the variable and put in an alphabet character or some characters alsdfjlkjsdaf, it will break the page. I'm trying to find a way that says, if there is something in there beside 1-3, then set the speed to 1 and give an error. My attempts at this have failed so far because no matter what I put in there, it still breaks the page once a character is listed. I thought the name of the function seemed appropriate. :)
This is for a scrolling bar. It displays text information as well as work related things and a clock. It's embedded within an iframe.
/* Start speedlimit code - This code ensures speed won't be faster than 3. */
function speedLimitSet()
{
if ((speedSet !== 1) && (speedSet !== 2) && (speedSet !== 3))
{
speedSet = 1
//error code 1003
alert("Error Code 1003 - speedSet - Please change speed to 3 or less. This pop up will continue to pop up otherwise. Speed limit is set to 3 or less.")
}
}
//end speedlimit code
Edit:
/* Quality check for turnOffcrawler. It has to be typed as "Yes" or "No" else will error. */
function crawlerSwitch()
{
if (turnOffcrawler == "No") /* Code for general message is included in here. It looks long but it is spaced out. */
{
width = "1000px";
speed = speedSet;
errorFlag1000 = "No";
}
else if (turnOffcrawler == "Yes")
{
width = "0px";
speed = 0;
errorFlag1000 = "No";
}
else
{
width = "1000px";
speed = speedSet
errorFlag1000 = "Yes"
importantMessageError = "Error Code 1000 - turnOffcrawler is not set correctly. Please check settings and/or refer to instructions.       Error Code 1000 - turnoffcrawler is not set correctly. Please check settings and/or refer to instructions."
}
}
//end quality check
Which then links to:
function marqueeInitCall()
{
marqueeInit({
uniqueid: 'mycrawler',
style: {
'padding': '0px',
'width': width, //change to 1000 for normal, change to 0 for off
'background': scrollerBackground, //#00008B is background of menu bar
'border': '0px solid black'
},
inc: speed, //speed - pixel increment for each iteration of this marquee's movement
mouse: mouse, //mouseover behavior ('pause' 'cursor driven' or false)
moveatleast: 1,
neutral: 150,
savedirection: true
});
}
A couple of problems with that code:
You're not declaring any arguments. I'm guessing speedSet was meant to be an argument to the function?
You're using !== which is correct if you know that what you're being passed is already a number, not a numeric string. If you don't know that, you want to parse it first.
I probably wouldn't check against all three values individually, but that might be a style thing.
It's not saving the resulting value anywhere (so maybe my #1 is wrong). If speedSet is a global variable and this function is just validating its value, I'd recommend not using global variables.
so:
/* Start speedlimit code - This code ensures speed won't be faster than 3. */
function speedLimitSet(speedSet)
{
speedSet = parseInt(speedSet, 10); // Now it's a number or `NaN`
if (isNaN(speedSet) || speedSet < 1 || speedSet > 3)
{
speedSet = 1;
//error code 1003
alert("Error Code 1003 - speedSet - Please change speed to 3 or less. This pop up will continue to pop up otherwise. Speed limit is set to 3 or less.")
}
// Save it somewhere appropriate here
}
//end speedlimit code
Other items of note:
Indenting your code makes a huge difference to readability. Note how I've indented the code above.
Although JavaScript has the horror that is automatic semicolon insertion, my humble advice is never rely on it, always put in all of the necessary semicolons. (You needed one after speedSet = 1.)
alert isn't a great way to deal with programming errors. Recommend throwing an exception and handling it at a higher level in the code.
You're free to do what you like with your function names, but the convention for setter functions is usually setXyz (e.g., setSpeedLimit rather than speedLimitSet).
Related
I am making a simple JS program and am having some trouble. You can view it here
http://codepen.io/TheAndersMan/pen/mOGVEy?editors=0010
Enter in your name and press enter, it will animate your name, but the letters disappear after the animation, which is understandable. what I don't understand is why my setTimeout isn't working and making them re-appear.
So here is the basic problem:
var timeOut = (a / 2 + 1) * 1000;
document.querySelector(".spanWrap").style.width = char.length * 60 + "px";
setTimeout(function() {
thang.style.opacity = "1"
thang.style.marginTop = "0";
}, timeOut);
So hopefully that is all the info you will need, if not reference my pen, this is all in a for loop and if you see undefined variables here, they are defined in my pen.
So if someone can tell me what I did wrong that would be great.
Thanks in advance!
You have the infamous closure bug.
I noticed that you are transpiring using Babel. Using let instead of var for your variables local to your loop should fix the issue. Notice that in your broken CodePen, the last letter stays while the rest disappear. That is because your thang is always equal to the last letter by the time the timeout handlers execute (the loop has concluded long before).
See http://codepen.io/anon/pen/ObaVyb.
Also, a better idea might be to take a look at animation-fill-mode: forwards, which allows you to retain styles after animations have been run.
Finally, for those of you not using ES6, this code will allow you to achieve the same functionality without creating another wrapper function. (Essentially, setTimeout allows you to pass arguments to your callback when you register each handler.)
setTimeout(function (thang) {
thang.style.opacity = "1"
thang.style.marginTop = "0";
}, timeOut, thang);
The problem is, that you have several timeouts in for loop, that needs references to thang variables, but when your timeouts will be executed thang variable will be equal to the last thang in the cycle, so all the timeout would have the same reference. Hope it's clear.
So, to fix that, you need to bind your timeouts with thangs variables, one by one.
For example, you can do it with closures:
(function(thang) {setTimeout(function() {
thang.style.opacity = "1"
thang.style.marginTop = "0";
}, timeOut);})(thang)
Ok, so I've made a timer that makes parts of my SVG map fadeOut as they cross certain thresholds. However, I want to mess with other parts of the CSS.
I looked at this post, but couldn't make sense of it in terms of my problem.
** Edits Below**
Thanks for the help, I took a look at my code and tried to clean out some of the stuff that didn't need to be there. I also restructured my if statement, putting it inside of the JQuery code. I tried the suggestion below, assigning the var timer outside the interval function, but then my start button no longer worked and the script started running on page load. So, I moved it back to keep things working.
Also, put my code into JSFiddle, but I couldn't get it to work correctly. Will spend some more time familiarizing myself with that in the meantime. Thank you for introducing me to that.
As for my original question:
the .animate() tag works so long as I set it to change the opacity attribute, but has no effect on the other attributes I want to change. I know SVG and CSS have different attribute names, and I've tried both types of names. Here is my code below. I am trying to get the .animate() effect to change the fill color and stroke-width.
var i,timer;
i = 2013;
function start() {
timer = self.setInterval("increment()", 800 )
}
function increment() {
i++;
document.getElementById("timer_out").innerHTML = i ;
$(document).ready( function() {
if (i == 2014) {
$('#AL').animate( {
opacity: 0.3 } , 500 );
}
});
}
function stop() {
clearInterval(timer);
timer = null;
}
function reset() {
stop();
i=2013;
document.getElementById("timer_out").innerHTML = i;
}
I'm really just concerned with the JQuery statement, which works perfectly fine until I replace opacity with a different CSS attribute.
Thanks again for the attention and advice.
1) if you divide any number by 1 you get the original number, your divisions are doing nothing as far as i can tell.
2) setInterval should be written:
timer = setInterval(increment, ( 1000 / divide ))
also note increment() and start() are not good name choices to have in global scope, how many people will think of those names, use anonymous functions maybe to contain scope
(function()
{
// function is now contained within anonymous function scope and not accessible outside
function increment(){}
})()
3) logically step though your code in your head. your code wont work
4) create a fiddle of what you have done so far
Disclaimer - I've tried finding an answer to this via google/stackoverflow, but I don't know how to define the problem (I don't know the proper term)
I have many small AI snippets such as what follows. There is an ._ai snippet (like below) per enemy type, with one function next() which is called by the finite state machine in the main game loop (fyi: the next function doesn't get called every update iteration, only when the enemy is shifted from the queue).
The question: How do I test every case (taking into account some enemy AI snippets might be more complex, having cases that may occur 1 in 1000 turns) and ensure the code is valid?
In the example below, if I added the line blabla/1 under count++, the error might not crop for a long time, as the Javascript interpreter won't catch the error until it hits that particular path. In compiled languages, adding garbage such as blabla/1 would be caught at compile time.
// AI Snippet
this._ai = (function(commands){
var count = 0;
return {
next: function(onDone, goodies, baddies) {
// If the internal counter reaches
// 2, launch a super attack and
// reset the count
if(count >= 2) {
commands.super(onDone);
count = 0;
}
else {
// If not performing the super attack
// there is a 50% chance of calling
// the `attack` command
if(chance(50)) {
var target = goodies[0];
commands.attack(onDone, target);
}
// Or a 50% chance of calling the
// `charge` command
else {
commands.charge(onDone);
count++;
}
}
}
};
})(this._commands);
I could rig the random generator to return a table of values from 0-n and run next 1000's of times against each number. I just don't feel like that is will concretely tell me every path is error free.
As you say, unit tests must test every path so you will be sure all works well.
But you should be able to decide which path the method will follow before calling it on your tests, so you're be able to know if the method behaviour is the expected one, and if there is any error.
So, for example, if there is a path that will be followed in only one of every 1000 executions, you shouldn't need to test all 0, 1, 2 ... 999 cases. You only one combination of results that behave distinctly.
For example, in the snippet shown you have these cases:
the counter has reached 2
the counter has not reached 2 and chance returns true
the counter has not reached 2 and chance returns false
One way to archieve this is taking control of the counter and of the chance method by mocking them.
If you want to know what happens when the counter has reached 2 and the next method is called, just pass a counter with 2 and call next. You don't need to reach 2 on the counter by really passing for all the code.
As for the randomizer, you don't need to try until the randomizer returns the value you want to test. Make it a mock and configure it to behave as you need for each case.
I hope this helps.
I would like to edit my if else statement in javascript dynamically.
So after one if statement is used, it could be removed. I get this maybe isn't possible but after a search online failed, my curiosity begged me to ask.
For instance:
if (x > 200 && x % 25 === 0) {
doSomething1();
} else if (x > 300 && !inRange) {
doSomething2();
} else if (x > 400 && x % 7 === 0) {
doSomething3();
}
There are eight if else statements within this loop. The loop determines which object to create. There are 2000 objects created over the course of a couple minutes. If on average we reach the fourth statement before it breaks, then there are 8,000 calculations being performed just within this one set of statements.
I want to streamline the script for speed and again, curiosity if we can actually write javascript dynamically without using separate functions etc. After an if statement fails, it is often not required anymore. The next statement could I suppose, include code to remove its predecessor dynamically. This might save 3 or 4 thousand calculations - not huge I know, but worthy of consideration given that there are lots of other things going on as well.
Is there a way to remove them dynamically or does anyone have any tricks or patterns up their sleeves?
Also, even if this is not available in js, what would this be called?
No. And the need for such would indicate poor design.
You should use a conditional expression to determine when which code segment should be run, as you mention. If you pass a certain threshold within your code after which you no longer want a condition to be executed in your loop, why not simply break the loop and have a new code block handling the doSomethingElse clause. If you're using setInterval, that's the point at which you would call clearInterval, and then trigger some new action if necessary. Anyway, running a single (or even a few) simple conditional statement doesn't add much overhead, and isn't likely to be the limiting factor in your optimization anyway.
Ignoring the fact that I doubt this is a bottleneck in modern browsers that JIT the JavaScript (CPUs are very good at predictive branching) as shown because simple number comparison is not going to be expensive even in large iterations with smart predictions once it's compiled.
You can do this by injecting a different function:
checker: function(x) {
if (x > 200) {
doSomething1();
}
else if (x > 300) {
doSomething2();
}
else if (y > 400) {
doSomething3();
}
}
Can be changed to
checker: function(x) {
if (x > 200) {
doSomething1();
}
else if (x > 300) {
doSomething2();
this.checker = smallerChecker;
}
else if (y > 400) {
doSomething3();
}
}
function smallerChecker(x) {
if (x > 200) {
doSomething1();
}
else if (y > 400) {
doSomething3();
}
}
Fundamentally, you simply need to make the behavior injectable, and then you change it however you see fit. Be-it by replacing the function doing the checking outright (the functional way) as I did above, or enabling an object to replace it (the OO way).
Why would you want to remove them dynamically? Altering the code dynamically is unnecessary and a bag of worms that's overdoing it for this situation. You should be using a flag.
I'll answer separately for whether you're trying to skip a large group of if statements, or an individual if statement.
Foreword
As mentioned in the comments on your question, run profiling to make sure you know where your performance problems are!
You mention your aversion to simply using boolean flags to make an if statement not run in your answer. This is fine, and it's what people normally do. This should not be an actual performance concern, and profiling will probably show your performance problems lie elsewhere. If they don't and this boolean flag check is genuinely your bottleneck - you have bigger problems, such as expecting too much from your JavaScript code, or that you didn't use the profiling tool correctly, or misinterpreted its results.
If you're trying to avoid running the body of an if statement, or its conditions, those are a bigger performance concern to you than the boolean flag check itself.
For skipping a large group of if statements
Wrap your bunch of if statements in a condition.
if (runBunchOfIfStatements) {
// all those if statements here
}
When you're past the point of wanting those if statements to run, set the runBunchOfIfStatements flag to false (of course, you should probably pick a more meaningful name than that).
That said, 8 or 9 if statements is a code length issue, and more than likely means nothing at all for performance concerns - unless those if statements happen to involve very intensive checks. If you're worried just because there's a lot of if checks, you're probably looking in the wrong place.
For individual if statements
Say you have only one if statement you want to skip. You had this code in your answer:
} else if (x > 300 && !doneSomething2) {
doSomething2();
doneSomething2 = 1;
}
This is fine. You're just making a tiny check: see the foreword. Look elsewhere for your performance concern. It could be rewritten slightly to more closely follow convention (which I'm about to get to), but in this situation, the change will have negligible impact.
Let's take a situation where there is actually a performance concern here. Suppose that instead of checking x > 300 you're doing something more intensive like calculateSeveralSquareRoots(). Generally, you do take this approach, but you rearrange it like this:
} else if (needCalculations && calculateSeveralSquareRoots() {
// do stuff
needCalculations = false;
}
The difference here is the needCalculations flag comes first, not second. JavaScript's comparison operators have short circuit evaluation. This means that when evaluating a && b, if a is false, b never even gets checked - we already know the result will be false. If the flag comes first, that means calculateSeveralSquareRoots() never gets run, and you save time on the check.
If the flag came second, then you're potentially wasting a lot of time on that function for a condition that might almost always resolve to false anyway thanks to that flag.
So in your original, you could have the flag come before the x > 300 evaluation, just to follow convention. But again... if an if statement like this is a real and significant performance concern for you, then you have bigger issues.
Order them in order of likelihood (so if >400 is most common, check for that first, and if x<200 is next most common, check for that, etc.) The example code is in order of increasing boundaries.
Next, your code doesn't show it and you just imply it, this is in a loop. (And if it isn't a loop, then this isn't a perf issue of interest) You could try fancy loops like Duff's device.
And figuring out what code can be changed to use more native API's is going to make a magical difference, whereas code optimizations like this will likely make only a marginal difference.
If you want it to be dynamic, you could always have a collection of conditions associated with actions and as soon as executed, these gets removed from the collection. However, I doubt it will lead to faster code execution, but you would have to create a jsperf test to know for sure.
DEMO: http://jsfiddle.net/a2ZEj/1/
function doSomethingA() {}
function doSomethingB() {}
var doOperation = (function doOperation() {
var operations = [
{
check: function (someArg) {
return someArg > 100;
},
exec: doSomethingA
},
{
check: function (someArg) {
return someArg > 100 && someArg < 200;
},
exec: doSomethingB
}
];
return function (someArg) {
var i = 0,
len = operations.length,
item;
for (; i < len; i++) {
if ((item = operations[i]).check(someArg)) {
item.exec();
operations.splice(i, 1);
console.log('executed ' + item.exec.name);
return;
}
}
};
})();
doOperation(101); //calls doSomethingA
doOperation(101); //calls doSomethingB
doOperation(101); //does nothing
You can create a method as below and create dynamic conditions
function buildCond(lhv1,rhv1,lhv2,rhv2)
{
var condition1,condition2;
condition1 = condition2 = '';
if(rhv1 !== -1){
condition1 = lhv1 + " == " + rhv1 + " && ";
}
if(rhv2 !== -1){
condition2 = lhv2 + " == " + rhv2 + " && ";
}
return condition1 + condition2;
}
And then call this method with eval to execute
if(eval(buildCond(var1,value1,var2,value2)) === true){
//do stuff
}
I have a JavaScript function that contains a for loop that iterates so many times.
After calling this function, the IE browser displays this message:
Stop running this script?
A script on this page is causing your web browser to run slowly.
If it continues to run, your computer might become unresponsive.
How can I fix this?
is there anyway I can disable this message from IE?
This message displays when Internet Explorer reaches the maximum number of synchronous instructions for a piece of JavaScript. The default maximum is 5,000,000 instructions, you can increase this number on a single machine by editing the registry.
Internet Explorer now tracks the total number of executed script statements and resets the value each time that a new script execution is started, such as from a timeout or from an event handler, for the current page with the script engine. Internet Explorer displays a "long-running script" dialog box when that value is over a threshold amount.
The only way to solve the problem for all users that might be viewing your page is to break up the number of iterations your loop performs using timers, or refactor your code so that it doesn't need to process as many instructions.
Breaking up a loop with timers is relatively straightforward:
var i=0;
(function () {
for (; i < 6000000; i++) {
/*
Normal processing here
*/
// Every 100,000 iterations, take a break
if ( i > 0 && i % 100000 == 0) {
// Manually increment `i` because we break
i++;
// Set a timer for the next iteration
window.setTimeout(arguments.callee);
break;
}
}
})();
The unresponsive script dialog box shows when some javascript thread takes too long too complete. Editing the registry could work, but you would have to do it on all client machines. You could use a "recursive closure" as follows to alleviate the problem. It's just a coding structure in which allows you to take a long running for loop and change it into something that does some work, and keeps track where it left off, yielding to the browser, then continuing where it left off until we are done.
Figure 1, Add this Utility Class RepeatingOperation to your javascript file. You will not need to change this code:
RepeatingOperation = function(op, yieldEveryIteration) {
//keeps count of how many times we have run heavytask()
//before we need to temporally check back with the browser.
var count = 0;
this.step = function() {
//Each time we run heavytask(), increment the count. When count
//is bigger than the yieldEveryIteration limit, pass control back
//to browser and instruct the browser to immediately call op() so
//we can pick up where we left off. Repeat until we are done.
if (++count >= yieldEveryIteration) {
count = 0;
//pass control back to the browser, and in 1 millisecond,
//have the browser call the op() function.
setTimeout(function() { op(); }, 1, [])
//The following return statement halts this thread, it gives
//the browser a sigh of relief, your long-running javascript
//loop has ended (even though technically we havn't yet).
//The browser decides there is no need to alarm the user of
//an unresponsive javascript process.
return;
}
op();
};
};
Figure 2, The following code represents your code that is causing the 'stop running this script' dialog because it takes so long to complete:
process10000HeavyTasks = function() {
var len = 10000;
for (var i = len - 1; i >= 0; i--) {
heavytask(); //heavytask() can be run about 20 times before
//an 'unresponsive script' dialog appears.
//If heavytask() is run more than 20 times in one
//javascript thread, the browser informs the user that
//an unresponsive script needs to be dealt with.
//This is where we need to terminate this long running
//thread, instruct the browser not to panic on an unresponsive
//script, and tell it to call us right back to pick up
//where we left off.
}
}
Figure 3. The following code is the fix for the problematic code in Figure 2. Notice the for loop is replaced with a recursive closure which passes control back to the browser every 10 iterations of heavytask()
process10000HeavyTasks = function() {
var global_i = 10000; //initialize your 'for loop stepper' (i) here.
var repeater = new this.RepeatingOperation(function() {
heavytask();
if (--global_i >= 0){ //Your for loop conditional goes here.
repeater.step(); //while we still have items to process,
//run the next iteration of the loop.
}
else {
alert("we are done"); //when this line runs, the for loop is complete.
}
}, 10); //10 means process 10 heavytask(), then
//yield back to the browser, and have the
//browser call us right back.
repeater.step(); //this command kicks off the recursive closure.
};
Adapted from this source:
http://www.picnet.com.au/blogs/Guido/post/2010/03/04/How-to-prevent-Stop-running-this-script-message-in-browsers
In my case, while playing video, I needed to call a function everytime currentTime of video updates. So I used timeupdate event of video and I came to know that it was fired at least 4 times a second (depends on the browser you use, see this). So I changed it to call a function every second like this:
var currentIntTime = 0;
var someFunction = function() {
currentIntTime++;
// Do something here
}
vidEl.on('timeupdate', function(){
if(parseInt(vidEl.currentTime) > currentIntTime) {
someFunction();
}
});
This reduces calls to someFunc by at least 1/3 and it may help your browser to behave normally. It did for me !!!
I can't comment on the previous answers since I haven't tried them. However I know the following strategy works for me. It is a bit less elegant but gets the job done. It also doesn't require breaking code into chunks like some other approaches seem to do. In my case, that was not an option, because my code had recursive calls to the logic that was being looped; i.e., there was no practical way to just hop out of the loop, then be able to resume in some way by using global vars to preserve current state since those globals could be changed by references to them in a subsequent recursed call. So I needed a straight-forward way that would not offer a chance for the code to compromise the data state integrity.
Assuming the "stop script?" dialog is coming up during a for() loop executuion after a number of iterations (in my case, about 8-10), and messing with the registry is no option, here was the fix (for me, anyway):
var anarray = [];
var array_member = null;
var counter = 0; // Could also be initialized to the max desired value you want, if
// planning on counting downward.
function func_a()
{
// some code
// optionally, set 'counter' to some desired value.
...
anarray = { populate array with objects to be processed that would have been
processed by a for() }
// 'anarry' is going to be reduced in size iteratively. Therefore, if you need
// to maintain an orig. copy of it, create one, something like 'anarraycopy'.
// If you need only a shallow copy, use 'anarraycopy = anarray.slice(0);'
// A deep copy, depending on what kind of objects you have in the array, may be
// necessary. The strategy for a deep copy will vary and is not discussed here.
// If you need merely to record the array's orig. size, set a local or
// global var equal to 'anarray.length;', depending on your needs.
// - or -
// plan to use 'counter' as if it was 'i' in a for(), as in
// for(i=0; i < x; i++ {...}
...
// Using 50 for example only. Could be 100, etc. Good practice is to pick something
// other than 0 due to Javascript engine processing; a 0 value is all but useless
// since it takes time for Javascript to do anything. 50 seems to be good value to
// use. It could be though that what value to use does depend on how much time it
// takes the code in func_c() to execute, so some profiling and knowing what the
// most likely deployed user base is going to be using might help. At the same
// time, this may make no difference. Not entirely sure myself. Also,
// using "'func_b()'" instead of just "func_b()" is critical. I've found that the
// callback will not occur unless you have the function in single-quotes.
setTimeout('func_b()', 50);
// No more code after this. function func_a() is now done. It's important not to
// put any more code in after this point since setTimeout() does not act like
// Thread.sleep() in Java. Processing just continues, and that is the problem
// you're trying to get around.
} // func_a()
function func_b()
{
if( anarray.length == 0 )
{
// possibly do something here, relevant to your purposes
return;
}
// -or-
if( counter == x ) // 'x' is some value you want to go to. It'll likely either
// be 0 (when counting down) or the max desired value you
// have for x if counting upward.
{
// possibly do something here, relevant to your purposes
return;
}
array_member = anarray[0];
anarray.splice(0,1); // Reduces 'anarray' by one member, the one at anarray[0].
// The one that was at anarray[1] is now at
// anarray[0] so will be used at the next iteration of func_b().
func_c();
setTimeout('func_b()', 50);
} // func_b()
function func_c()
{
counter++; // If not using 'anarray'. Possibly you would use
// 'counter--' if you set 'counter' to the highest value
// desired and are working your way backwards.
// Here is where you have the code that would have been executed
// in the for() loop. Breaking out of it or doing a 'continue'
// equivalent can be done with using 'return;' or canceling
// processing entirely can be done by setting a global var
// to indicate the process is cancelled, then doing a 'return;', as in
// 'bCancelOut = true; return;'. Then in func_b() you would be evaluating
// bCancelOut at the top to see if it was true. If so, you'd just exit from
// func_b() with a 'return;'
} // func_c()