X-Git-Url: http://www.git.cypherpunks.ru/?a=blobdiff_plain;f=js.go;h=ccc9fe1d1ab1a9ecaa4f4a202804af09e3dbbde6;hb=634ee31ae35a2eaac517e0ffa1b7caede4b27ac5;hp=d3ed7bb3fb752b5b7566c1251db7ae11b3c93a1f;hpb=bc7701e7a4f95cee680e0736ec3e68a8b0b5c09f;p=goredo.git diff --git a/js.go b/js.go index d3ed7bb..ccc9fe1 100644 --- a/js.go +++ b/js.go @@ -19,53 +19,103 @@ along with this program. If not, see . package main -import "os" +import ( + "flag" + "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, "number of parallel jobs (0=inf) (REDO_JOBS)") ) 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") + 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++ { + for i := uint64(0); i < jobs; i++ { jsRelease("initial fill") } } -func jsRelease(ctx string) { - if JSW == nil { - return - } - trace(CJS, "release from %s", ctx) +func jsReleaseNoLock() { if n, err := JSW.Write([]byte{0}); err != nil || n != 1 { panic("can not write JSW") } } +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 @@ -74,5 +124,8 @@ func jsAcquire(ctx string) { 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) }