@@ -19,18 +19,19 @@ import (
19
19
"log"
20
20
"runtime/debug"
21
21
"sync"
22
+ "sync/atomic"
22
23
)
23
24
24
25
type MessageNumber uint32
25
26
26
27
// A BLIP message. It could be a request or response or error, and it could be from me or the peer.
27
28
type Message struct {
28
- Outgoing bool // Is this a message created locally?
29
- Sender * Sender // The connection that sent this message.
30
- Properties Properties // The message's metadata, similar to HTTP headers.
31
- body []byte // The message body. MIME type is defined by "Content-Type" property
32
- number MessageNumber // The sequence number of the message in the connection.
33
- flags frameFlags // Message flags as seen on the first frame.
29
+ Outgoing bool // Is this a message created locally?
30
+ Sender * Sender // The connection that sent this message.
31
+ Properties Properties // The message's metadata, similar to HTTP headers.
32
+ body []byte // The message body. MIME type is defined by "Content-Type" property
33
+ number MessageNumber // The sequence number of the message in the connection.
34
+ flags atomic. Pointer [ frameFlags ] // Message flags as seen on the first frame.
34
35
bytesSent uint64
35
36
bytesAcked uint64
36
37
@@ -56,7 +57,7 @@ func (message *Message) Close() (err error) {
56
57
57
58
// Returns a string describing the message for debugging purposes
58
59
func (message * Message ) String () string {
59
- return frameString (message .number , message .flags )
60
+ return frameString (message .number , * message .flags . Load () )
60
61
}
61
62
62
63
func frameString (number MessageNumber , flags frameFlags ) string {
@@ -72,12 +73,13 @@ func frameString(number MessageNumber, flags frameFlags) string {
72
73
73
74
// Creates a new outgoing request.
74
75
func NewRequest () * Message {
75
- return & Message {
76
- flags : frameFlags (RequestType ),
76
+ m := & Message {
77
77
Outgoing : true ,
78
78
Properties : Properties {},
79
79
cond : sync .NewCond (& sync.Mutex {}),
80
80
}
81
+ m .flags .Store (ptr (frameFlags (RequestType )))
82
+ return m
81
83
}
82
84
83
85
// The order in which a request message was sent.
@@ -90,17 +92,17 @@ func (message *Message) SerialNumber() MessageNumber {
90
92
}
91
93
92
94
// The type of message: request, response or error
93
- func (message * Message ) Type () MessageType { return MessageType (message .flags .messageType ()) }
95
+ func (message * Message ) Type () MessageType { return MessageType (message .flags .Load (). messageType ()) }
94
96
95
97
// True if the message has Urgent priority.
96
- func (message * Message ) Urgent () bool { return message .flags & kUrgent != 0 }
98
+ func (message * Message ) Urgent () bool { return * message .flags . Load () & kUrgent != 0 }
97
99
98
100
// True if the message doesn't want a reply.
99
- func (message * Message ) NoReply () bool { return message .flags & kNoReply != 0 }
101
+ func (message * Message ) NoReply () bool { return * message .flags . Load () & kNoReply != 0 }
100
102
101
103
// True if the message's body was GZIP-compressed in transit.
102
104
// (This is for informative purposes only; you don't need to unzip it yourself!)
103
- func (message * Message ) Compressed () bool { return message .flags & kCompressed != 0 }
105
+ func (message * Message ) Compressed () bool { return * message .flags . Load () & kCompressed != 0 }
104
106
105
107
// Marks an outgoing message as having high priority. Urgent messages get a higher amount of
106
108
// bandwidth. This is useful for streaming media.
@@ -125,11 +127,13 @@ func (request *Message) SetNoReply(noReply bool) {
125
127
126
128
func (message * Message ) setFlag (flag frameFlags , value bool ) {
127
129
message .assertMutable ()
130
+ flags := * message .flags .Load ()
128
131
if value {
129
- message . flags |= flag
132
+ flags |= flag
130
133
} else {
131
- message . flags &^= flag
134
+ flags &^= flag
132
135
}
136
+ message .flags .Store (& flags )
133
137
}
134
138
135
139
func (message * Message ) assertMutable () {
@@ -228,7 +232,7 @@ func (m *Message) SetJSONBodyAsBytes(jsonBytes []byte) {
228
232
// Multiple calls return the same object.
229
233
// If called on a NoReply request, this returns nil.
230
234
func (request * Message ) Response () * Message {
231
- if request .flags & kNoReply != 0 {
235
+ if * request .flags . Load () & kNoReply != 0 {
232
236
return nil
233
237
}
234
238
if request .Type () != RequestType {
@@ -257,7 +261,8 @@ func (request *Message) Response() *Message {
257
261
return request .response
258
262
}
259
263
response := request .createResponse ()
260
- response .flags |= request .flags & kUrgent
264
+ newFlags := * response .flags .Load () | * request .flags .Load ()& kUrgent
265
+ response .flags .Store (& newFlags )
261
266
response .Properties = Properties {}
262
267
request .response = response
263
268
return response
@@ -271,7 +276,8 @@ func (response *Message) SetError(errDomain string, errCode int, message string)
271
276
if response .Type () == RequestType {
272
277
panic ("Can't call SetError on a request" )
273
278
}
274
- response .flags = (response .flags &^ kTypeMask ) | frameFlags (ErrorType )
279
+ newFlags := * response .flags .Load ()&^kTypeMask | frameFlags (ErrorType )
280
+ response .flags .Store (& newFlags )
275
281
response .Properties = Properties {
276
282
"Error-Domain" : errDomain ,
277
283
"Error-Code" : fmt .Sprintf ("%d" , errCode ),
@@ -285,13 +291,14 @@ func (response *Message) SetError(errDomain string, errCode int, message string)
285
291
//////// INTERNALS:
286
292
287
293
func newIncomingMessage (sender * Sender , number MessageNumber , flags frameFlags , reader io.ReadCloser ) * Message {
288
- return & Message {
294
+ m := & Message {
289
295
Sender : sender ,
290
- flags : flags | kMoreComing ,
291
296
number : number ,
292
297
reader : reader ,
293
298
cond : sync .NewCond (& sync.Mutex {}),
294
299
}
300
+ m .flags .Store (ptr (flags | kMoreComing ))
301
+ return m
295
302
}
296
303
297
304
// Creates an incoming message given properties and body; exposed only for testing.
@@ -309,16 +316,17 @@ func NewParsedIncomingMessage(sender *Sender, msgType MessageType, properties Pr
309
316
}
310
317
311
318
func (request * Message ) createResponse () * Message {
319
+ flags := frameFlags (ResponseType ) | (* request .flags .Load () & kUrgent )
312
320
response := & Message {
313
- flags : frameFlags (ResponseType ) | (request .flags & kUrgent ),
314
321
number : request .number ,
315
322
Outgoing : ! request .Outgoing ,
316
323
inResponseTo : request ,
317
324
cond : sync .NewCond (& sync.Mutex {}),
318
325
}
319
326
if ! response .Outgoing {
320
- response . flags |= kMoreComing
327
+ flags |= kMoreComing
321
328
}
329
+ response .flags .Store (& flags )
322
330
return response
323
331
}
324
332
@@ -409,7 +417,7 @@ func (m *Message) nextFrameToSend(maxSize int) ([]byte, frameFlags) {
409
417
}
410
418
411
419
frame := make ([]byte , maxSize )
412
- flags := m .flags
420
+ flags := * m .flags . Load ()
413
421
size , err := io .ReadFull (m .encoder , frame )
414
422
if err == nil {
415
423
flags |= kMoreComing
@@ -421,3 +429,7 @@ func (m *Message) nextFrameToSend(maxSize int) ([]byte, frameFlags) {
421
429
422
430
// A callback function that takes a message and returns nothing
423
431
type MessageCallback func (* Message )
432
+
433
+ func ptr [T any ](v T ) * T {
434
+ return & v
435
+ }
0 commit comments