github.com/goplusjs/gopherjs@v1.2.6-0.20211206034512-f187917453b8/compiler/natives/src/sync/sync.go (about)

     1  // +build js
     2  // +build !go1.13
     3  
     4  package sync
     5  
     6  import "github.com/gopherjs/gopherjs/js"
     7  
     8  var semWaiters = make(map[*uint32][]chan bool)
     9  
    10  // semAwoken tracks the number of waiters awoken by runtime_Semrelease (`ch <- true`)
    11  // that have not yet acquired the semaphore (`<-ch` in runtime_SemacquireMutex).
    12  //
    13  // This prevents a new call to runtime_SemacquireMutex to wrongly acquire the semaphore
    14  // in between (because runtime_Semrelease has already incremented the semaphore while
    15  // all the pending calls to runtime_SemacquireMutex have not yet received from the channel
    16  // and thus decremented the semaphore).
    17  //
    18  // See https://github.com/gopherjs/gopherjs/issues/736.
    19  var semAwoken = make(map[*uint32]uint32)
    20  
    21  func runtime_Semacquire(s *uint32) {
    22  	runtime_SemacquireMutex(s, false)
    23  }
    24  
    25  // SemacquireMutex is like Semacquire, but for profiling contended Mutexes.
    26  // Mutex profiling is not supported, so just use the same implementation as runtime_Semacquire.
    27  // TODO: Investigate this. If it's possible to implement, consider doing so, otherwise remove this comment.
    28  func runtime_SemacquireMutex(s *uint32, lifo bool) {
    29  	if (*s - semAwoken[s]) == 0 {
    30  		ch := make(chan bool)
    31  		if lifo {
    32  			semWaiters[s] = append([]chan bool{ch}, semWaiters[s]...)
    33  		} else {
    34  			semWaiters[s] = append(semWaiters[s], ch)
    35  		}
    36  		<-ch
    37  		semAwoken[s] -= 1
    38  		if semAwoken[s] == 0 {
    39  			delete(semAwoken, s)
    40  		}
    41  	}
    42  	*s--
    43  }
    44  
    45  func runtime_Semrelease(s *uint32, handoff bool) {
    46  	// TODO: Use handoff if needed/possible.
    47  	*s++
    48  
    49  	w := semWaiters[s]
    50  	if len(w) == 0 {
    51  		return
    52  	}
    53  
    54  	ch := w[0]
    55  	w = w[1:]
    56  	semWaiters[s] = w
    57  	if len(w) == 0 {
    58  		delete(semWaiters, s)
    59  	}
    60  
    61  	semAwoken[s] += 1
    62  
    63  	ch <- true
    64  }
    65  
    66  func runtime_notifyListCheck(size uintptr) {}
    67  
    68  func runtime_canSpin(i int) bool {
    69  	return false
    70  }
    71  
    72  // Copy of time.runtimeNano.
    73  func runtime_nanotime() int64 {
    74  	const millisecond = 1000000
    75  	return js.Global.Get("Date").New().Call("getTime").Int64() * millisecond
    76  }
    77  
    78  // Implemented in runtime.
    79  func throw(s string) {
    80  	js.Global.Call("$throwRuntimeError", s)
    81  }