diff --git a/src/epics/seq/main.cc b/src/epics/seq/main.cc index 2541fb81a3bc7132ebbc721016ea83141e73ac99..956b83e61baa7e2a8a782d7c800b0a741d847052 100644 --- a/src/epics/seq/main.cc +++ b/src/epics/seq/main.cc @@ -59,21 +59,10 @@ using embedded::fixed_string; //template <std::size_t Size> using fixed_string = embedded::fixed_string<Size>; #ifdef CA_SDF +#include <mutex> -// The identifiers below were defined in the EPICS local db headers but -// also are defined in cadef.h. -// They are undefined here to avoid compiler warnings. -#undef DBR_SHORT -#undef DBR_GR_LONG -#undef DBR_GR_DOUBLE -#undef DBR_CTRL_LONG -#undef DBR_CTRL_DOUBLE -#undef DBR_PUT_ACKT -#undef DBR_PUT_ACKS -#undef VALID_DB_REQ -#undef INVALID_DB_REQ - -#include <pthread.h> +// Including the DB/IOC based code + CA based client code gives warnings on redefinitions +// so undef these before including the CA code. #undef DBR_SHORT #undef DBR_GR_LONG #undef DBR_GR_DOUBLE @@ -270,10 +259,12 @@ int chEnumDetermined = 0; ///< Total number of enums whos types have been dete long chDisconnected = 0; ///< Total number of channels that are disconnected. This is used as the max index for disconnectedChans long chDisconnectedCount = 0; ///< The count of the disconnected channels. Seperate from chDisconnected so that it can be updated even when the table is not updated. -pthread_t caThread; -pthread_mutex_t caStateMutex; -pthread_mutex_t caTableMutex; -pthread_mutex_t caEvidMutex; + +std::mutex caStateMutex; +std::mutex caTableMutex; +std::mutex caEvidMutex; + +using lock_guard = std::lock_guard<std::mutex>; int caThreadState; long droppedPVCount; @@ -2517,7 +2508,7 @@ bool syncEpicsDoubleValue(ADDRESS index, double *dest, time_t *tp, int *connp) { debug=1; } #endif - pthread_mutex_lock(&caTableMutex); + lock_guard l_(caTableMutex); if (caTable[index].datatype == SDF_NUM) { *dest = caTable[index].data.chval; if (tp) { @@ -2527,7 +2518,6 @@ bool syncEpicsDoubleValue(ADDRESS index, double *dest, time_t *tp, int *connp) { *connp = caTable[index].connected; } } - pthread_mutex_unlock(&caTableMutex); return true; } @@ -2544,7 +2534,7 @@ bool syncEpicsIntValue(ADDRESS index, PV_INT_TYPE *dest, time_t *tp, int *connp) bool syncEpicsStrValue(ADDRESS index, char *dest, int dest_size, time_t *tp, int *connp) { if (!dest || index < 0 || index >= chNum || dest_size < 1) return false; dest[0] = '\0'; - pthread_mutex_lock(&caTableMutex); + lock_guard l_(caTableMutex); if (caTable[index].datatype == SDF_STR) { const int MAX_STR_LEN = sizeof(caTable[index].data.strval); strncpy(dest, caTable[index].data.strval, (dest_size < MAX_STR_LEN ? dest_size : MAX_STR_LEN)); @@ -2556,7 +2546,6 @@ bool syncEpicsStrValue(ADDRESS index, char *dest, int dest_size, time_t *tp, int *connp = caTable[index].connected; } } - pthread_mutex_unlock(&caTableMutex); return true; } @@ -2571,7 +2560,7 @@ void subscriptionHandler(struct event_handler_args args) { return; } - pthread_mutex_lock(&caTableMutex); + lock_guard l_(caTableMutex); // If this entry has just reconnected, then do not write the old copy, write to the temporary/redir dest initialRedirIndex = entry->redirIndex; @@ -2626,7 +2615,6 @@ void subscriptionHandler(struct event_handler_args args) { // The dbr_gr_enum type does not have time information, so we use current time entry->mod_time = time(NULL); } - pthread_mutex_unlock(&caTableMutex); } void connectCallback(struct connection_handler_args args) { @@ -2653,65 +2641,68 @@ void connectCallback(struct connection_handler_args args) { } } - pthread_mutex_lock(&caTableMutex); - if (args.op == CA_OP_CONN_UP) { - // connection - if (is_enum) { - entry->redirIndex = entry->chanIndex + SDF_MAX_TSIZE; - connEntry = &(caConnEnumTable[entry->chanIndex]); - } else { - // reserve a new conn table entry if one is not already reserved - if (entry->redirIndex < 0) { - entry->redirIndex = chConnNum; - ++chConnNum; - } - connEntry = &(caConnTable[entry->redirIndex]); - } - entry->chanid = args.chid; + { + lock_guard l_(caTableMutex); + if (args.op == CA_OP_CONN_UP) { + // connection + if (is_enum) { + entry->redirIndex = entry->chanIndex + SDF_MAX_TSIZE; + connEntry = &(caConnEnumTable[entry->chanIndex]); + } else { + // reserve a new conn table entry if one is not already reserved + if (entry->redirIndex < 0) { + entry->redirIndex = chConnNum; + ++chConnNum; + } + connEntry = &(caConnTable[entry->redirIndex]); + } + entry->chanid = args.chid; - // now copy items over to the connection record - connEntry->redirIndex = -1; + // now copy items over to the connection record + connEntry->redirIndex = -1; - connEntry->datatype = sdf_type; - connEntry->data.chval = 0.0; - entry->connected = 1; - connEntry->connected = 1; - connEntry->mod_time = 0; - connEntry->chanid = args.chid; - connEntry->chanIndex = entry->chanIndex; - typeChange = (connEntry->datatype != entry->datatype); + connEntry->datatype = sdf_type; + connEntry->data.chval = 0.0; + entry->connected = 1; + connEntry->connected = 1; + connEntry->mod_time = 0; + connEntry->chanid = args.chid; + connEntry->chanIndex = entry->chanIndex; + typeChange = (connEntry->datatype != entry->datatype); - } else { - // disconnect - entry->connected = 0; - } - pthread_mutex_unlock(&caTableMutex); + } else { + // disconnect + entry->connected = 0; + } + } - // now register/clear the subscription callback - pthread_mutex_lock(&caEvidMutex); - if (args.op == CA_OP_CONN_UP) { - // connect - // if we are subscribed but the types are wrong, then unsubscribe - if (caEvid[chanIndex] && typeChange) { - ca_clear_subscription(caEvid[chanIndex]); - caEvid[chanIndex] = 0; - } - // if we are not subscribed become subscribed - if (!caEvid[chanIndex]) { - chtype subtype = (sdf_type == SDF_NUM ? DBR_TIME_DOUBLE : DBR_TIME_STRING); - if (is_enum) { - subtype = DBR_GR_ENUM; - } - ca_create_subscription(subtype, 0, args.chid, DBE_VALUE, subscriptionHandler, entry, &(caEvid[chanIndex])); - } - } else { - // disconnect - if (caEvid[chanIndex]) { - ca_clear_subscription(caEvid[chanIndex]); - caEvid[chanIndex] = 0; - } - } - pthread_mutex_unlock(&caEvidMutex); + { + // now register/clear the subscription callback + lock_guard l_(caEvidMutex); + if (args.op == CA_OP_CONN_UP) { + // connect + // if we are subscribed but the types are wrong, then unsubscribe + if (caEvid[chanIndex] && typeChange) { + ca_clear_subscription(caEvid[chanIndex]); + caEvid[chanIndex] = 0; + } + // if we are not subscribed become subscribed + if (!caEvid[chanIndex]) { + chtype subtype = (sdf_type == SDF_NUM ? DBR_TIME_DOUBLE : DBR_TIME_STRING); + if (is_enum) { + subtype = DBR_GR_ENUM; + } + ca_create_subscription(subtype, 0, args.chid, DBE_VALUE, subscriptionHandler, entry, + &(caEvid[chanIndex])); + } + } else { + // disconnect + if (caEvid[chanIndex]) { + ca_clear_subscription(caEvid[chanIndex]); + caEvid[chanIndex] = 0; + } + } + } } } @@ -2726,18 +2717,19 @@ void registerPV(char *PVname) return; } //printf("Registering %s\n", PVname); - pthread_mutex_lock(&caTableMutex); - caTable[chNum].datatype = SDF_NUM; - caTable[chNum].connected = 0; - cdTable[chNum].chname = PVname; - cdTable[chNum].datatype = SDF_NUM; - cdTable[chNum].initialized = 0; - cdTable[chNum].filterswitch = 0; - cdTable[chNum].filterNum = -1; - cdTable[chNum].error = 0; - cdTable[chNum].initialized = 0; - cdTable[chNum].mask = 0; - pthread_mutex_unlock(&caTableMutex); + { + lock_guard l_(caTableMutex); + caTable[chNum].datatype = SDF_NUM; + caTable[chNum].connected = 0; + cdTable[chNum].chname = PVname; + cdTable[chNum].datatype = SDF_NUM; + cdTable[chNum].initialized = 0; + cdTable[chNum].filterswitch = 0; + cdTable[chNum].filterNum = -1; + cdTable[chNum].error = 0; + cdTable[chNum].initialized = 0; + cdTable[chNum].mask = 0; + } status = ca_create_channel(PVname, connectCallback, &(caTable[chNum]), 0, &chid1); @@ -2808,18 +2800,14 @@ void parseChannelListReq(char *fname) { /// Routine to get the state of the CA Thread int getCAThreadState() { - int state = 0; - pthread_mutex_lock(&caStateMutex); - state = caThreadState; - pthread_mutex_unlock(&caStateMutex); - return state; + lock_guard l_(caStateMutex); + return caThreadState; } /// Routine to set the state of the CA Thread void setCAThreadState(int state) { - pthread_mutex_lock(&caStateMutex); + lock_guard l_(caStateMutex); caThreadState = state; - pthread_mutex_unlock(&caStateMutex); } // copy the given entry (which should be in caConnTable or caConnEnumTable) to caTable @@ -2855,7 +2843,7 @@ void syncCAConnections(long *disconnected_count) int chanIndex = SDF_MAX_TSIZE; chtype subtype = DBR_TIME_DOUBLE; - pthread_mutex_lock(&caTableMutex); + lock_guard l_(caTableMutex); // sync all non-enum channel connections that have taken place for (ii = 0; ii < chConnNum; ++ii) { copyConnectedCAEntry(&(caConnTable[ii])); @@ -2893,7 +2881,6 @@ void syncCAConnections(long *disconnected_count) // } // *disconnected_count = tmp; //} - pthread_mutex_unlock(&caTableMutex); } /// Main loop of the CA Thread @@ -2983,17 +2970,11 @@ void setupCASDF() bzero((void *)&(readErrTable[ii]), sizeof(readErrTable[ii])); } droppedPVCount = 0; - pthread_mutex_init(&caStateMutex, NULL); // FIXME check for errors - pthread_mutex_init(&caTableMutex, NULL); - pthread_mutex_init(&caEvidMutex, NULL); } /// Routine to tear-down mutexes and other resources used by the CA SDF system void cleanupCASDF() { - pthread_mutex_destroy(&caEvidMutex); - pthread_mutex_destroy(&caTableMutex); - pthread_mutex_destroy(&caStateMutex); } #else void countDisconnectedChannels(int curTable)