1 /* 2 This file is part of GNU APL, a free implementation of the 3 ISO/IEC Standard 13751, "Programming Language APL, Extended" 4 5 Copyright (C) 2008-2015 Dr. Jürgen Sauermann 6 7 This program is free software: you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation, either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program. If not, see <http://www.gnu.org/licenses/>. 19 */ 20 21 #ifndef __SVAR_RECORD_HH_DEFINED__ 22 #define __SVAR_RECORD_HH_DEFINED__ 23 24 #include <stdint.h> 25 26 #include "APL_types.hh" 27 28 /// The coupling level of a shared variable 29 enum SV_Coupling 30 { 31 NO_COUPLING = 0, ///< not offered or coupled 32 SV_OFFERED = 1, ///< offered but not coupled, 33 SV_COUPLED = 2 ///< coupled 34 }; 35 36 /** shared variables control (what is NOT allowed). Terminology: 37 _OFF: the parner that has first offered the variable, 38 _ACC: the parner that has accepted the offer 39 _1: the partner reading ot changing the control vector 40 _2: the other partner of _1 (if any) 41 42 Normally the APL interpreter is _1 == _OFF and the 43 partner is _2 == _ACC. If not (eg. when the partner offers first) then 44 the functions set_control() and get_control() map the _1 and _2 arg (of 45 set_control()) and result (of get_control()) to the proper _OFF and _ACC 46 int in in the flags of the corresponding partner. 47 48 **/ 49 enum Svar_Control 50 { 51 // SET USE 52 // O A O A 53 SET_BY_OFF = 0x08, ///< 1 0 0 0: offering proc can't set (again) 54 SET_BY_ACC = 0x04, ///< 0 1 0 0: accepting proc can't set (again) 55 USE_BY_OFF = 0x02, ///< 0 0 1 0: offering proc can't (yet) use 56 USE_BY_ACC = 0x01, ///< 0 0 0 1: accepting proc can't (yet) use 57 NO_SVAR_CONTROL = 0, ///< 0 0 0 0: everything allowed 58 ALL_SVAR_CONTROLS = SET_BY_OFF | SET_BY_ACC | USE_BY_OFF | USE_BY_ACC, 59 SET_BY_1 = SET_BY_OFF, ///< if 1 is the offering partner 60 SET_BY_2 = SET_BY_ACC, ///< if 1 is the offering partner 61 USE_BY_1 = USE_BY_OFF, ///< if 1 is the offering partner 62 USE_BY_2 = USE_BY_ACC, ///< if 1 is the offering partner 63 }; 64 65 /// the state of the shared variable 66 enum Svar_state 67 { 68 // SET USE 69 // O A O A 70 SVS_NOT_SHARED = NO_SVAR_CONTROL, ///< 0 0 0 0 71 SVS_IDLE = USE_BY_OFF | USE_BY_ACC, ///< 0 0 1 1 72 SVS_OFF_HAS_SET = SET_BY_OFF | USE_BY_OFF, ///< 1 0 1 0 73 SVS_ACC_HAS_SET = SET_BY_ACC | USE_BY_ACC ///< 0 1 0 1 74 }; 75 76 /// events for a shared variable 77 enum Svar_event 78 { 79 SVE_NO_EVENTS = 0, /// no event pending 80 SVE_OFFER_MISMATCH = 0x0001, ///< not matching ⎕SVO 81 SVE_OFFER_MATCHED = 0x0002, ///< matching ⎕SVO 82 SVE_OFFER_RETRACT = 0x0004, ///< ⎕SVR 83 SVE_ACCESS_CONTROL = 0x0008, ///< ⎕SVC by partner 84 SVE_USE_BY_OFF_SUCCESS = 0x0010, ///< CTL is 1 x x x and offerer USEs var 85 SVE_USE_BY_OFF_FAILED = 0x0020, ///< CTL is x 1 x x and offerer USE failed 86 SVE_SET_BY_OFF_SUCCESS = 0x0040, ///< CTL is x x 1 x and offerer SETs var 87 SVE_SET_BY_OFF_FAILED = 0x0080, ///< CTL is x x x 1 and offerer SET failed 88 SVE_USE_BY_ACC_SUCCESS = 0x0100, ///< CTL is 1 x x x and acceptor USEs var 89 SVE_USE_BY_ACC_FAILED = 0x0200, ///< CTL is x 1 x x and acc. USE failed 90 SVE_SET_BY_ACC_SUCCESS = 0x0400, ///< CTL is x x 1 x and acceptor SETs var 91 SVE_SET_BY_ACC_FAILED = 0x0800, ///< CTL is x x x 1 and acc. SET failed 92 }; 93 94 /// return the name for event \b ev 95 extern const char * event_name(Svar_event ev); 96 97 /// SV_key uniquely identifies a shared variable. It is created when the 98 /// variable is first offered and passed to the share partner when the offer 99 /// is matched. The partner (offering or accepting) is identified by the id 100 /// of the partner. 101 typedef uint64_t SV_key; 102 103 //----------------------------------------------------------------------------- 104 enum TCP_socket 105 { 106 NO_TCP_SOCKET = -1 107 }; 108 //----------------------------------------------------------------------------- 109 /// one of the two partners of a shared vaiable 110 struct Svar_partner 111 { 112 /// constructor: unused share partner Svar_partnerSvar_partner113 Svar_partner() 114 : id(NO_AP), 115 tcp_fd(NO_TCP_SOCKET), 116 flags(0), 117 events(SVE_NO_EVENTS), 118 active(false) 119 {} 120 121 /// constructor: specific share partner Svar_partnerSvar_partner122 Svar_partner(const AP_num3 _id, TCP_socket _tcp_fd) 123 : id(_id), 124 tcp_fd(_tcp_fd), 125 flags(0), 126 events(SVE_NO_EVENTS), 127 active(true) 128 {} 129 130 /// copy other to \n this operator =Svar_partner131 void operator =(const Svar_partner & other) 132 { 133 id = other.id; 134 tcp_fd = other.tcp_fd; 135 flags = other.flags; 136 events = other.events; 137 active = other.active; 138 } 139 140 /// clear this partner clearSvar_partner141 void clear() { new (this) Svar_partner; } 142 143 /// return true if this partner is active. Note that this can be the case 144 /// even though tcp_fd is invalid. is_activeSvar_partner145 bool is_active() const 146 { return active; } 147 148 /// set the control bits of this partner (as seen by the offering partner) set_controlSvar_partner149 void set_control(Svar_Control ctl) 150 { flags = ctl; } 151 152 /// return the control bits of this partner (as seen by the offering 153 // partner) get_controlSvar_partner154 Svar_Control get_control() const 155 { return Svar_Control(flags); } 156 157 /// print this partner 158 ostream & print(ostream & out) const; 159 160 /// the processor 161 AP_num3 id; 162 163 /// the TCP socket of the server towards the partner 164 TCP_socket tcp_fd; 165 166 /// flags controlled by this partner. The numbers 1 and 2 in the SET_BY_1, 167 /// SET_BY_2 bits refer to this partner as 1 and the other partner as 2. 168 uint16_t flags; 169 170 /// the events for the partner 171 Svar_event events; 172 173 protected: 174 /// true if this is a valid (connected) partner 175 bool active; 176 }; 177 //----------------------------------------------------------------------------- 178 179 extern TCP_socket get_TCP_for_key(SV_key key); 180 181 //----------------------------------------------------------------------------- 182 183 /// one shared variable. 184 struct Svar_record 185 { 186 /// a key that uniquely identifies this variable 187 SV_key key; 188 189 /// true if this is a valid entry. validSvar_record190 bool valid() const { return get_coupling() != NO_COUPLING; } 191 192 /// invalidate this entry clearSvar_record193 void clear() 194 { 195 key = 0; 196 offering.clear(); 197 accepting.clear(); 198 state = SVS_NOT_SHARED; 199 varname[0] = 0; 200 } 201 202 /// remove accepting partner 203 void remove_accepting(); 204 205 /// remove offering partner 206 void remove_offering(); 207 208 /// retract the offer made by the calling ID. 209 SV_Coupling retract(); 210 211 /// return true iff this is a variable shared between APL interpreters 212 /// as opposed to shared with an AP. 213 bool is_ws_to_ws() const; 214 215 /// complain about \b proc 216 void bad_proc(const char * function, const AP_num3 & ap) const; 217 218 /// return true if UCS_other matches varname (could be a wildcard match) 219 bool match_name(const uint32_t * UCS_other) const; 220 221 /// return the coupling of the variable get_couplingSvar_record222 SV_Coupling get_coupling() const 223 { int ret = 0; if (offering.is_active()) ++ret; 224 if (accepting.is_active()) ++ret; 225 return SV_Coupling(ret); } 226 227 228 /// return the control bits of this variable 229 Svar_Control get_control() const; 230 231 /// set the control bits of this variable 232 void set_control(Svar_Control ctl); 233 234 /// return the state of this variable 235 Svar_state get_state() const; 236 237 /// return the name of the variable, or 0 if fetching it has failed get_svar_nameSvar_record238 const uint32_t * get_svar_name() const 239 { return *varname ? varname : 0; } 240 241 /// update the state when using or setting this variable, and clear events 242 void set_state(bool used, const char * loc); 243 244 /// return true iff the calling partner may use the current value 245 bool may_use(int attempt); 246 247 /// return true iff the calling partner may set the current value 248 bool may_set(int attempt); 249 250 /// print the variable 251 void print(ostream & out) const; 252 253 /// print a name 254 static ostream & print_name(ostream & out, const uint32_t * name, 255 int len = MAX_SVAR_NAMELEN); 256 257 /// print the name of this variable print_nameSvar_record258 ostream & print_name(ostream & out) const 259 { return print_name(out, varname, 0); } 260 261 /// name of the offered variable (UCS), 0-terminated 262 uint32_t varname[MAX_SVAR_NAMELEN + 1]; 263 264 /// the partner that has offered the variable first 265 Svar_partner offering; 266 267 /// the partner that has accepted the offer from \b offering 268 Svar_partner accepting; 269 270 /// state of this variable 271 Svar_state state; 272 }; 273 //----------------------------------------------------------------------------- 274 275 #if APSERVER_TRANSPORT == 1 276 enum { ABSTRACT_OFFSET = 1 }; 277 #else 278 enum { ABSTRACT_OFFSET = 0 }; 279 #endif 280 281 #endif // __SVAR_RECORD_HH_DEFINED__ 282