code: def start(self, rootJob):
          
          self._assertContextManagerUsed()
          self.writePIDFile()
          if self.config.restart:
              raise ToilRestartException('A Toil workflow can only be started once. Use '
                                         'Toil.restart() to resume it.')
  
          self._batchSystem = self.createBatchSystem(self.config)
          self._setupAutoDeployment(rootJob.getUserScript())
          try:
              self._setBatchSystemEnvVars()
              self._serialiseEnv()
              self._cacheAllJobs()
  
              # Pickle the promised return value of the root job, then write the pickled promise to
              # a shared file, where we can find and unpickle it at the end of the workflow.
              # Unpickling the promise will automatically substitute the promise for the actual
              # return value.
              with self._jobStore.writeSharedFileStream('rootJobReturnValue') as fH:
                  rootJob.prepareForPromiseRegistration(self._jobStore)
                  promise = rootJob.rv()
                  pickle.dump(promise, fH, protocol=pickle.HIGHEST_PROTOCOL)
  
              # Setup the first wrapper and cache it
              rootJobGraph = rootJob._serialiseFirstJob(self._jobStore)
              self._cacheJob(rootJobGraph)
  
              self._setProvisioner()
              return self._runMainLoop(rootJobGraph)
          finally:
              self._shutdownBatchSystem()
docs: Invoke a Toil workflow with the given job as the root for an initial run. This method
          must be called in the body of a ``with Toil(...) as toil:`` statement. This method should
          not be called more than once for a workflow that has not finished.
  
          :param toil.job.Job rootJob: The root job of the workflow
          :return: The root job's return value