I am writing a function that I want to have the ability to automatically update itself. In other words, when the function is run, I want it to check if the current code in the editor is the most recent version and if it is not, go fetch the most recent version.
I have already solved the part about fetching the most recent version; however, I have not found a way to call this newly updated code from the current code. So even after the code is updated, I still want the new code to run with the same inputs that were used for the original call. Here is a brief example of what I mean:
function autoUpdatingCode(varargin)
if not_most_recent_version
urlwrite('http://somewebsite.com/autoUpdatingCode.p','autoUpdatingCode_updated.p')
delete('autoUpdatingCode.p');
movefile('autoUpdatingCode_updated.p','autoUpdatingCode.p');
c = onCleanup(#() restartCode(varargin));
return
end
... code for the function ...
end
function restartCode(inputs)
if isempty(inputs)
autoUpdatingCode();
elseif length(inputs)==1
autoUpdatingCode(inputs{1});
... so on for more inputs ...
end
end
Here I download the new code, delete the old version, and rename the updated version to the correct file name.
Note that the restartCode function is saved inside the same file as autoUpdatingCode. The problem here is that the call to autoUpdatingCode inside the restartCode function does not call the newly updated file (that was updated using movefile as shown), it calls the outdated code.
I'm assuming this happens because the entire program has been loaded into cache. Is there a way to clear the currently running function and load the new version? When I exit the function, the file is then updated with the new code as expected, I'm just looking for a way to force that update during execution of the same file.
I have so far experimented with rehash and clear, but had no luck with either. Using either of those functions still result in the old version of the code being called. I tried calling rehash and clear just after downloading, and just before the call to the function in the restartCode function.
If this is not possible, is there another workaround? I have considered automatically downloading another file that can restart the function and call this new function during the onCleanup function, but then I would need to delete that new file (which I can definitely do in my autoUpdatingCode function - I'm just looking for a cleaner alternative). Calling an external function from onCleanup still does not use the updated code.
Unfortunately, git (or any source control) is not an option here.
After messing with it for a while, I was able to find a solution. As the comment by #suever suggests, it is impossible to delete the file and then expect an updated version to be called. (More details here).
However, I was able to take advantage of function precedence to solve this problem. Instead of copying the new file to the same directory, I created a temporary directory, copied it there, and then called the function from that directory. Thanks to function precedence, the updated version is called instead of the program loaded into memory. The last step was just using dbstack (docs here) to determine if the program was being recursively called, in which case I moved the updated file from the temporary directory into the correct location and performed the necessary cleanup. Here's part of the updated code:
function autoUpdatingCode(varargin)
stack = dbstack('-completenames');
... process the stack ...
if recursively_called
cd('..');
movefile(newfile, oldfile);
rmdir('temp','s');
end
if not_most_recent_version
mkdir('temp');
websasve('./temp/autoUpdatingCode_updated.p', 'http://somewebsite.com/autoUpdatingCode.p',)
cd('temp');
c = onCleanup(#() restartCode(varargin));
return
end
... code for the function ...
end
function restartCode(inputs)
if isempty(inputs)
autoUpdatingCode();
elseif length(inputs)==1
autoUpdatingCode(inputs{1});
... so on for more inputs ...
end
end
Related
Is there a way to know when an MATLAB exits? I wanted to do some work, for example, release some resource, print some logs... I could add some code at some class's destructors. But since we cannot determine the order that MATLAB calls destructors, I am not sure which one is the last one so I can release the resource.
Can we register any callback to the MATLAB exit event if there exists such an event...?
There is no exit event I know of that's thrown when exiting from a function or MATLAB itself. However, there are two things you can do to handle final cleanup:
Use onCleanUp objects: When exiting from a function, variables in the local workspace are destroyed (and exiting from MATLAB itself will destroy objects in the base workspace). When working with resources (files, etc.), good practice is to create an onCleanUp object to handle those resources in an exception-safe manner. This is discussed in more detail in the documentation and this question: How do you handle resources in MATLAB in an exception safe manner? (like “try … finally”)
Create a finish.m file: When quitting MATLAB, it will look on the search path for a file named finish.m and run that code before terminating.
You can place any cleanup actions in the finish.m file.
Similar to startup.m, MATLAB executes this file (when found on the MATLAB search path) just prior to program termination.
Also worth looking into is onCleanup. This simple class creates an object that, when destroyed, runs the function registered during object creation. This is extremely useful when dealing with files for example:
fid = fopen(filename, 'r');
OC = onCleanup(#() any(fopen('all')==fid) && fclose(fid));
% ...file reading and processing here
% ERROR HAPPENS HERE!
% ... more processing here
fclose(fid);
meaning, the file handle fid is still closed, even though the normal fclose(fid) was not reached. This is because the object OC was cleared implicitly by MATLAB after the error.
I have a script that calls a function, which is written in separate file and contains sub-functions that are inner to main function only. In one of my sub-functions, I have persistent variable that I would like to clear every time I run the main script. How can I do so? In addition, I have breakpoints through my code, and I would prefer to keep them while I clear the persistent variable - how that can be done?
MainScript.m script:
clear variables;
for iterNum=1:5
dataOut = MyMainFunction(iterNum);
end
disp(dataOut);
MyMainFunction code:
function dataOut = MyMainFunction(iterNum)
if (iterNum==1)
clear MySubFunction;
end
dataOut = MySubFunction();
end
function dataOut = MySubFunction()
persistent idx;
if isempty(idx)
idx=1;
end
dataOut=idx;
idx=idx+1;
end
I would like to clear "idx" persistent variable every time that I run MainScript.m, but of course to keep that variable as long as the script is running.
Thanks, John
The easiest way I see is to call clear followed the function name:
clear MySubFunction
instead of
clear variables;
This should clear all the persistent variables in that particular function. This will probably have the side effect of removing the stored JIT'd copy of it, causing it to be reparsed the next time it is invoked.
You can use munlock if you previously mlock'ed your function.
OR
You can define a special set of parameters in your function that are designed to solely clear the persistent variable, and you call the function with this syntax at the beginning of your main file.
Unfortunately, the other answer is partially incorrect - it is NOT possible to clear persistent variables in a sub-function using clear MySubFunction.
To quote an answer by a MathWorks staff member,
Only top level or main functions (with the same name as the file) may be cleared. To clear any local or nested function the main function must be cleared and that can't be done while the main function (or any other function in the file) is running.
and
Only whole m files can be cleared from memory. The entire file is managed as a unit so sub functions can't be cleared without clearing the main function.
As such, your options are to
separate the sub-function into its own m-file, or
clear the entire MyMainFunction from within MainScript.m, or
follow Ratbert's second suggestion, i.e. instead of using clear, give MySubFunction an additional argument that tells it to reset the persistent variables by itself
This is my code:
%Activity 3.4 An object is thrown vertically with a speed vo reaches at
%height h at a time t.
function t = time(h,vo,g)
t = roots([0.5*g,-vo,h])
%Testing the function
test = time(100,50,9.81)
I've looked through different solutions but still can't figure out why I keep getting this error.
The error is happening on the line t = roots([0.5*g,-vo,h]).
Three comments:
You are probably pushing the Play button in the MATLAB editor. Don't do that. Forget that it even exists. Define h, vo and g in your Command Prompt, then do t = time(h, vo, g); in the Command Prompt. Again, do not push the Play button.
Make sure your working directory is set to where you defined the function time. MATLAB can't find this function that you defined. If you don't know how to do that, check out this from MathWorks: http://www.mathworks.com/help/matlab/ref/cd.html
Your error says it's trying to use a file called A3_4, yet your function is called time. In other words, It looks like you called your file A3_4.m yet it needs to be called time.m. Make sure it's in a file called time.m, then try again. That's one of MATLAB's cardinal rules. When you define a function, the function name and file name need to match.
Do all of those three steps in order, and you will be laughing and singing like these guys below:
(source: kym-cdn.com)
tl;dr
Is there any way in a Matlab .m file to detect that Matlab termination is under way?
I have an unmanaged library that provides an interface to my product. I have wrapped that for Matlab using a mex file. So my unmanaged library exists as a Windows DLL. I have a mex file that wraps that. In turn I have a collection of Matlab classes, implemented in various .m files that wrap the mex file. So far so good, all of this works splendidly.
I recently became aware of a problem during Matlab shutdown. Some of the Matlab classes wrap unmanaged objects. These unmanaged objects need to be destroyed when they are no longer needed. So I implement delete functions for the Matlab classes that wrap the unmanaged objects, and call into the mex file to destroy the objects. Obviously the mex file simply forwards these destruction calls to the unmanaged library. Again, this all works just fine.
The problem arises when Matlab shuts down and the user's workspace contains Matlab objects wrapping the unmanaged objects. Unfortunately, Matlab unloads the mex file, and then destroys the objects in the workspace. What happens next is that the delete function executes which calls into the mex file. Which reloads the mex file that was just unloaded. And now the attempt to destroy the unmanaged object leads to runtime errors, because my library has to be re-loaded.
Since is going to unload the mex file before destroying workspace objects, I have no choice but to skip the deletion of the unmanaged objects in that scenario. It isn't a memory leak or indeed a problem in any way, since the process is terminating. However, I do need to detect that the process is terminating. Which leads to the question, how to do that.
I'm aware of the finish.m termination file, but I'm not in control of that since I am providing a library. The user controls their termination file, and so I've ruled out that option. I don't even know whether or not it runs at a suitable time, i.e. before the workspace objects are destroyed.
I've built a functioning solution using mexAtExit. In the mex file initialization I call mexAtExit like so:
mexAtExit(atExit);
The atExit function is:
void atExit(void)
{
mexCallMATLAB(0, NULL, 0, NULL, "mylib.atExit");
}
And ofx.atExit is in the Matlab code and is implemented like this:
methods(Static)
function atExit
mylib.mexHasUnloaded(true);
end
function result = mexHasUnloaded(varargin)
global mexHasUnloadedGlobalVar;
if isempty(mexHasUnloadedGlobalVar)
mexHasUnloadedGlobalVar = false;
end
if nargin > 0
mexHasUnloadedGlobalVar = varargin{1};
end
result = mexHasUnloadedGlobalVar;
end
....
end
The delete function then checks mexHasUnloaded like this:
function delete(self)
if ~mylib.mexHasUnloaded
mylibMex(mylib.mexDestroyObject, self.handle);
end
end
Whilst this appears to work, I'm not at all happy with it.
Can I really only detect Matlab termination from inside a mex file? I would like to detect this directly in the .m file and it feels like that ought to be possible. Is it possible?
Do I really need to use a global variable like that? Can't I find a better way to look after this state? I tried using a persistent variable but that was just as hacky and did not work. The persistent variable was re-initialised at some point during the termination which meant that mexHasUnloaded started returning false after it had earlier been set to true.
Or is there a different solution to my problem? Can I force my mex file to stay loaded until after the workspace objects are deleted?
Does it work to mexLock() your MEX file so that it doesn't get unloaded, so the delete methods can do the right thing at shutdown?
I'm writing a matlab script where I'd like to know the name of the script which is one step up in the stack. The reason I need this is that I'm writing a helper script to be called to assert some basic facts about the workspace before engaging in heavier calculations, and the helper script should be able to give error messages when calling the calculation scripts.
I've tried using mfilename and dbstack, but I do not manage to get anything but the name of the helper script from them.
To explain further, I have the following scripts:
verify_base_conditions: the helper script, called on one of the first lines in
heavy_stuff_calculation and
sweet_mother_of_algorithms.
general_entry_point: a script where I gather common workflows in cells
I try to keep the entry point script as small as possible, and refactor heavier calculations (or anything that needs more than a few lines, really) into task-based, re-usable scripts. If I, from the entry point script, call sweet_mother_of_algorithms and the basic conditions for this script to run are not fulfilled, I want to see an error message like
Error: this_cool_var must be defined when running sweet_mother_of_algorithms
general_entry_point line 15
I tried using
error(['this_cool_var must be defined when running ' mdfilename])
and other similar constructs, but I couldn't make the error message say anything but verify_base_conditions.
How do I find the name of the script running one level up in the stack?
(Note: I'm not interested in finding the script running at the bottom of the stack - that will almost always be general_entry_point. I'm just interested in getting the name of the script that called verify_base_conditions.)
dbstack should work for this. I think this is an analogous set-up to yours:
a.m:
b;
b.m:
c;
c.m:
stack = dbstack;
for i=1:3
disp(stack(i));
end
When I run a;, this prints out the whole stack, including b (which I think it was you want - the second-top item on the call stack.
Alternatively, although this probably gives exactly the same result, you could throw and catch an error and look at its stack:
c.m:
try
error('What is on the call stack?');
catch e
for i=1:3
disp(e.stack(i));
end
end