@@ -3,6 +3,7 @@ package quickfix
33import (
44 "bytes"
55 "sort"
6+ "sync"
67 "time"
78)
89
@@ -39,6 +40,7 @@ func (t tagSort) Less(i, j int) bool { return t.compare(t.tags[i], t.tags[j]) }
3940type FieldMap struct {
4041 tagLookup map [Tag ]field
4142 tagSort
43+ rwLock * sync.RWMutex
4244}
4345
4446// ascending tags
@@ -49,12 +51,16 @@ func (m *FieldMap) init() {
4951}
5052
5153func (m * FieldMap ) initWithOrdering (ordering tagOrder ) {
54+ m .rwLock = & sync.RWMutex {}
5255 m .tagLookup = make (map [Tag ]field )
5356 m .compare = ordering
5457}
5558
5659//Tags returns all of the Field Tags in this FieldMap
5760func (m FieldMap ) Tags () []Tag {
61+ m .rwLock .RLock ()
62+ defer m .rwLock .RUnlock ()
63+
5864 tags := make ([]Tag , 0 , len (m .tagLookup ))
5965 for t := range m .tagLookup {
6066 tags = append (tags , t )
@@ -70,12 +76,18 @@ func (m FieldMap) Get(parser Field) MessageRejectError {
7076
7177//Has returns true if the Tag is present in this FieldMap
7278func (m FieldMap ) Has (tag Tag ) bool {
79+ m .rwLock .RLock ()
80+ defer m .rwLock .RUnlock ()
81+
7382 _ , ok := m .tagLookup [tag ]
7483 return ok
7584}
7685
7786//GetField parses of a field with Tag tag. Returned reject may indicate the field is not present, or the field value is invalid.
7887func (m FieldMap ) GetField (tag Tag , parser FieldValueReader ) MessageRejectError {
88+ m .rwLock .RLock ()
89+ defer m .rwLock .RUnlock ()
90+
7991 f , ok := m .tagLookup [tag ]
8092 if ! ok {
8193 return ConditionallyRequiredFieldMissing (tag )
@@ -90,6 +102,9 @@ func (m FieldMap) GetField(tag Tag, parser FieldValueReader) MessageRejectError
90102
91103//GetBytes is a zero-copy GetField wrapper for []bytes fields
92104func (m FieldMap ) GetBytes (tag Tag ) ([]byte , MessageRejectError ) {
105+ m .rwLock .RLock ()
106+ defer m .rwLock .RUnlock ()
107+
93108 f , ok := m .tagLookup [tag ]
94109 if ! ok {
95110 return nil , ConditionallyRequiredFieldMissing (tag )
@@ -124,6 +139,9 @@ func (m FieldMap) GetInt(tag Tag) (int, MessageRejectError) {
124139
125140//GetTime is a GetField wrapper for utc timestamp fields
126141func (m FieldMap ) GetTime (tag Tag ) (t time.Time , err MessageRejectError ) {
142+ m .rwLock .RLock ()
143+ defer m .rwLock .RUnlock ()
144+
127145 bytes , err := m .GetBytes (tag )
128146 if err != nil {
129147 return
@@ -148,6 +166,9 @@ func (m FieldMap) GetString(tag Tag) (string, MessageRejectError) {
148166
149167//GetGroup is a Get function specific to Group Fields.
150168func (m FieldMap ) GetGroup (parser FieldGroupReader ) MessageRejectError {
169+ m .rwLock .RLock ()
170+ defer m .rwLock .RUnlock ()
171+
151172 f , ok := m .tagLookup [parser .Tag ()]
152173 if ! ok {
153174 return ConditionallyRequiredFieldMissing (parser .Tag ())
@@ -193,6 +214,9 @@ func (m *FieldMap) SetString(tag Tag, value string) *FieldMap {
193214
194215//Clear purges all fields from field map
195216func (m * FieldMap ) Clear () {
217+ m .rwLock .Lock ()
218+ defer m .rwLock .Unlock ()
219+
196220 m .tags = m .tags [0 :0 ]
197221 for k := range m .tagLookup {
198222 delete (m .tagLookup , k )
@@ -201,6 +225,9 @@ func (m *FieldMap) Clear() {
201225
202226//CopyInto overwrites the given FieldMap with this one
203227func (m * FieldMap ) CopyInto (to * FieldMap ) {
228+ m .rwLock .RLock ()
229+ defer m .rwLock .RUnlock ()
230+
204231 to .tagLookup = make (map [Tag ]field )
205232 for tag , f := range m .tagLookup {
206233 clone := make (field , 1 )
@@ -213,6 +240,9 @@ func (m *FieldMap) CopyInto(to *FieldMap) {
213240}
214241
215242func (m * FieldMap ) add (f field ) {
243+ m .rwLock .Lock ()
244+ defer m .rwLock .Unlock ()
245+
216246 t := fieldTag (f )
217247 if _ , ok := m .tagLookup [t ]; ! ok {
218248 m .tags = append (m .tags , t )
@@ -222,6 +252,9 @@ func (m *FieldMap) add(f field) {
222252}
223253
224254func (m * FieldMap ) getOrCreate (tag Tag ) field {
255+ m .rwLock .Lock ()
256+ defer m .rwLock .Unlock ()
257+
225258 if f , ok := m .tagLookup [tag ]; ok {
226259 f = f [:1 ]
227260 return f
@@ -242,6 +275,9 @@ func (m *FieldMap) Set(field FieldWriter) *FieldMap {
242275
243276//SetGroup is a setter specific to group fields
244277func (m * FieldMap ) SetGroup (field FieldGroupWriter ) * FieldMap {
278+ m .rwLock .Lock ()
279+ defer m .rwLock .Unlock ()
280+
245281 _ , ok := m .tagLookup [field .Tag ()]
246282 if ! ok {
247283 m .tags = append (m .tags , field .Tag ())
@@ -256,6 +292,9 @@ func (m *FieldMap) sortedTags() []Tag {
256292}
257293
258294func (m FieldMap ) write (buffer * bytes.Buffer ) {
295+ m .rwLock .Lock ()
296+ defer m .rwLock .Unlock ()
297+
259298 for _ , tag := range m .sortedTags () {
260299 if f , ok := m .tagLookup [tag ]; ok {
261300 writeField (f , buffer )
@@ -264,6 +303,9 @@ func (m FieldMap) write(buffer *bytes.Buffer) {
264303}
265304
266305func (m FieldMap ) total () int {
306+ m .rwLock .RLock ()
307+ defer m .rwLock .RUnlock ()
308+
267309 total := 0
268310 for _ , fields := range m .tagLookup {
269311 for _ , tv := range fields {
@@ -279,6 +321,9 @@ func (m FieldMap) total() int {
279321}
280322
281323func (m FieldMap ) length () int {
324+ m .rwLock .RLock ()
325+ defer m .rwLock .RUnlock ()
326+
282327 length := 0
283328 for _ , fields := range m .tagLookup {
284329 for _ , tv := range fields {
0 commit comments