Merge pull request #30 from dadgar/b-concurrent

Allow library to be used in parallel
diff --git a/cronexpr_parse.go b/cronexpr_parse.go
index be6ef17..a9fe746 100644
--- a/cronexpr_parse.go
+++ b/cronexpr_parse.go
@@ -19,6 +19,7 @@
 	"regexp"
 	"sort"
 	"strings"
+	"sync"
 )
 
 /******************************************************************************/
@@ -194,6 +195,7 @@
 	fieldFinder               = regexp.MustCompile(`\S+`)
 	entryFinder               = regexp.MustCompile(`[^,]+`)
 	layoutRegexp              = make(map[string]*regexp.Regexp)
+	layoutRegexpLock          sync.Mutex
 )
 
 /******************************************************************************/
@@ -488,6 +490,9 @@
 /******************************************************************************/
 
 func makeLayoutRegexp(layout, value string) *regexp.Regexp {
+	layoutRegexpLock.Lock()
+	defer layoutRegexpLock.Unlock()
+
 	layout = strings.Replace(layout, `%value%`, value, -1)
 	re := layoutRegexp[layout]
 	if re == nil {
diff --git a/cronexpr_test.go b/cronexpr_test.go
index f170769..6ccf7ab 100644
--- a/cronexpr_test.go
+++ b/cronexpr_test.go
@@ -10,15 +10,13 @@
  *
  */
 
-package cronexpr_test
+package cronexpr
 
 /******************************************************************************/
 
 import (
 	"testing"
 	"time"
-
-	"github.com/gorhill/cronexpr"
 )
 
 /******************************************************************************/
@@ -203,9 +201,9 @@
 	for _, test := range crontests {
 		for _, times := range test.times {
 			from, _ := time.Parse("2006-01-02 15:04:05", times.from)
-			expr, err := cronexpr.Parse(test.expr)
+			expr, err := Parse(test.expr)
 			if err != nil {
-				t.Errorf(`cronexpr.Parse("%s") returned "%s"`, test.expr, err.Error())
+				t.Errorf(`Parse("%s") returned "%s"`, test.expr, err.Error())
 			}
 			next := expr.Next(from)
 			nextstr := next.Format(test.layout)
@@ -220,17 +218,17 @@
 
 func TestZero(t *testing.T) {
 	from, _ := time.Parse("2006-01-02", "2013-08-31")
-	next := cronexpr.MustParse("* * * * * 1980").Next(from)
+	next := MustParse("* * * * * 1980").Next(from)
 	if next.IsZero() == false {
 		t.Error(`("* * * * * 1980").Next("2013-08-31").IsZero() returned 'false', expected 'true'`)
 	}
 
-	next = cronexpr.MustParse("* * * * * 2050").Next(from)
+	next = MustParse("* * * * * 2050").Next(from)
 	if next.IsZero() == true {
 		t.Error(`("* * * * * 2050").Next("2013-08-31").IsZero() returned 'true', expected 'false'`)
 	}
 
-	next = cronexpr.MustParse("* * * * * 2099").Next(time.Time{})
+	next = MustParse("* * * * * 2099").Next(time.Time{})
 	if next.IsZero() == false {
 		t.Error(`("* * * * * 2014").Next(time.Time{}).IsZero() returned 'true', expected 'false'`)
 	}
@@ -247,7 +245,7 @@
 		"Sat, 29 Nov 2014 00:00:00",
 	}
 	from, _ := time.Parse("2006-01-02 15:04:05", "2013-09-02 08:44:30")
-	result := cronexpr.MustParse("0 0 * * 6#5").NextN(from, uint(len(expected)))
+	result := MustParse("0 0 * * 6#5").NextN(from, uint(len(expected)))
 	if len(result) != len(expected) {
 		t.Errorf(`MustParse("0 0 * * 6#5").NextN("2013-09-02 08:44:30", 5):\n"`)
 		t.Errorf(`  Expected %d returned time values but got %d instead`, len(expected), len(result))
@@ -270,7 +268,7 @@
 		"Mon, 2 Sep 2013 09:05:00",
 	}
 	from, _ := time.Parse("2006-01-02 15:04:05", "2013-09-02 08:44:32")
-	result := cronexpr.MustParse("*/5 * * * *").NextN(from, uint(len(expected)))
+	result := MustParse("*/5 * * * *").NextN(from, uint(len(expected)))
 	if len(result) != len(expected) {
 		t.Errorf(`MustParse("*/5 * * * *").NextN("2013-09-02 08:44:30", 5):\n"`)
 		t.Errorf(`  Expected %d returned time values but got %d instead`, len(expected), len(result))
@@ -278,30 +276,30 @@
 	for i, next := range result {
 		nextStr := next.Format("Mon, 2 Jan 2006 15:04:05")
 		if nextStr != expected[i] {
-		t.Errorf(`MustParse("*/5 * * * *").NextN("2013-09-02 08:44:30", 5):\n"`)
+			t.Errorf(`MustParse("*/5 * * * *").NextN("2013-09-02 08:44:30", 5):\n"`)
 			t.Errorf(`  result[%d]: expected "%s" but got "%s"`, i, expected[i], nextStr)
 		}
 	}
 }
 
 // Issue: https://github.com/gorhill/cronexpr/issues/16
-func TestInterval_Interval60Issue(t *testing.T){
-	_, err := cronexpr.Parse("*/60 * * * * *")
+func TestInterval_Interval60Issue(t *testing.T) {
+	_, err := Parse("*/60 * * * * *")
 	if err == nil {
 		t.Errorf("parsing with interval 60 should return err")
 	}
 
-	_, err = cronexpr.Parse("*/61 * * * * *")
+	_, err = Parse("*/61 * * * * *")
 	if err == nil {
 		t.Errorf("parsing with interval 61 should return err")
 	}
 
-	_, err = cronexpr.Parse("2/60 * * * * *")
+	_, err = Parse("2/60 * * * * *")
 	if err == nil {
 		t.Errorf("parsing with interval 60 should return err")
 	}
 
-	_, err = cronexpr.Parse("2-20/61 * * * * *")
+	_, err = Parse("2-20/61 * * * * *")
 	if err == nil {
 		t.Errorf("parsing with interval 60 should return err")
 	}
@@ -322,14 +320,14 @@
 
 func BenchmarkParse(b *testing.B) {
 	for i := 0; i < b.N; i++ {
-		_ = cronexpr.MustParse(benchmarkExpressions[i%benchmarkExpressionsLen])
+		_ = MustParse(benchmarkExpressions[i%benchmarkExpressionsLen])
 	}
 }
 
 func BenchmarkNext(b *testing.B) {
-	exprs := make([]*cronexpr.Expression, benchmarkExpressionsLen)
+	exprs := make([]*Expression, benchmarkExpressionsLen)
 	for i := 0; i < benchmarkExpressionsLen; i++ {
-		exprs[i] = cronexpr.MustParse(benchmarkExpressions[i])
+		exprs[i] = MustParse(benchmarkExpressions[i])
 	}
 	from := time.Now()
 	b.ResetTimer()
diff --git a/example_test.go b/example_test.go
index 3dc27d0..f91dc9e 100644
--- a/example_test.go
+++ b/example_test.go
@@ -8,15 +8,13 @@
  *
  */
 
-package cronexpr_test
+package cronexpr
 
 /******************************************************************************/
 
 import (
 	"fmt"
 	"time"
-
-	"github.com/gorhill/cronexpr"
 )
 
 /******************************************************************************/
@@ -24,7 +22,7 @@
 // ExampleMustParse
 func ExampleMustParse() {
 	t := time.Date(2013, time.August, 31, 0, 0, 0, 0, time.UTC)
-	nextTimes := cronexpr.MustParse("0 0 29 2 *").NextN(t, 5)
+	nextTimes := MustParse("0 0 29 2 *").NextN(t, 5)
 	for i := range nextTimes {
 		fmt.Println(nextTimes[i].Format(time.RFC1123))
 		// Output: