internal/atomic: move to separate package
diff --git a/connection.go b/connection.go
index 948a595..6f5c700 100644
--- a/connection.go
+++ b/connection.go
@@ -9,6 +9,8 @@
package mysql
import (
+ "github.com/go-sql-driver/mysql/internal/atomic"
+
"database/sql/driver"
"io"
"net"
@@ -47,8 +49,8 @@
watcher chan<- mysqlContext
closech chan struct{}
finished chan<- struct{}
- canceled atomicError // set non-nil if conn is canceled
- closed atomicBool // set when conn is closed, before closech is closed
+ canceled atomic.Error // set non-nil if conn is canceled
+ closed atomic.Bool // set when conn is closed, before closech is closed
}
// Handles parameters set in DSN after the connection is established
diff --git a/internal/atomic/atomic.go b/internal/atomic/atomic.go
new file mode 100644
index 0000000..a794491
--- /dev/null
+++ b/internal/atomic/atomic.go
@@ -0,0 +1,73 @@
+// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
+//
+// Copyright 2017 The Go-MySQL-Driver Authors. All rights reserved.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this file,
+// You can obtain one at http://mozilla.org/MPL/2.0/.
+
+package atomic
+
+import (
+ "sync/atomic"
+)
+
+// noCopy may be embedded into structs which must not be copied
+// after the first use.
+//
+// See https://github.com/golang/go/issues/8005#issuecomment-190753527
+// for details.
+type noCopy struct{}
+
+// Lock is a no-op used by -copylocks checker from `go vet`.
+func (*noCopy) Lock() {}
+
+// Bool is a wrapper around uint32 for usage as a boolean value with
+// atomic access.
+type Bool struct {
+ _noCopy noCopy
+ value uint32
+}
+
+// IsSet returns wether the current boolean value is true
+func (b *Bool) IsSet() bool {
+ return atomic.LoadUint32(&b.value) > 0
+}
+
+// Set sets the value of the bool regardless of the previous value
+func (b *Bool) Set(value bool) {
+ if value {
+ atomic.StoreUint32(&b.value, 1)
+ } else {
+ atomic.StoreUint32(&b.value, 0)
+ }
+}
+
+// TrySet sets the value of the bool and returns wether the value changed
+func (b *Bool) TrySet(value bool) bool {
+ if value {
+ return atomic.SwapUint32(&b.value, 1) == 0
+ }
+ return atomic.SwapUint32(&b.value, 0) > 0
+}
+
+// Error is a wrapper for atomically accessed error values
+type Error struct {
+ _noCopy noCopy
+ value atomic.Value
+}
+
+// Set sets the error value regardless of the previous value.
+// The value must not be nil
+func (e *Error) Set(value error) {
+ e.value.Store(value)
+}
+
+// Value returns the current error value
+func (e *Error) Value() error {
+ if v := e.value.Load(); v != nil {
+ // this will panic if the value doesn't implement the error interface
+ return v.(error)
+ }
+ return nil
+}
diff --git a/internal/atomic/atomic_test.go b/internal/atomic/atomic_test.go
new file mode 100644
index 0000000..f22dbb3
--- /dev/null
+++ b/internal/atomic/atomic_test.go
@@ -0,0 +1,99 @@
+// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
+//
+// Copyright 2017 The Go-MySQL-Driver Authors. All rights reserved.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this file,
+// You can obtain one at http://mozilla.org/MPL/2.0/.
+
+package atomic
+
+import (
+ "errors"
+ "testing"
+)
+
+var (
+ errOne = errors.New("one")
+ errTwo = errors.New("two")
+)
+
+func TestAtomicBool(t *testing.T) {
+ var b Bool
+ if b.IsSet() {
+ t.Fatal("Expected value to be false")
+ }
+
+ b.Set(true)
+ if b.value != 1 {
+ t.Fatal("Set(true) did not set value to 1")
+ }
+ if !b.IsSet() {
+ t.Fatal("Expected value to be true")
+ }
+
+ b.Set(true)
+ if !b.IsSet() {
+ t.Fatal("Expected value to be true")
+ }
+
+ b.Set(false)
+ if b.value != 0 {
+ t.Fatal("Set(false) did not set value to 0")
+ }
+ if b.IsSet() {
+ t.Fatal("Expected value to be false")
+ }
+
+ b.Set(false)
+ if b.IsSet() {
+ t.Fatal("Expected value to be false")
+ }
+ if b.TrySet(false) {
+ t.Fatal("Expected TrySet(false) to fail")
+ }
+ if !b.TrySet(true) {
+ t.Fatal("Expected TrySet(true) to succeed")
+ }
+ if !b.IsSet() {
+ t.Fatal("Expected value to be true")
+ }
+
+ b.Set(true)
+ if !b.IsSet() {
+ t.Fatal("Expected value to be true")
+ }
+ if b.TrySet(true) {
+ t.Fatal("Expected TrySet(true) to fail")
+ }
+ if !b.TrySet(false) {
+ t.Fatal("Expected TrySet(false) to succeed")
+ }
+ if b.IsSet() {
+ t.Fatal("Expected value to be false")
+ }
+
+ b._noCopy.Lock() // we've "tested" it ¯\_(ツ)_/¯
+}
+
+func TestAtomicError(t *testing.T) {
+ var e Error
+ if e.Value() != nil {
+ t.Fatal("Expected value to be nil")
+ }
+
+ e.Set(errOne)
+ if v := e.Value(); v != errOne {
+ if v == nil {
+ t.Fatal("Value is still nil")
+ }
+ t.Fatal("Error did not match")
+ }
+ e.Set(errTwo)
+ if e.Value() == errOne {
+ t.Fatal("Error still matches old error")
+ }
+ if v := e.Value(); v != errTwo {
+ t.Fatal("Error did not match")
+ }
+}
diff --git a/utils.go b/utils.go
index 82da830..0c3729d 100644
--- a/utils.go
+++ b/utils.go
@@ -17,7 +17,6 @@
"io"
"strings"
"sync"
- "sync/atomic"
"time"
)
@@ -756,67 +755,3 @@
return buf[:pos]
}
-
-/******************************************************************************
-* Sync utils *
-******************************************************************************/
-
-// noCopy may be embedded into structs which must not be copied
-// after the first use.
-//
-// See https://github.com/golang/go/issues/8005#issuecomment-190753527
-// for details.
-type noCopy struct{}
-
-// Lock is a no-op used by -copylocks checker from `go vet`.
-func (*noCopy) Lock() {}
-
-// atomicBool is a wrapper around uint32 for usage as a boolean value with
-// atomic access.
-type atomicBool struct {
- _noCopy noCopy
- value uint32
-}
-
-// IsSet returns wether the current boolean value is true
-func (ab *atomicBool) IsSet() bool {
- return atomic.LoadUint32(&ab.value) > 0
-}
-
-// Set sets the value of the bool regardless of the previous value
-func (ab *atomicBool) Set(value bool) {
- if value {
- atomic.StoreUint32(&ab.value, 1)
- } else {
- atomic.StoreUint32(&ab.value, 0)
- }
-}
-
-// TrySet sets the value of the bool and returns wether the value changed
-func (ab *atomicBool) TrySet(value bool) bool {
- if value {
- return atomic.SwapUint32(&ab.value, 1) == 0
- }
- return atomic.SwapUint32(&ab.value, 0) > 0
-}
-
-// atomicBool is a wrapper for atomically accessed error values
-type atomicError struct {
- _noCopy noCopy
- value atomic.Value
-}
-
-// Set sets the error value regardless of the previous value.
-// The value must not be nil
-func (ae *atomicError) Set(value error) {
- ae.value.Store(value)
-}
-
-// Value returns the current error value
-func (ae *atomicError) Value() error {
- if v := ae.value.Load(); v != nil {
- // this will panic if the value doesn't implement the error interface
- return v.(error)
- }
- return nil
-}
diff --git a/utils_test.go b/utils_test.go
index 0041892..0d6c668 100644
--- a/utils_test.go
+++ b/utils_test.go
@@ -195,83 +195,3 @@
expect("foo''bar", "foo'bar") // affected
expect("foo\"bar", "foo\"bar") // not affected
}
-
-func TestAtomicBool(t *testing.T) {
- var ab atomicBool
- if ab.IsSet() {
- t.Fatal("Expected value to be false")
- }
-
- ab.Set(true)
- if ab.value != 1 {
- t.Fatal("Set(true) did not set value to 1")
- }
- if !ab.IsSet() {
- t.Fatal("Expected value to be true")
- }
-
- ab.Set(true)
- if !ab.IsSet() {
- t.Fatal("Expected value to be true")
- }
-
- ab.Set(false)
- if ab.value != 0 {
- t.Fatal("Set(false) did not set value to 0")
- }
- if ab.IsSet() {
- t.Fatal("Expected value to be false")
- }
-
- ab.Set(false)
- if ab.IsSet() {
- t.Fatal("Expected value to be false")
- }
- if ab.TrySet(false) {
- t.Fatal("Expected TrySet(false) to fail")
- }
- if !ab.TrySet(true) {
- t.Fatal("Expected TrySet(true) to succeed")
- }
- if !ab.IsSet() {
- t.Fatal("Expected value to be true")
- }
-
- ab.Set(true)
- if !ab.IsSet() {
- t.Fatal("Expected value to be true")
- }
- if ab.TrySet(true) {
- t.Fatal("Expected TrySet(true) to fail")
- }
- if !ab.TrySet(false) {
- t.Fatal("Expected TrySet(false) to succeed")
- }
- if ab.IsSet() {
- t.Fatal("Expected value to be false")
- }
-
- ab._noCopy.Lock() // we've "tested" it ¯\_(ツ)_/¯
-}
-
-func TestAtomicError(t *testing.T) {
- var ae atomicError
- if ae.Value() != nil {
- t.Fatal("Expected value to be nil")
- }
-
- ae.Set(ErrMalformPkt)
- if v := ae.Value(); v != ErrMalformPkt {
- if v == nil {
- t.Fatal("Value is still nil")
- }
- t.Fatal("Error did not match")
- }
- ae.Set(ErrPktSync)
- if ae.Value() == ErrMalformPkt {
- t.Fatal("Error still matches old error")
- }
- if v := ae.Value(); v != ErrPktSync {
- t.Fatal("Error did not match")
- }
-}