forked from att/gopkgs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
chmsg.go
135 lines (110 loc) · 4.39 KB
/
chmsg.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
// vi: sw=4 ts=4:
/*
---------------------------------------------------------------------------
Copyright (c) 2013-2015 AT&T Intellectual Property
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at:
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
---------------------------------------------------------------------------
*/
/*
Mnemonic: chmsg
Abstract: Channel message object and related methods.
Date: 02 December 2013
Author: E. Scott Daniels
Mod: 2015 Nov 06 - Added nil ptr protection.
07 Mar 2015 - Added non-blocking send.
*/
/*
The chmsg provides a data structure that helps to manage interprocess
communications between Goroutines via channels.
*/
package ipc
import (
)
// --------------------------------------------------------------------------------------
/*
Defines a message. Request and response data pointers are used so that in the case
where the requesting thread is not blocking on the response the request data will
be available for response processing if needed. A third data field, requestor_data
is another hook to assist with asynch response processing. This is assumed to point
to a data object that is of no significance to the receiver of the message when
the message is a request. It should be nil if the response channel is also nil.
The struct allows the application to define how it is used, and does not really imply
any meaning on the fields.
*/
type Chmsg struct { // all fields are externally available as a convenence
Msg_type int; // action requested
Response_ch chan *Chmsg; // channel to write this request back onto when done
Response_data interface{}; // what might be useful in addition to the state
Req_data interface{}; // necessary information to processes the request
Requestor_data interface{}; // private data meaningful only to the requestor and
// necessary to process an asynch response to the message.
State error; // response state, nil == no error
}
/*
constructor
*/
func Mk_chmsg( ) (r *Chmsg) {
r = &Chmsg { };
return;
}
// ---- these are convenience functions that might make the code a bit easier to read ------------------
/*
Real function which accepts a can-block flag sending the message along on the requested channel
*/
func (r *Chmsg) send_req( dest_ch chan *Chmsg, resp_ch chan *Chmsg, mtype int, data interface{}, pdata interface{}, can_block bool ) {
if r == nil {
return
}
r.Msg_type = mtype;
r.Req_data = data;
r.Response_ch = resp_ch;
r.Requestor_data = pdata;
r.Response_data = nil;
r.State = nil;
if can_block {
dest_ch <- r; // this may block until the receiver reads it if the channel is not buffered
} else {
select { // this will not block if channel is full or unbuffered; message is dropped
case dest_ch <- r:
// we don't do anything, it just worked :)
default:
// we could log this, but we won't
}
}
}
/*
Send the message as a request oriented packet.
Data is mapped to request data, while response data and state are set to nil.
Pdata is the private requestor data.
*/
func (r *Chmsg) Send_req( dest_ch chan *Chmsg, resp_ch chan *Chmsg, mtype int, data interface{}, pdata interface{} ) {
r.send_req( dest_ch, resp_ch, mtype, data, pdata, true )
}
/*
Sends the message as a request to the indicated channel. The no-block flag is set which
causes the message to be SILENTLY droped if the reciving channel is blocking.
*/
func (r *Chmsg) Send_nbreq( dest_ch chan *Chmsg, resp_ch chan *Chmsg, mtype int, data interface{}, pdata interface{} ) {
r.send_req( dest_ch, resp_ch, mtype, data, pdata, false )
}
/*
Send the request as a response oriented packet.
The response channel is used to send the block.
Data is mapped to response data and state is set. All other fields are left unchanged.
*/
func (r *Chmsg) Send_resp( data interface{}, state error ) {
if r == nil {
return
}
r.Response_data = data;
r.State = state;
r.Response_ch <- r; // this may block until the receiver reads it if the channel is not buffered
}