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)