Permalink
Browse files

nosync for some core packages

  • Loading branch information...
1 parent 1636d68 commit ac5f8a84b1bb5392d20a6bf1d671a7174fb539fe @neelance neelance committed Dec 6, 2014
Showing with 144 additions and 10 deletions.
  1. +17 −5 build/build.go
  2. +25 −5 nosync/{nosync.go → mutex.go}
  3. +39 −0 nosync/once.go
  4. +63 −0 nosync/pool.go
View
@@ -57,13 +57,12 @@ func Import(path string, mode build.ImportMode, archSuffix string) (*build.Packa
if err != nil {
return nil, err
}
- if path == "runtime" {
+ switch path {
+ case "runtime":
pkg.GoFiles = []string{"error.go", fmt.Sprintf("zgoos_%s.go", runtime.GOOS), "zversion.go"}
- }
- if path == "runtime/pprof" {
+ case "runtime/pprof":
pkg.GoFiles = nil
- }
- if path == "hash/crc32" {
+ case "hash/crc32":
pkg.GoFiles = []string{"crc32.go", "crc32_generic.go"}
}
if pkg.IsCommand() {
@@ -157,6 +156,19 @@ func Parse(pkg *build.Package, fileSet *token.FileSet) ([]*ast.File, error) {
continue
}
+ switch pkg.ImportPath {
+ case "crypto/rand", "encoding/json", "math/big", "math/rand", "testing", "time":
+ for _, spec := range file.Imports {
+ path, _ := strconv.Unquote(spec.Path.Value)
+ if path == "sync" {
+ if spec.Name == nil {
+ spec.Name = ast.NewIdent("sync")
+ }
+ spec.Path.Value = `"github.com/gopherjs/gopherjs/nosync"`
+ }
+ }
+ }
+
for _, decl := range file.Decls {
switch d := decl.(type) {
case *ast.FuncDecl:
@@ -29,17 +29,14 @@ type RWMutex struct {
// Lock locks m for writing. It is a run-time error if rw is already locked for reading or writing.
func (rw *RWMutex) Lock() {
- println("Lock")
if rw.readLockCounter != 0 || rw.writeLocked {
- println("FAIL")
panic("nosync: mutex is already locked")
}
rw.writeLocked = true
}
// Unlock unlocks rw for writing. It is a run-time error if rw is not locked for writing.
func (rw *RWMutex) Unlock() {
- println("Unlock")
if !rw.writeLocked {
panic("nosync: unlock of unlocked mutex")
}
@@ -48,7 +45,6 @@ func (rw *RWMutex) Unlock() {
// RLock locks m for reading. It is a run-time error if rw is already locked for reading or writing.
func (rw *RWMutex) RLock() {
- println("RLock")
if rw.writeLocked {
panic("nosync: mutex is already locked")
}
@@ -57,9 +53,33 @@ func (rw *RWMutex) RLock() {
// RUnlock undoes a single RLock call; it does not affect other simultaneous readers. It is a run-time error if rw is not locked for reading.
func (rw *RWMutex) RUnlock() {
- println("RUnlock")
if rw.readLockCounter == 0 {
panic("nosync: unlock of unlocked mutex")
}
rw.readLockCounter--
}
+
+// WaitGroup is a dummy which is non-blocking.
+type WaitGroup struct {
+ counter int
+}
+
+// Add adds delta, which may be negative, to the WaitGroup If the counter goes negative, Add panics.
+func (wg *WaitGroup) Add(delta int) {
+ wg.counter += delta
+ if wg.counter < 0 {
+ panic("sync: negative WaitGroup counter")
+ }
+}
+
+// Done decrements the WaitGroup counter.
+func (wg *WaitGroup) Done() {
+ wg.Add(-1)
+}
+
+// Wait panics if the WaitGroup counter is not zero.
+func (wg *WaitGroup) Wait() {
+ if wg.counter != 0 {
+ panic("sync: WaitGroup counter not zero")
+ }
+}
View
@@ -0,0 +1,39 @@
+package nosync
+
+// Once is an object that will perform exactly one action.
+type Once struct {
+ doing bool
+ done bool
+}
+
+// Do calls the function f if and only if Do is being called for the
+// first time for this instance of Once. In other words, given
+// var once Once
+// if once.Do(f) is called multiple times, only the first call will invoke f,
+// even if f has a different value in each invocation. A new instance of
+// Once is required for each function to execute.
+//
+// Do is intended for initialization that must be run exactly once. Since f
+// is niladic, it may be necessary to use a function literal to capture the
+// arguments to a function to be invoked by Do:
+// config.once.Do(func() { config.init(filename) })
+//
+// If f causes Do to be called, it will panic.
+//
+// If f panics, Do considers it to have returned; future calls of Do return
+// without calling f.
+//
+func (o *Once) Do(f func()) {
+ if o.done {
+ return
+ }
+ if o.doing {
+ panic("nosync: Do called within f")
+ }
+ o.doing = true
+ defer func() {
+ o.doing = false
+ o.done = true
+ }()
+ f()
+}
View
@@ -0,0 +1,63 @@
+package nosync
+
+// A Pool is a set of temporary objects that may be individually saved and
+// retrieved.
+//
+// Any item stored in the Pool may be removed automatically at any time without
+// notification. If the Pool holds the only reference when this happens, the
+// item might be deallocated.
+//
+// A Pool is safe for use by multiple goroutines simultaneously.
+//
+// Pool's purpose is to cache allocated but unused items for later reuse,
+// relieving pressure on the garbage collector. That is, it makes it easy to
+// build efficient, thread-safe free lists. However, it is not suitable for all
+// free lists.
+//
+// An appropriate use of a Pool is to manage a group of temporary items
+// silently shared among and potentially reused by concurrent independent
+// clients of a package. Pool provides a way to amortize allocation overhead
+// across many clients.
+//
+// An example of good use of a Pool is in the fmt package, which maintains a
+// dynamically-sized store of temporary output buffers. The store scales under
+// load (when many goroutines are actively printing) and shrinks when
+// quiescent.
+//
+// On the other hand, a free list maintained as part of a short-lived object is
+// not a suitable use for a Pool, since the overhead does not amortize well in
+// that scenario. It is more efficient to have such objects implement their own
+// free list.
+//
+type Pool struct {
+ store []interface{}
+ New func() interface{}
+}
+
+// Get selects an arbitrary item from the Pool, removes it from the
+// Pool, and returns it to the caller.
+// Get may choose to ignore the pool and treat it as empty.
+// Callers should not assume any relation between values passed to Put and
+// the values returned by Get.
+//
+// If Get would otherwise return nil and p.New is non-nil, Get returns
+// the result of calling p.New.
+func (p *Pool) Get() interface{} {
+ if len(p.store) == 0 {
+ if p.New != nil {
+ return p.New()
+ }
+ return nil
+ }
+ x := p.store[len(p.store)-1]
+ p.store = p.store[:len(p.store)-1]
+ return x
+}
+
+// Put adds x to the pool.
+func (p *Pool) Put(x interface{}) {
+ if x == nil {
+ return
+ }
+ p.store = append(p.store, x)
+}

0 comments on commit ac5f8a8

Please sign in to comment.