X-Git-Url: http://www.git.cypherpunks.ru/?a=blobdiff_plain;f=js.go;h=d160c1091a28995a471c2e6ae2b30de83276daf1;hb=db81599c97bdc51c5fd1edfabc4840438a26029a;hp=ab1190e00c00759f48899030271986704d3c9ae4;hpb=f15fe27971bcf37a06bb9542ea1907f11444515a;p=goredo.git diff --git a/js.go b/js.go index ab1190e..d160c10 100644 --- a/js.go +++ b/js.go @@ -19,59 +19,114 @@ along with this program. If not, see . package main -import "os" +import ( + "flag" + "fmt" + "log" + "os" + "os/signal" + "strconv" + "strings" + "sync" + "syscall" +) + +const ( + EnvJobs = "REDO_JOBS" + EnvJSFd = "REDO_JS_FD" +) var ( - JSR *os.File - JSW *os.File + JSR *os.File + JSW *os.File + jsTokens int + jsTokensM sync.Mutex + + flagJobs = flag.Uint64("j", 1, fmt.Sprintf("number of parallel jobs (0=inf) (%s)", EnvJobs)) ) func jsInit() { - jsrRaw := os.Getenv(RedoJSRFdEnv) - jswRaw := os.Getenv(RedoJSWFdEnv) - if (jsrRaw == "" && jswRaw != "") || (jsrRaw != "" && jswRaw == "") { - panic("both JSR and JSW must be set") - } - if jsrRaw == "NO" { + jsRaw := os.Getenv(EnvJSFd) + if jsRaw == "NO" { // infinite jobs return } - if jsrRaw != "" { - JSR = mustParseFd(jsrRaw, "JSR") - JSW = mustParseFd(jswRaw, "JSW") - jsRelease() + if jsRaw != "" { + cols := strings.Split(jsRaw, ",") + if len(cols) != 2 { + log.Fatalln("invalid", EnvJSFd, "format") + } + JSR = mustParseFd(cols[0], "JSR") + JSW = mustParseFd(cols[1], "JSW") + jsRelease("ifchange entered") + + killed := make(chan os.Signal, 0) + signal.Notify(killed, syscall.SIGTERM, syscall.SIGINT) + go func() { + <-killed + jsTokensM.Lock() + for ; jsTokens > 0; jsTokens-- { + jsReleaseNoLock() + } + os.Exit(1) + }() return } - if *JobsN == 0 { + + var jobs uint64 + if v := os.Getenv(EnvJobs); v != "" { + var err error + jobs, err = strconv.ParseUint(v, 10, 64) + if err != nil { + log.Fatalln("can not parse", EnvJobs, err) + } + } else { + jobs = *flagJobs + } + if jobs == 0 { // infinite jobs return } + var err error JSR, JSW, err = os.Pipe() if err != nil { panic(err) } - for i := uint(0); i < *JobsN; i++ { - jsRelease() + for i := uint64(0); i < jobs; i++ { + jsRelease("initial fill") } } -func jsRelease() { - if JSW == nil { - return - } - trace(CJS, "release") +func jsReleaseNoLock() { if n, err := JSW.Write([]byte{0}); err != nil || n != 1 { panic("can not write JSW") } } -func jsAcquire() { +func jsRelease(ctx string) int { + if JSW == nil { + return 0 + } + trace(CJS, "release from %s", ctx) + jsTokensM.Lock() + jsTokens-- + left := jsTokens + jsReleaseNoLock() + jsTokensM.Unlock() + return left +} + +func jsAcquire(ctx string) { if JSR == nil { return } - trace(CJS, "acquire") + trace(CJS, "acquire for %s", ctx) if n, err := JSR.Read([]byte{0}); err != nil || n != 1 { panic("can not read JSR") } + jsTokensM.Lock() + jsTokens++ + jsTokensM.Unlock() + trace(CJS, "acquired for %s", ctx) }