# Autosave in your program

**URL:** <https://discourse.processing.org/t/autosave-in-your-program/3504>\
**Category:** Coding Questions\
**Created:** [September 13, 2018, 7:36am UTC](https://discourse.processing.org/t/autosave-in-your-program/3504 "2018-09-13T07:36:42Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![MxFxM](https://avatars.discourse-cdn.com/v4/letter/m/71e660/32.png) [@MxFxM](https://discourse.processing.org/u/MxFxM)\
**Post date:** [September 13, 2018, 7:36am UTC](https://discourse.processing.org/t/autosave-in-your-program/3504/1 "2018-09-13T07:36:42Z")

</div>

Hi.  
Just like me you might want some code in your tool that saves the file you are working on in a set interval. I searched the forum but there was no topic like this before.

A little research in the java documentation as well as on stackoverflow and I found this piece of code:

```auto
import java.util.*;

class SayHello extends TimerTask {
    public void run() {
       System.out.println("Hello World!"); 
    }
}

// And From your main() method or any other method
Timer timer = new Timer();
timer.schedule(new SayHello(), 0, 5000);

```

Source: [https://stackoverflow.com/questions/12908412/print-hello-world-every-x-seconds](https://stackoverflow.com/questions/12908412/print-hello-world-every-x-seconds)

My idea is to replace the “Hello World” part with my code to save the file that is currently opened in my program.

However it might throw an error when I am writing or reading from that file at the exact same moment. So I will have to make a key that is only released when it is save to save the file (no pun intended).

Also I don’t want to save every 5 seconds but more like every 15 minutes. So I will have to replace the 5000ms with 900 000ms.

Did you write an autosave function before? What are your ideas to save a file at a specific rate? Can you find ways to improve what I found?

Edit:  
This is closer to what I will use.

```auto
import java.util.*;
Timer timer = new Timer();

int autosave_state = 0;

void setup() {
  timer.schedule(new Autosave(), 0, 900000); // every 15 min
}

void draw() {
  while (autosave_state == 2) {
    // wait until save is over
  }
  
  autosave_state = 0;
  // do critical stuff
  autosave_state = 1;
  // non critical stuff
}

class Autosave extends TimerTask {
    public void run() {
       while (autosave_state != 1) {
         // wait until critical stuff is over
       }
       
       autosave_state = 2;
       // save here
       autosave_state = 3;
    }
}

```

---

<div class="post-metadata">

**Author:** ![jeremydouglass](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jeremydouglass/32/20_2.png) [@jeremydouglass](https://discourse.processing.org/u/jeremydouglass)\
**Post date:** [September 15, 2018, 12:40am UTC](https://discourse.processing.org/t/autosave-in-your-program/3504/2 "2018-09-15T00:40:08Z")

</div>

Is your program using threads, what kind of data / file handle, what kind of saving (total / progressive), and how are you writing to your file?

If you are in a normal single-threaded program (not using Thread) for example, and if you are using saveStrings / saveBytes / saveJSON etc, then I don’t _think_ you have to do any of this.

**However: threading experts like @neilcsmith and @GoToLoop may know better than I do.**

If I am correct, you could just write:

**Edit: I was NOT correct, correction below**

```auto
int autoSaveDuration;
int nextSave;
void setup(){
  autoSaveDuration = 1000 * 5; // save every 5 seconds
  nextSave = autoSaveDuration;
}
void draw(){
  if(millis()>nextSave){
    mySave();
    println("saved at " + millis());
    nextSave += autoSaveDuration;
  }
}
void mySave(){
}

```

…and it will run your save safely every 5 seconds (or 100 seconds, or whatever you choose).

The key thing here is that Processing already has an internal timer, so you don’t actually need to create a heavy-duty one. If you need complex timing functions, however (and for autosave it doesn’t seem like you do) you might want to check out the [Processing libraries](https://processing.org/reference/libraries/) page for [Timing Utilities](https://github.com/Lord-of-the-Galaxy/Timing-Utilities) and [CountdownTimer](https://github.com/dhchoi/processing-countdowntimer).

---

<div class="post-metadata">

**Author:** ![MxFxM](https://avatars.discourse-cdn.com/v4/letter/m/71e660/32.png) [@MxFxM](https://discourse.processing.org/u/MxFxM)\
**Post date:** [September 17, 2018, 9:05am UTC](https://discourse.processing.org/t/autosave-in-your-program/3504/3 "2018-09-17T09:05:56Z")

</div>

I am using multiple threads.

This is my save function:

```auto
void saveSelected(File selection) {
  // projektdatei speichern
  if (selection == null) { // wenn kein pfad gewählt
  } else {
    export_running_panel.setVisible(true); // zeige, dass beschäftigt
    String[] alldata = new String[var.data.size() + 5]; // neuer string, so lang wie die daten sind plus iso, stütz und zoom

    alldata[0] = "" + var.X_MIN + "/" + var.Y_MIN + "/" + var.X_MAX + "/" + var.Y_MAX + "/"; // fenstergröße
    for (int i = 0; i < var.iso_line_value.length; i++) { // für jede iso linie
      alldata[0] += var.iso_line_value[i] + "/"; // wert der iso linie
    }

    alldata[1] = "";
    for (int i = 0; i < var.supports_xparallel.length; i++) { // für jede zur x achse parallelen stützachse
      alldata[1] += var.supports_xparallel[i] + "/"; // wert der stützachse
    }

    alldata[2] = "";
    for (int i = 0; i < var.supports_yparallel.length; i++) { // für jede zur y achse parallelen stützachse
      alldata[2] += var.supports_yparallel[i] + "/"; // wert der stützachse
    }

    alldata[3] = "";
    for (int i = 0; i < var.iso_line_points.length; i++) { // für jede iso linie
      for (int j = 0; j < var.iso_line_points[i].length; j++) { // für jeden knickpunkt
        alldata[3] += var.iso_line_points[i][j][0] + "/" + var.iso_line_points[i][j][1] + "/"; // x und y wert des knickpunktes
      }
    }

    if (var.EXTENDED_MODE) { // wenn der erweiterte isolinien modus aktiv ist
      alldata[3] += "true" + "/"; // true in die datei schreiben
    } else { // wenn der erweiterte isolinien modus noch nicht aktiviert wurde
      alldata[3] += "false" + "/"; // true in die datei schreiben
    }

    alldata[4] = "" + var.nvpoints.length + "/"; // anzahl der ungeeignet punkte in fünfte zeile
    for (int i = 0; i < var.nvpoints.length; i++) { // für jeden punkt
      alldata[4] += var.nvpoints[i][0] + "/" + var.nvpoints[i][1] + "/"; // d und L wert dazu
    }

    for (int i = 5; i < var.data.size() + 5; i++) { // für jeden datensatz
      alldata[i] = var.data.get(i-5).getStream(); // gesamter datensatz
    }

    String path = selection.getAbsolutePath();

    if (!path.substring(path.length()-4).equals(".txt")) { // wenn die endung nicht schon .txt ist
      path += ".txt"; // endung hinzufügen
    }

    saveStrings(path, alldata); // speichern als .txt datei
    
    File f = new File(path);
    surface.setTitle("" + f.getName() + " Table Tool : Version " + VERSIONNR);

    System.gc(); // datenmüll vermeiden
    export_running_panel.setVisible(false); // nichtmehr beschäftigt
    save_for_next_start[0] = path; // datei beim nächsten öffnen laden
  }
}

```

I didn’t bother to take out the german comments. Just ignore them.  
What that code does is to create a string array with a fixed length plus one element for each data-set. In the fixed part I store some setup data. Each data-set contains of multiple data points.

There are about 100 000 data points in total to store, depending on the measurements done before.

I’m not sure if I can just put the save at the end of the main loop since other threads might write to the variables?

EDIT:  
This just came to my mind: What if

> [@jeremydouglass](#):
>
> if(millis()%100000==0){

never is detected because my draw loop takes more than 1ms to run (I bet it does)?

---

<div class="post-metadata">

**Author:** ![jeremydouglass](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jeremydouglass/32/20_2.png) [@jeremydouglass](https://discourse.processing.org/u/jeremydouglass)\
**Post date:** [September 17, 2018, 11:36pm UTC](https://discourse.processing.org/t/autosave-in-your-program/3504/4 "2018-09-17T23:36:50Z")

</div>

> [@MxFxM](#):
>
> never is detected because my draw loop takes more than 1ms to run (I bet it does)?

Gah. Sorry, my mistake – my example is bad and will most certainly _not_ be detected, because millis() will almost never be _exactly_ – when checked, it will be slightly less or more. I will provide a (again, very single-threaded) example correction.

Kids: don’t post code without running it. After I’ve explained “don’t use == on millis()” many times on the forum, I went and did it anyway.

…okay, Simple example posted in the comment above, replacing the bad code. It stores the next save time in a global variable, and increments it forward whenever save is triggered by millis() being greater than the next scheduled time. For many timers you could wrap this in a simple timer class – if you don’t mind being dependent on the main thread timer, of course.
