9fans.net/go@v0.0.7/cmd/acme/internal/util/util.go (about)

     1  // #include <u.h>
     2  // #include <libc.h>
     3  // #include <draw.h>
     4  // #include <thread.h>
     5  // #include <cursor.h>
     6  // #include <mouse.h>
     7  // #include <keyboard.h>
     8  // #include <frame.h>
     9  // #include <fcall.h>
    10  // #include <plumb.h>
    11  // #include <libsec.h>
    12  // #include "dat.h"
    13  // #include "fns.h"
    14  
    15  package util
    16  
    17  import (
    18  	"log"
    19  	"sync"
    20  	"sync/atomic"
    21  )
    22  
    23  func Min(a int, b int) int {
    24  	if a < b {
    25  		return a
    26  	}
    27  	return b
    28  }
    29  
    30  func Max(a int, b int) int {
    31  	if a > b {
    32  		return a
    33  	}
    34  	return b
    35  }
    36  
    37  func Fatal(s string) {
    38  	log.Fatalf("acme: %s\n", s)
    39  }
    40  
    41  var locks struct {
    42  	mu   sync.Mutex
    43  	cond sync.Cond
    44  }
    45  
    46  func init() {
    47  	locks.cond.L = &locks.mu
    48  }
    49  
    50  type QLock struct {
    51  	held uint32
    52  }
    53  
    54  func (l *QLock) TryLock() bool {
    55  	return atomic.CompareAndSwapUint32(&l.held, 0, 1)
    56  }
    57  
    58  func (l *QLock) Unlock() {
    59  	v := atomic.SwapUint32(&l.held, 0)
    60  	if v == 0 {
    61  		panic("Unlock of unlocked lock")
    62  	}
    63  	if v > 1 {
    64  		locks.cond.Broadcast()
    65  	}
    66  }
    67  
    68  func (l *QLock) Lock() {
    69  	if atomic.AddUint32(&l.held, 1) == 1 {
    70  		return
    71  	}
    72  	locks.mu.Lock()
    73  	defer locks.mu.Unlock()
    74  
    75  	for atomic.AddUint32(&l.held, 1) != 1 {
    76  		locks.cond.Wait()
    77  	}
    78  }
    79  
    80  func Incref(p *uint32) { atomic.AddUint32(p, 1) }
    81  
    82  func Decref(p *uint32) uint32 {
    83  	return atomic.AddUint32(p, ^uint32(0))
    84  }