Backed out changeset 7c90ac565923 (bug 927560)
authorRyan VanderMeulen <ryanvm@gmail.com>
Fri, 06 Dec 2013 10:09:13 -0500
changeset 156817 aa3b9dc8c0e001fe8efe09d97ac16f9f7595178f
parent 156816 ad7cf694eaac9d6254b998a7eea2cf4ef3e53383
child 156818 02194c6fe61e03ba34970d77d789dbcffa4b1d69
push id332
push userryanvm@gmail.com
push dateFri, 06 Dec 2013 15:09:09 +0000
bugs927560
milestone26.0
backs out7c90ac5659232a44ac80c7cd30eb246ed9f16f42
Backed out changeset 7c90ac565923 (bug 927560)
toolkit/components/osfile/modules/osfile_async_front.jsm
toolkit/components/osfile/modules/osfile_async_worker.js
--- a/toolkit/components/osfile/modules/osfile_async_front.jsm
+++ b/toolkit/components/osfile/modules/osfile_async_front.jsm
@@ -133,46 +133,43 @@ let clone = function clone(object, refs 
       result[k] = object[k];
     } else {
       refer(result, k, object);
     }
   }
   return result;
 };
 
-let worker = null;
+let worker = new PromiseWorker(
+  "resource://gre/modules/osfile/osfile_async_worker.js", LOG);
 let Scheduler = {
   /**
    * |true| once we have sent at least one message to the worker.
-   * This field is unaffected by resetting the worker.
    */
-   launched: false,
+  launched: false,
 
   /**
    * |true| once shutdown has begun i.e. we should reject any
-   * message, including resets.
+   * message
    */
   shutdown: false,
 
   /**
    * The latest promise returned.
    */
   latestPromise: Promise.resolve("OS.File scheduler hasn't been launched yet"),
 
   post: function post(...args) {
     this.launched = true;
+
     if (this.shutdown) {
       LOG("OS.File is not available anymore. The following request has been rejected.", args);
       return Promise.reject(new Error("OS.File has been shut down."));
     }
-    if (!worker) {
-      // Either the worker has never been created or it has been reset
-      worker = new PromiseWorker(
-        "resource://gre/modules/osfile/osfile_async_worker.js", LOG);
-    }
+
     // By convention, the last argument of any message may be an |options| object.
     let methodArgs = args[1];
     let options = methodArgs ? methodArgs[methodArgs.length - 1] : null;
     let promise = worker.post.apply(worker, args);
     return this.latestPromise = promise.then(
       function onSuccess(data) {
         // Check for duration and return result.
         if (!options) {
@@ -992,61 +989,24 @@ if (OS.Constants.Win) {
 } else {
   throw new Error("I am neither under Windows nor under a Posix system");
 }
 
 DirectoryIterator.Entry.fromMsg = function fromMsg(value) {
   return new DirectoryIterator.Entry(value);
 };
 
-/**
- * Flush all operations currently queued, then kill the underlying
- * worker to save memory.
- *
- * @return {Promise}
- * @reject {Error} If at least one file or directory iterator instance
- * is still open and the worker cannot be killed safely.
- */
-File.resetWorker = function() {
-  if (!Scheduler.launched || Scheduler.shutdown) {
-    // No need to reset
-    return Promise.resolve();
-  }
-  return Scheduler.post("Meta_reset").then(
-    function(wouldLeak) {
-      if (!wouldLeak) {
-        // No resource would leak, the worker was stopped.
-        worker = null;
-        return;
-      }
-      // Otherwise, resetting would be unsafe and has been canceled.
-      // Turn this into an error
-      let msg = "Cannot reset worker: ";
-      let {openedFiles, openedDirectoryIterators} = wouldLeak;
-      if (openedFiles.length > 0) {
-        msg += "The following files are still open:\n" +
-          openedFiles.join("\n");
-      }
-      if (openedDirectoryIterators.length > 0) {
-        msg += "The following directory iterators are still open:\n" +
-          openedDirectoryIterators.join("\n");
-      }
-      throw new Error(msg);
-    }
-  );
-};
-
 // Constants
 Object.defineProperty(File, "POS_START", {value: OS.Shared.POS_START});
 Object.defineProperty(File, "POS_CURRENT", {value: OS.Shared.POS_CURRENT});
 Object.defineProperty(File, "POS_END", {value: OS.Shared.POS_END});
 
-this.OS.File = File;
-this.OS.File.Error = OSError;
-this.OS.File.DirectoryIterator = DirectoryIterator;
+OS.File = File;
+OS.File.Error = OSError;
+OS.File.DirectoryIterator = DirectoryIterator;
 
 
 // Auto-flush OS.File during profile-before-change. This ensures that any I/O
 // that has been queued *before* profile-before-change is properly completed.
 // To ensure that I/O queued *during* profile-before-change is completed,
 // clients should register using AsyncShutdown.addBlocker.
 AsyncShutdown.profileBeforeChange.addBlocker(
   "OS.File: flush I/O queued before profile-before-change",
--- a/toolkit/components/osfile/modules/osfile_async_worker.js
+++ b/toolkit/components/osfile/modules/osfile_async_worker.js
@@ -62,28 +62,20 @@ if (this.Components) {
        }
 
        // Now, post a reply, possibly as an uncaught error.
        // We post this message from outside the |try ... catch| block
        // to avoid capturing errors that take place during |postMessage| and
        // built-in serialization.
        if (!exn) {
          LOG("Sending positive reply", result, "id is", id);
-         if (result instanceof Meta) {
-           if ("transfers" in result.meta) {
-             // Take advantage of zero-copy transfers
-             self.postMessage({ok: result.data, id: id, durationMs: durationMs},
-               result.meta.transfers);
-           } else {
-             self.postMessage({ok: result.data, id:id, durationMs: durationMs});
-           }
-           if (result.meta.shutdown || false) {
-             // Time to close the worker
-             self.close();
-           }
+         if (result instanceof Transfer) {
+           // Take advantage of zero-copy transfers
+           self.postMessage({ok: result.data, id: id, durationMs: durationMs},
+             result.transfers);
          } else {
            self.postMessage({ok: result, id:id, durationMs: durationMs});
          }
        } else if (exn == StopIteration) {
          // StopIteration cannot be serialized automatically
          LOG("Sending back StopIteration");
          self.postMessage({StopIteration: true, id: id, durationMs: durationMs});
        } else if (exn instanceof exports.OS.File.Error) {
@@ -195,35 +187,30 @@ if (this.Components) {
        }
        return f.call(file);
      };
 
      let Type = exports.OS.Shared.Type;
 
      let File = exports.OS.File;
 
-  /**
-   * A constructor used to return data to the caller thread while
-   * also executing some specific treatment (e.g. shutting down
-   * the current thread, transmitting data instead of copying it).
-   *
-   * @param {object=} data The data to return to the caller thread.
-   * @param {object=} meta Additional instructions, as an object
-   * that may contain the following fields:
-   * - {bool} shutdown If |true|, shut down the current thread after
-   *   having sent the result.
-   * - {Array} transfers An array of objects that should be transferred
-   *   instead of being copied.
-   *
-   * @constructor
-   */
-  let Meta = function Meta(data, meta) {
-    this.data = data;
-    this.meta = meta;
-   };
+     /**
+      * A constructor used to transfer data to the caller
+      * without copy.
+      *
+      * @param {*} data The data to return to the caller.
+      * @param {Array} transfers An array of Transferable
+      * values that should be moved instead of being copied.
+      *
+      * @constructor
+      */
+     let Transfer = function Transfer(data, transfers) {
+       this.data = data;
+       this.transfers = transfers;
+     };
 
      /**
       * The agent.
       *
       * It is in charge of performing method-specific deserialization
       * of messages, calling the function/method of OS.File and serializing
       * back the results.
       */
@@ -242,38 +229,16 @@ if (this.Components) {
          // Return information about both opened files and opened
          // directory iterators.
          return {
            openedFiles: OpenedFiles.listOpenedResources(),
            openedDirectoryIterators:
              OpenedDirectoryIterators.listOpenedResources()
          };
        },
-       Meta_reset: function() {
-         // Attempt to stop the worker. This fails if at least one
-         // resource is still open. Returns the list of files and
-         // directory iterators that cannot be closed safely (or undefined
-         // if there are no such files/directory iterators).
-         let openedFiles = OpenedFiles.listOpenedResources();
-         let openedDirectoryIterators =
-           OpenedDirectoryIterators.listOpenedResources();
-         let canShutdown = openedFiles.length == 0
-               && openedDirectoryIterators.length == 0;
-         if (canShutdown) {
-           // Succeed. Shutdown the thread, nothing to return
-           return new Meta(null, {shutdown: true});
-         } else {
-           // Fail. Don't shutdown the thread, return info on resources
-           return {
-             openedFiles: openedFiles,
-             openedDirectoryIterators: openedDirectoryIterators
-           };
-         }
-       },
-
        // Functions of OS.File
        stat: function stat(path) {
          return exports.OS.File.Info.toMsg(
            exports.OS.File.stat(Type.path.fromMsg(path)));
        },
        getCurrentDirectory: function getCurrentDirectory() {
          return exports.OS.Shared.Type.path.toMsg(File.getCurrentDirectory());
        },
@@ -303,23 +268,17 @@ if (this.Components) {
          return OpenedFiles.add(file, {
            // Adding path information to keep track of opened files
            // to report leaks when debugging.
            path: filePath
          });
        },
        read: function read(path, bytes, options) {
          let data = File.read(Type.path.fromMsg(path), bytes);
-         return new Meta({
-           buffer: data.buffer,
-           byteOffset: data.byteOffset,
-           byteLength: data.byteLength
-         }, {
-         transfers: [data.buffer]
-         });
+         return new Transfer({buffer: data.buffer, byteOffset: data.byteOffset, byteLength: data.byteLength}, [data.buffer]);
        },
        exists: function exists(path) {
          return File.exists(Type.path.fromMsg(path));
        },
        writeAtomic: function writeAtomic(path, buffer, options) {
          if (options.tmpPath) {
            options.tmpPath = Type.path.fromMsg(options.tmpPath);
          }
@@ -353,23 +312,17 @@ if (this.Components) {
            function do_stat() {
              return exports.OS.File.Info.toMsg(this.stat());
            });
        },
        File_prototype_read: function read(fd, nbytes, options) {
          return withFile(fd,
            function do_read() {
              let data = this.read(nbytes, options);
-             return new Meta({
-               buffer: data.buffer,
-               byteOffset: data.byteOffset,
-               byteLength: data.byteLength
-             }, {
-               transfers: [data.buffer]
-             });
+             return new Transfer({buffer: data.buffer, byteOffset: data.byteOffset, byteLength: data.byteLength}, [data.buffer]);
            }
          );
        },
        File_prototype_readTo: function readTo(fd, buffer, options) {
          return withFile(fd,
            function do_readTo() {
              return this.readTo(exports.OS.Shared.Type.voidptr_t.fromMsg(buffer),
              options);