Skip to content

Instantly share code, notes, and snippets.

@penguinpowernz
Last active October 19, 2016 11:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save penguinpowernz/e8a892db0538ac44d6f56a489dce3768 to your computer and use it in GitHub Desktop.
Save penguinpowernz/e8a892db0538ac44d6f56a489dce3768 to your computer and use it in GitHub Desktop.
Semaphore server
package main
import (
"log"
"net/http"
"time"
)
type empty struct{}
type semaphore chan empty
// acquire n resources
func (s semaphore) P(n int) {
e := empty{}
for i := 0; i < n; i++ {
s <- e
}
}
// release n resources
func (s semaphore) V(n int) {
for i := 0; i < n; i++ {
<-s
}
}
type store map[string]semaphore
func (s store) P(tag string, n int) chan empty {
log.Printf("Trying to lock")
if _, ok := s[tag]; !ok {
log.Printf("Created new tag %s", tag)
s[tag] = make(semaphore, 1)
}
ch := make(chan empty, 1)
log.Printf("TRYING TO LOCK %s", tag)
s[tag].P(n)
ch <- empty{}
log.Printf("LOCKED %s", tag)
return ch
}
func (s store) V(tag string, n int) {
if _, ok := s[tag]; !ok {
s[tag] = make(semaphore, 1)
}
s[tag].V(n)
}
var semaphoreStore store = make(store)
func handler(w http.ResponseWriter, r *http.Request) {
action := r.URL.Query().Get("action")
tag := r.URL.Query().Get("tag")
log.Printf("Found tag %s and action %s", tag, action)
timeout := time.NewTimer(10 * time.Second)
switch action {
case "lock":
select {
case <-semaphoreStore.P(tag, 1):
log.Printf("GOT A LOCK")
w.WriteHeader(200)
return
case <-timeout.C:
log.Printf("TIMED OUT WAITING FOR LOCK")
w.WriteHeader(403)
return
}
case "unlock":
semaphoreStore.V(tag, 1)
log.Printf("UNLOCKED")
w.WriteHeader(200)
return
}
log.Printf("No case was found")
w.WriteHeader(500)
return
}
func main() {
log.Printf("Starting semaphore server")
http.HandleFunc("/", handler)
log.Fatal(http.ListenAndServe(":8080", nil))
}
package main
// :(
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment