func (s *Scheduler) Swap(i, j int) {
	s.jobsMutex.Lock()
	defer s.jobsMutex.Unlock()
	s.jobs[i], s.jobs[j] = s.jobs[j], s.jobs[i]
}
Swap places each job into the other job's position given
the provided job indexes.
package gocron
import (
	"context"
	"fmt"
	"reflect"
	"sort"
	"sync"
	"time"
	"github.com/robfig/cron/v3"
	"golang.org/x/sync/semaphore"
)
type limitMode int8
type Scheduler struct {
	jobsMutex sync.RWMutex
	jobs      []*Job
	locationMutex sync.RWMutex
	location      *time.Location
	runningMutex  sync.RWMutex
	running       bool  
	time     timeWrapper  
	executor *executor    
	tags sync.Map  
	tagsUnique      bool  
	updateJob       bool  
	waitForInterval bool  
	jobCreated      bool  
}
const allWeekDays = 7
func NewScheduler(loc *time.Location) *Scheduler {
	executor := newExecutor()
	return &Scheduler{
		jobs:       make([]*Job, 0),
		location:   loc,
		running:    false,
		time:       &trueTime{},
		executor:   &executor,
		tagsUnique: false,
	}
}
func (s *Scheduler) SetMaxConcurrentJobs(n int, mode limitMode) {
	s.executor.maxRunningJobs = semaphore.NewWeighted(int64(n))
	s.executor.limitMode = mode
}
func (s *Scheduler) StartBlocking() {
	s.StartAsync()
	<-make(chan bool)
}
func (s *Scheduler) StartAsync() {
	if !s.IsRunning() {
		s.start()
	}
}
func (s *Scheduler) start() {
	go s.executor.start()
	s.setRunning(true)
	s.runJobs(s.Jobs())
}
func (s *Scheduler) runJobs(jobs []*Job) {
	for _, job := range jobs {
		s.scheduleNextRun(job)
	}
}
func (s *Scheduler) setRunning(b bool) {
	s.runningMutex.Lock()
	defer s.runningMutex.Unlock()
	s.running = b
}
func (s *Scheduler) IsRunning() bool {
	s.runningMutex.RLock()
	defer s.runningMutex.RUnlock()
	return s.running
}
func (s *Scheduler) Jobs() []*Job {
	s.jobsMutex.RLock()
	defer s.jobsMutex.RUnlock()
	return s.jobs
}
func (s *Scheduler) setJobs(jobs []*Job) {
	s.jobsMutex.Lock()
	defer s.jobsMutex.Unlock()
	s.jobs = jobs
}
func (s *Scheduler) Len() int {
	s.jobsMutex.RLock()
	defer s.jobsMutex.RUnlock()
	return len(s.jobs)
}