| @@ -50,6 +50,7 @@ CarlaPlugin::CarlaPlugin(CarlaEngine* const engine, const unsigned int id) | |||||
| case PROCESS_MODE_MULTIPLE_CLIENTS: | case PROCESS_MODE_MULTIPLE_CLIENTS: | ||||
| fData->ctrlInChannel = 0; | fData->ctrlInChannel = 0; | ||||
| break; | break; | ||||
| case PROCESS_MODE_CONTINUOUS_RACK: | case PROCESS_MODE_CONTINUOUS_RACK: | ||||
| CARLA_ASSERT(id < MAX_RACK_PLUGINS && id < MAX_MIDI_CHANNELS); | CARLA_ASSERT(id < MAX_RACK_PLUGINS && id < MAX_MIDI_CHANNELS); | ||||
| @@ -57,6 +58,10 @@ CarlaPlugin::CarlaPlugin(CarlaEngine* const engine, const unsigned int id) | |||||
| fData->ctrlInChannel = id; | fData->ctrlInChannel = id; | ||||
| break; | break; | ||||
| case PROCESS_MODE_PATCHBAY: | |||||
| case PROCESS_MODE_BRIDGE: | |||||
| break; | |||||
| } | } | ||||
| } | } | ||||
| @@ -1199,7 +1204,7 @@ void CarlaPlugin::postponeRtEvent(const PluginPostRtEventType type, const int32_ | |||||
| void CarlaPlugin::postRtEventsRun() | void CarlaPlugin::postRtEventsRun() | ||||
| { | { | ||||
| unsigned short i = 0; | |||||
| unsigned short k = 0; | |||||
| PluginPostRtEvent listData[MAX_RT_EVENTS]; | PluginPostRtEvent listData[MAX_RT_EVENTS]; | ||||
| // Make a safe copy of events while clearing them | // Make a safe copy of events while clearing them | ||||
| @@ -1209,53 +1214,53 @@ void CarlaPlugin::postRtEventsRun() | |||||
| { | { | ||||
| PluginPostRtEvent& event = fData->postRtEvents.data.getFirst(true); | PluginPostRtEvent& event = fData->postRtEvents.data.getFirst(true); | ||||
| //listData[i++] = event; | //listData[i++] = event; | ||||
| std::memcpy(&listData[i++], &event, sizeof(PluginPostRtEvent)); | |||||
| std::memcpy(&listData[k++], &event, sizeof(PluginPostRtEvent)); | |||||
| } | } | ||||
| fData->postRtEvents.mutex.unlock(); | fData->postRtEvents.mutex.unlock(); | ||||
| // Handle events now | // Handle events now | ||||
| for (i=0; i < MAX_RT_EVENTS; i++) | |||||
| for (unsigned short i=0; i < k; i++) | |||||
| { | { | ||||
| const PluginPostRtEvent* const event = &listData[i]; | |||||
| const PluginPostRtEvent& event = listData[i]; | |||||
| if (event->type != kPluginPostRtEventNull) | |||||
| qWarning("postRtEventsRun() - event type %i", i); | |||||
| if (event.type != kPluginPostRtEventNull) | |||||
| qWarning("postRtEventsRun() - @ %i", i); | |||||
| switch (event->type) | |||||
| switch (event.type) | |||||
| { | { | ||||
| case kPluginPostRtEventNull: | case kPluginPostRtEventNull: | ||||
| break; | break; | ||||
| case kPluginPostRtEventDebug: | case kPluginPostRtEventDebug: | ||||
| fData->engine->callback(CALLBACK_DEBUG, fData->id, event->value1, event->value2, event->value3, nullptr); | |||||
| fData->engine->callback(CALLBACK_DEBUG, fData->id, event.value1, event.value2, event.value3, nullptr); | |||||
| break; | break; | ||||
| case kPluginPostRtEventParameterChange: | case kPluginPostRtEventParameterChange: | ||||
| // Update UI | // Update UI | ||||
| if (event->value1 >= 0) | |||||
| uiParameterChange(event->value1, event->value3); | |||||
| if (event.value1 >= 0) | |||||
| uiParameterChange(event.value1, event.value3); | |||||
| #ifndef BUILD_BRIDGE | #ifndef BUILD_BRIDGE | ||||
| // Update OSC control client | // Update OSC control client | ||||
| if (fData->engine->isOscControlRegistered()) | if (fData->engine->isOscControlRegistered()) | ||||
| fData->engine->osc_send_control_set_parameter_value(fData->id, event->value1, event->value3); | |||||
| fData->engine->osc_send_control_set_parameter_value(fData->id, event.value1, event.value3); | |||||
| #endif | #endif | ||||
| // Update Host | // Update Host | ||||
| fData->engine->callback(CALLBACK_PARAMETER_VALUE_CHANGED, fData->id, event->value1, 0, event->value3, nullptr); | |||||
| fData->engine->callback(CALLBACK_PARAMETER_VALUE_CHANGED, fData->id, event.value1, 0, event.value3, nullptr); | |||||
| break; | break; | ||||
| case kPluginPostRtEventProgramChange: | case kPluginPostRtEventProgramChange: | ||||
| // Update UI | // Update UI | ||||
| if (event->value1 >= 0) | |||||
| uiProgramChange(event->value1); | |||||
| if (event.value1 >= 0) | |||||
| uiProgramChange(event.value1); | |||||
| #ifndef BUILD_BRIDGE | #ifndef BUILD_BRIDGE | ||||
| // Update OSC control client | // Update OSC control client | ||||
| if (fData->engine->isOscControlRegistered()) | if (fData->engine->isOscControlRegistered()) | ||||
| { | { | ||||
| fData->engine->osc_send_control_set_program(fData->id, event->value1); | |||||
| fData->engine->osc_send_control_set_program(fData->id, event.value1); | |||||
| for (uint32_t j=0; j < fData->param.count; j++) | for (uint32_t j=0; j < fData->param.count; j++) | ||||
| fData->engine->osc_send_control_set_default_value(fData->id, j, fData->param.ranges[j].def); | fData->engine->osc_send_control_set_default_value(fData->id, j, fData->param.ranges[j].def); | ||||
| @@ -1263,19 +1268,19 @@ void CarlaPlugin::postRtEventsRun() | |||||
| #endif | #endif | ||||
| // Update Host | // Update Host | ||||
| fData->engine->callback(CALLBACK_PROGRAM_CHANGED, fData->id, event->value1, 0, 0.0, nullptr); | |||||
| fData->engine->callback(CALLBACK_PROGRAM_CHANGED, fData->id, event.value1, 0, 0.0, nullptr); | |||||
| break; | break; | ||||
| case kPluginPostRtEventMidiProgramChange: | case kPluginPostRtEventMidiProgramChange: | ||||
| // Update UI | // Update UI | ||||
| if (event->value1 >= 0) | |||||
| uiMidiProgramChange(event->value1); | |||||
| if (event.value1 >= 0) | |||||
| uiMidiProgramChange(event.value1); | |||||
| #ifndef BUILD_BRIDGE | #ifndef BUILD_BRIDGE | ||||
| // Update OSC control client | // Update OSC control client | ||||
| if (fData->engine->isOscControlRegistered()) | if (fData->engine->isOscControlRegistered()) | ||||
| { | { | ||||
| fData->engine->osc_send_control_set_midi_program(fData->id, event->value1); | |||||
| fData->engine->osc_send_control_set_midi_program(fData->id, event.value1); | |||||
| for (uint32_t j=0; j < fData->param.count; j++) | for (uint32_t j=0; j < fData->param.count; j++) | ||||
| fData->engine->osc_send_control_set_default_value(fData->id, j, fData->param.ranges[j].def); | fData->engine->osc_send_control_set_default_value(fData->id, j, fData->param.ranges[j].def); | ||||
| @@ -1283,35 +1288,35 @@ void CarlaPlugin::postRtEventsRun() | |||||
| #endif | #endif | ||||
| // Update Host | // Update Host | ||||
| fData->engine->callback(CALLBACK_MIDI_PROGRAM_CHANGED, fData->id, event->value1, 0, 0.0, nullptr); | |||||
| fData->engine->callback(CALLBACK_MIDI_PROGRAM_CHANGED, fData->id, event.value1, 0, 0.0, nullptr); | |||||
| break; | break; | ||||
| case kPluginPostRtEventNoteOn: | case kPluginPostRtEventNoteOn: | ||||
| // Update UI | // Update UI | ||||
| uiNoteOn(event->value1, event->value2, int(event->value3)); | |||||
| uiNoteOn(event.value1, event.value2, int(event.value3)); | |||||
| #ifndef BUILD_BRIDGE | #ifndef BUILD_BRIDGE | ||||
| // Update OSC control client | // Update OSC control client | ||||
| if (fData->engine->isOscControlRegistered()) | if (fData->engine->isOscControlRegistered()) | ||||
| fData->engine->osc_send_control_note_on(fData->id, event->value1, event->value2, int(event->value3)); | |||||
| fData->engine->osc_send_control_note_on(fData->id, event.value1, event.value2, int(event.value3)); | |||||
| #endif | #endif | ||||
| // Update Host | // Update Host | ||||
| fData->engine->callback(CALLBACK_NOTE_ON, fData->id, event->value1, event->value2, int(event->value3), nullptr); | |||||
| fData->engine->callback(CALLBACK_NOTE_ON, fData->id, event.value1, event.value2, int(event.value3), nullptr); | |||||
| break; | break; | ||||
| case kPluginPostRtEventNoteOff: | case kPluginPostRtEventNoteOff: | ||||
| // Update UI | // Update UI | ||||
| uiNoteOff(event->value1, event->value2); | |||||
| uiNoteOff(event.value1, event.value2); | |||||
| #ifndef BUILD_BRIDGE | #ifndef BUILD_BRIDGE | ||||
| // Update OSC control client | // Update OSC control client | ||||
| if (fData->engine->isOscControlRegistered()) | if (fData->engine->isOscControlRegistered()) | ||||
| fData->engine->osc_send_control_note_off(fData->id, event->value1, event->value2); | |||||
| fData->engine->osc_send_control_note_off(fData->id, event.value1, event.value2); | |||||
| #endif | #endif | ||||
| // Update Host | // Update Host | ||||
| fData->engine->callback(CALLBACK_NOTE_OFF, fData->id, event->value1, event->value2, 0.0, nullptr); | |||||
| fData->engine->callback(CALLBACK_NOTE_OFF, fData->id, event.value1, event.value2, 0.0, nullptr); | |||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| @@ -434,10 +434,18 @@ struct CarlaPluginProtectedData { | |||||
| : data(MIN_RT_EVENTS, MAX_RT_EVENTS), | : data(MIN_RT_EVENTS, MAX_RT_EVENTS), | ||||
| dataPendingRT(MIN_RT_EVENTS, MAX_RT_EVENTS) {} | dataPendingRT(MIN_RT_EVENTS, MAX_RT_EVENTS) {} | ||||
| ~PostRtEvents() | |||||
| { | |||||
| clear(); | |||||
| } | |||||
| void appendRT(const PluginPostRtEvent& event) | void appendRT(const PluginPostRtEvent& event) | ||||
| { | { | ||||
| dataPendingRT.append(event); | dataPendingRT.append(event); | ||||
| } | |||||
| void trySplice() | |||||
| { | |||||
| if (mutex.tryLock()) | if (mutex.tryLock()) | ||||
| { | { | ||||
| dataPendingRT.splice(data, true); | dataPendingRT.splice(data, true); | ||||
| @@ -445,6 +453,14 @@ struct CarlaPluginProtectedData { | |||||
| } | } | ||||
| } | } | ||||
| void clear() | |||||
| { | |||||
| mutex.lock(); | |||||
| data.clear(); | |||||
| dataPendingRT.clear(); | |||||
| mutex.unlock(); | |||||
| } | |||||
| //void appendNonRT(const PluginPostRtEvent& event) | //void appendNonRT(const PluginPostRtEvent& event) | ||||
| //{ | //{ | ||||
| // data.append_sleepy(event); | // data.append_sleepy(event); | ||||
| @@ -921,6 +921,8 @@ public: | |||||
| } | } | ||||
| } | } | ||||
| fData->postRtEvents.trySplice(); | |||||
| } // End of Parameters Input | } // End of Parameters Input | ||||
| CARLA_PROCESS_CONTINUE_CHECK; | CARLA_PROCESS_CONTINUE_CHECK; | ||||
| @@ -1820,15 +1820,26 @@ class PluginEdit(QDialog): | |||||
| # Check parameters needing update | # Check parameters needing update | ||||
| for index, value in self.fParametersToUpdate: | for index, value in self.fParametersToUpdate: | ||||
| if index == PARAMETER_DRYWET: | if index == PARAMETER_DRYWET: | ||||
| self.ui.dial_drywet.setValue(value * 1000, True, False) | |||||
| self.ui.dial_drywet.blockSignals(True) | |||||
| self.ui.dial_drywet.setValue(value * 1000) | |||||
| self.ui.dial_drywet.blockSignals(False) | |||||
| elif index == PARAMETER_VOLUME: | elif index == PARAMETER_VOLUME: | ||||
| self.ui.dial_vol.setValue(value * 1000, True, False) | |||||
| self.ui.dial_vol.blockSignals(True) | |||||
| self.ui.dial_vol.setValue(value * 1000) | |||||
| self.ui.dial_vol.blockSignals(False) | |||||
| elif index == PARAMETER_BALANCE_LEFT: | elif index == PARAMETER_BALANCE_LEFT: | ||||
| self.ui.dial_b_left.setValue(value * 1000, True, False) | |||||
| self.ui.dial_b_left.blockSignals(True) | |||||
| self.ui.dial_b_left.setValue(value * 1000) | |||||
| self.ui.dial_b_left.blockSignals(False) | |||||
| elif index == PARAMETER_BALANCE_RIGHT: | elif index == PARAMETER_BALANCE_RIGHT: | ||||
| self.ui.dial_b_right.setValue(value * 1000, True, False) | |||||
| self.ui.dial_b_right.blockSignals(True) | |||||
| self.ui.dial_b_right.setValue(value * 1000) | |||||
| self.ui.dial_b_right.blockSignals(False) | |||||
| elif index == PARAMETER_PANNING: | elif index == PARAMETER_PANNING: | ||||
| pass #self.ui.dial_pan.setValue(value * 1000, True, False) | |||||
| pass | |||||
| #self.ui.dial_pan.blockSignals(True) | |||||
| #self.ui.dial_pan.setValue(value * 1000, True, False) | |||||
| #self.ui.dial_pan.blockSignals(False) | |||||
| elif index >= 0: | elif index >= 0: | ||||
| for paramType, paramId, paramWidget in self.fParameterList: | for paramType, paramId, paramWidget in self.fParameterList: | ||||
| if paramId == index: | if paramId == index: | ||||
| @@ -1,5 +1,5 @@ | |||||
| /* | /* | ||||
| * High-level, real-time safe, templated C++ doubly linked list | |||||
| * High-level, real-time safe, templated C++ doubly-linked list | |||||
| * Copyright (C) 2013 Filipe Coelho <falktx@falktx.com> | * Copyright (C) 2013 Filipe Coelho <falktx@falktx.com> | ||||
| * | * | ||||
| * This program is free software; you can redistribute it and/or | * This program is free software; you can redistribute it and/or | ||||
| @@ -23,8 +23,7 @@ extern "C" { | |||||
| #include "rtmempool/rtmempool.h" | #include "rtmempool/rtmempool.h" | ||||
| } | } | ||||
| #include <cassert> | |||||
| #include <cstring> | |||||
| #include "carla_utils.hpp" | |||||
| // list_entry C++11 version (using nullptr instead of 0) | // list_entry C++11 version (using nullptr instead of 0) | ||||
| #undef list_entry | #undef list_entry | ||||
| @@ -47,7 +46,8 @@ class List | |||||
| { | { | ||||
| protected: | protected: | ||||
| List() | List() | ||||
| : fDataSize(sizeof(Data)) | |||||
| : kDataSize(sizeof(Data)), | |||||
| fCount(0) | |||||
| { | { | ||||
| _init(); | _init(); | ||||
| } | } | ||||
| @@ -55,20 +55,19 @@ protected: | |||||
| public: | public: | ||||
| virtual ~List() | virtual ~List() | ||||
| { | { | ||||
| clear(); | |||||
| CARLA_ASSERT(fCount == 0); | |||||
| } | } | ||||
| void clear() | void clear() | ||||
| { | { | ||||
| if (fCount != 0) | if (fCount != 0) | ||||
| { | { | ||||
| Data* data; | |||||
| k_list_head* entry; | k_list_head* entry; | ||||
| list_for_each(entry, &fQueue) | list_for_each(entry, &fQueue) | ||||
| { | { | ||||
| data = list_entry(entry, Data, siblings); | |||||
| _deallocate(data); | |||||
| if (Data* data = list_entry(entry, Data, siblings)) | |||||
| _deallocate(data); | |||||
| } | } | ||||
| } | } | ||||
| @@ -98,14 +97,27 @@ public: | |||||
| return false; | return false; | ||||
| } | } | ||||
| bool insert(const T& value) | |||||
| { | |||||
| if (Data* const data = _allocate()) | |||||
| { | |||||
| std::memcpy(&data->value, &value, sizeof(T)); | |||||
| list_add(&data->siblings, &fQueue); | |||||
| fCount++; | |||||
| return true; | |||||
| } | |||||
| return false; | |||||
| } | |||||
| T& getAt(const size_t index, const bool remove = false) | T& getAt(const size_t index, const bool remove = false) | ||||
| { | { | ||||
| if (fCount == 0 || index >= fCount) | if (fCount == 0 || index >= fCount) | ||||
| return _retEmpty(); | return _retEmpty(); | ||||
| size_t i = 0; | |||||
| Data* data = nullptr; | Data* data = nullptr; | ||||
| k_list_head* entry; | k_list_head* entry; | ||||
| size_t i = 0; | |||||
| list_for_each(entry, &fQueue) | list_for_each(entry, &fQueue) | ||||
| { | { | ||||
| @@ -113,20 +125,22 @@ public: | |||||
| continue; | continue; | ||||
| data = list_entry(entry, Data, siblings); | data = list_entry(entry, Data, siblings); | ||||
| assert(data); | |||||
| if (remove) | if (remove) | ||||
| { | { | ||||
| fCount--; | fCount--; | ||||
| list_del(entry); | list_del(entry); | ||||
| _deallocate(data); | |||||
| if (data != nullptr) | |||||
| _deallocate(data); | |||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| assert(data); | |||||
| return data->value; | |||||
| CARLA_ASSERT(data != nullptr); | |||||
| return (data != nullptr) ? data->value : _retEmpty(); | |||||
| } | } | ||||
| T& getFirst(const bool remove = false) | T& getFirst(const bool remove = false) | ||||
| @@ -147,9 +161,10 @@ public: | |||||
| list_for_each(entry, &fQueue) | list_for_each(entry, &fQueue) | ||||
| { | { | ||||
| data = list_entry(entry, Data, siblings); | data = list_entry(entry, Data, siblings); | ||||
| assert(data); | |||||
| if (data->value == value) | |||||
| CARLA_ASSERT(data != nullptr); | |||||
| if (data != nullptr && data->value == value) | |||||
| { | { | ||||
| fCount--; | fCount--; | ||||
| list_del(entry); | list_del(entry); | ||||
| @@ -170,9 +185,10 @@ public: | |||||
| list_for_each_safe(entry, tmp, &fQueue) | list_for_each_safe(entry, tmp, &fQueue) | ||||
| { | { | ||||
| data = list_entry(entry, Data, siblings); | data = list_entry(entry, Data, siblings); | ||||
| assert(data); | |||||
| if (data->value == value) | |||||
| CARLA_ASSERT(data != nullptr); | |||||
| if (data != nullptr && data->value == value) | |||||
| { | { | ||||
| fCount--; | fCount--; | ||||
| list_del(entry); | list_del(entry); | ||||
| @@ -184,13 +200,20 @@ public: | |||||
| void splice(List& list, const bool init = false) | void splice(List& list, const bool init = false) | ||||
| { | { | ||||
| if (init) | if (init) | ||||
| { | |||||
| list_splice_init(&fQueue, &list.fQueue); | list_splice_init(&fQueue, &list.fQueue); | ||||
| list.fCount += fCount; | |||||
| fCount = 0; | |||||
| } | |||||
| else | else | ||||
| { | |||||
| list_splice(&fQueue, &list.fQueue); | list_splice(&fQueue, &list.fQueue); | ||||
| list.fCount += fCount; | |||||
| } | |||||
| } | } | ||||
| protected: | protected: | ||||
| const size_t fDataSize; | |||||
| const size_t kDataSize; | |||||
| size_t fCount; | size_t fCount; | ||||
| k_list_head fQueue; | k_list_head fQueue; | ||||
| @@ -214,15 +237,17 @@ private: | |||||
| if (fCount == 0) | if (fCount == 0) | ||||
| return _retEmpty(); | return _retEmpty(); | ||||
| k_list_head* const entry = first ? fQueue.next : fQueue.prev; | |||||
| k_list_head* const entry = first ? fQueue.prev : fQueue.next; | |||||
| Data* const data = list_entry(entry, Data, siblings); | Data* const data = list_entry(entry, Data, siblings); | ||||
| CARLA_ASSERT(data != nullptr); | |||||
| if (data == nullptr) | if (data == nullptr) | ||||
| return _retEmpty(); | return _retEmpty(); | ||||
| T& ret = data->value; | T& ret = data->value; | ||||
| if (data && remove) | |||||
| if (data != nullptr && remove) | |||||
| { | { | ||||
| fCount--; | fCount--; | ||||
| list_del(entry); | list_del(entry); | ||||
| @@ -247,7 +272,7 @@ private: | |||||
| return value; | return value; | ||||
| } | } | ||||
| //LIST_DECLARATIONS(List) | |||||
| LIST_DECLARATIONS(List) | |||||
| }; | }; | ||||
| template<typename T> | template<typename T> | ||||
| @@ -255,9 +280,10 @@ class RtList : public List<T> | |||||
| { | { | ||||
| public: | public: | ||||
| RtList(const size_t minPreallocated, const size_t maxPreallocated) | RtList(const size_t minPreallocated, const size_t maxPreallocated) | ||||
| : fMemPool(nullptr) | |||||
| { | { | ||||
| rtsafe_memory_pool_create(&fMemPool, nullptr, this->fDataSize, minPreallocated, maxPreallocated); | |||||
| assert(fMemPool); | |||||
| rtsafe_memory_pool_create(&fMemPool, nullptr, this->kDataSize, minPreallocated, maxPreallocated); | |||||
| CARLA_ASSERT(fMemPool != nullptr); | |||||
| } | } | ||||
| ~RtList() | ~RtList() | ||||
| @@ -280,9 +306,12 @@ public: | |||||
| { | { | ||||
| this->clear(); | this->clear(); | ||||
| rtsafe_memory_pool_destroy(fMemPool); | |||||
| if (fMemPool != nullptr) | |||||
| rtsafe_memory_pool_destroy(fMemPool); | |||||
| fMemPool = nullptr; | |||||
| rtsafe_memory_pool_create(&fMemPool, nullptr, this->fDataSize, minPreallocated, maxPreallocated); | rtsafe_memory_pool_create(&fMemPool, nullptr, this->fDataSize, minPreallocated, maxPreallocated); | ||||
| assert(fMemPool); | |||||
| CARLA_ASSERT(fMemPool != nullptr); | |||||
| } | } | ||||
| private: | private: | ||||
| @@ -303,7 +332,7 @@ private: | |||||
| return (typename List<T>::Data*)rtsafe_memory_pool_allocate_sleepy(fMemPool); | return (typename List<T>::Data*)rtsafe_memory_pool_allocate_sleepy(fMemPool); | ||||
| } | } | ||||
| void _deallocate(typename List<T>::Data* const dataPtr) | |||||
| void _deallocate(typename List<T>::Data* const dataPtr) | |||||
| { | { | ||||
| rtsafe_memory_pool_deallocate(fMemPool, dataPtr); | rtsafe_memory_pool_deallocate(fMemPool, dataPtr); | ||||
| } | } | ||||
| @@ -329,7 +358,7 @@ private: | |||||
| return (typename List<T>::Data*)malloc(this->fDataSize); | return (typename List<T>::Data*)malloc(this->fDataSize); | ||||
| } | } | ||||
| void _deallocate(typename List<T>::Data* const dataPtr) | |||||
| void _deallocate(typename List<T>::Data* const dataPtr) | |||||
| { | { | ||||
| free(dataPtr); | free(dataPtr); | ||||
| } | } | ||||
| @@ -355,7 +384,7 @@ private: | |||||
| return new typename List<T>::Data; | return new typename List<T>::Data; | ||||
| } | } | ||||
| void _deallocate(typename List<T>::Data* const dataPtr) | |||||
| void _deallocate(typename List<T>::Data* const dataPtr) | |||||
| { | { | ||||
| delete dataPtr; | delete dataPtr; | ||||
| } | } | ||||