# HG changeset patch # User František Kučera # Date 1601828819 -7200 # Node ID 0fcd9944016a31e608d314d0c27536ab42237b24 # Parent d17d707314466019d3bc41b24576ac0bdf488a9a finalize on exceptions in constructor diff -r d17d70731446 -r 0fcd9944016a 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 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(); } };