finalize on exceptions in constructor v_0
authorFrantišek Kučera <franta-hg@frantovo.cz>
Sun, 04 Oct 2020 18:26:59 +0200
branchv_0
changeset 17 0fcd9944016a
parent 16 d17d70731446
child 18 7a74e9f9e674
finalize on exceptions in constructor
src/JackHandler.h
--- a/src/JackHandler.h	Sun Oct 04 12:40:00 2020 +0200
+++ b/src/JackHandler.h	Sun Oct 04 18:26:59 2020 +0200
@@ -155,13 +155,25 @@
 		std::wcerr << L"JACK: " << convertor.from_bytes(message) << std::endl;
 	}
 
+	void finalize() {
+		// Close JACK connection:
+		jack_deactivate(realTimeContext.jackClient);
+		jack_client_close(realTimeContext.jackClient);
+		jack_ringbuffer_free(realTimeContext.ringBuffer);
+	}
+
+	void failInConstructor(const relpipe::common::type::StringX& errorMessage) {
+		finalize();
+		throw JackException(errorMessage);
+	}
+
 public:
 
 	JackHandler(Configuration& configuration) : configuration(configuration) {
 		// Initialize JACK connection:
 		std::string clientName = convertor.to_bytes(configuration.jackClientName);
 		realTimeContext.jackClient = jack_client_open(clientName.c_str(), JackNullOption, nullptr);
-		if (realTimeContext.jackClient == nullptr) throw JackException(L"Could not create JACK client.");
+		if (realTimeContext.jackClient == nullptr) failInConstructor(L"Could not create JACK client.");
 
 		realTimeContext.ringBuffer = jack_ringbuffer_create(realTimeContext.RING_BUFFER_SIZE * sizeof (MidiMessage));
 
@@ -172,25 +184,24 @@
 		jack_set_info_function(jackErrorCallback);
 
 		realTimeContext.jackPort = jack_port_register(realTimeContext.jackClient, "output", JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0);
-		if (realTimeContext.jackPort == nullptr) throw JackException(L"Could not register port.");
+		if (realTimeContext.jackPort == nullptr) failInConstructor(L"Could not register the JACK port.");
 
 		if (mlockall(MCL_CURRENT | MCL_FUTURE)) fwprintf(stderr, L"Warning: Can not lock memory.\n");
 
 		int jackError = jack_activate(realTimeContext.jackClient);
-		if (jackError) throw JackException(L"Could not activate client.");
+		if (jackError) failInConstructor(L"Could not activate the JACK client.");
 
 
 		// Connect to configured destination ports:
 		const char* jackPortName = jack_port_name(realTimeContext.jackPort);
 		for (auto destinationPort : configuration.portsToConnect) {
 			int error = jack_connect(realTimeContext.jackClient, jackPortName, convertor.to_bytes(destinationPort).c_str());
-			if (error) throw JackException(L"Connection to the JACK port failed: " + destinationPort);
+			if (error) failInConstructor(L"Connection to the JACK port failed: " + destinationPort);
 		}
 
 		// Wait for a port connection, because it does not make much sense to send MIDI events nowhere:
 		while (jack_port_connected(realTimeContext.jackPort) < configuration.requiredJackConnections) usleep(10000);
 
-		// TODO: finalize on exceptions
 	}
 
 	void startRelation(const relpipe::common::type::StringX name, std::vector<relpipe::reader::handlers::AttributeMetadata> attributes) override {
@@ -290,10 +301,7 @@
 	}
 
 	virtual ~JackHandler() {
-		// Close JACK connection:
-		jack_deactivate(realTimeContext.jackClient);
-		jack_client_close(realTimeContext.jackClient);
-		jack_ringbuffer_free(realTimeContext.ringBuffer);
+		finalize();
 	}
 
 };