annotate base/Scavenger.h @ 1833:21c792334c2e sensible-delimited-data-strings

Rewrite all the DelimitedDataString stuff so as to return vectors of individual cell strings rather than having the classes add the delimiters themselves. Rename accordingly to names based on StringExport. Take advantage of this in the CSV writer code so as to properly quote cells that contain delimiter characters.
author Chris Cannam
date Fri, 03 Apr 2020 17:11:05 +0100
parents ad5f892c0c4d
children
rev   line source
Chris@49 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@0 2
Chris@0 3 /*
Chris@52 4 Sonic Visualiser
Chris@52 5 An audio file viewer and annotation editor.
Chris@52 6 Centre for Digital Music, Queen Mary, University of London.
Chris@52 7 This file copyright 2006 Chris Cannam.
Chris@0 8
Chris@52 9 This program is free software; you can redistribute it and/or
Chris@52 10 modify it under the terms of the GNU General Public License as
Chris@52 11 published by the Free Software Foundation; either version 2 of the
Chris@52 12 License, or (at your option) any later version. See the file
Chris@52 13 COPYING included with this distribution for more information.
Chris@0 14 */
Chris@0 15
Chris@0 16 /*
Chris@0 17 This is a modified version of a source file from the
Chris@0 18 Rosegarden MIDI and audio sequencer and notation editor.
Chris@17 19 This file copyright 2000-2006 Chris Cannam.
Chris@0 20 */
Chris@0 21
Chris@1581 22 #ifndef SV_SCAVENGER_H
Chris@1581 23 #define SV_SCAVENGER_H
Chris@0 24
Chris@150 25 #include "system/System.h"
Chris@0 26
Chris@0 27 #include <vector>
Chris@158 28 #include <list>
Chris@178 29 #include <QMutex>
Chris@158 30 #include <iostream>
Chris@0 31
Chris@0 32 /**
Chris@0 33 * A very simple class that facilitates running things like plugins
Chris@0 34 * without locking, by collecting unwanted objects and deleting them
Chris@0 35 * after a delay so as to be sure nobody's in the middle of using
Chris@0 36 * them. Requires scavenge() to be called regularly from a non-RT
Chris@0 37 * thread.
Chris@0 38 *
Chris@0 39 * This is currently not at all suitable for large numbers of objects
Chris@0 40 * -- it's just a quick hack for use with things like plugins.
Chris@0 41 */
Chris@0 42
Chris@0 43 template <typename T>
Chris@0 44 class Scavenger
Chris@0 45 {
Chris@0 46 public:
Chris@0 47 Scavenger(int sec = 2, int defaultObjectListSize = 200);
Chris@158 48 ~Scavenger();
Chris@0 49
Chris@0 50 /**
Chris@0 51 * Call from an RT thread etc., to pass ownership of t to us.
Chris@0 52 * Only one thread should be calling this on any given scavenger.
Chris@0 53 */
Chris@0 54 void claim(T *t);
Chris@0 55
Chris@0 56 /**
Chris@0 57 * Call from a non-RT thread.
Chris@0 58 * Only one thread should be calling this on any given scavenger.
Chris@0 59 */
Chris@14 60 void scavenge(bool clearNow = false);
Chris@0 61
Chris@0 62 protected:
Chris@1039 63 typedef std::pair<T *, time_t> ObjectTimePair;
Chris@0 64 typedef std::vector<ObjectTimePair> ObjectTimeList;
Chris@0 65 ObjectTimeList m_objects;
Chris@1039 66 time_t m_sec;
Chris@0 67
Chris@158 68 typedef std::list<T *> ObjectList;
Chris@158 69 ObjectList m_excess;
Chris@1039 70 time_t m_lastExcess;
Chris@178 71 QMutex m_excessMutex;
Chris@158 72 void pushExcess(T *);
Chris@1039 73 void clearExcess(time_t);
Chris@158 74
Chris@0 75 unsigned int m_claimed;
Chris@0 76 unsigned int m_scavenged;
Chris@0 77 };
Chris@0 78
Chris@0 79 /**
Chris@0 80 * A wrapper to permit arrays to be scavenged.
Chris@0 81 */
Chris@0 82
Chris@0 83 template <typename T>
Chris@0 84 class ScavengerArrayWrapper
Chris@0 85 {
Chris@0 86 public:
Chris@0 87 ScavengerArrayWrapper(T *array) : m_array(array) { }
Chris@0 88 ~ScavengerArrayWrapper() { delete[] m_array; }
Chris@0 89
Chris@0 90 private:
Chris@0 91 T *m_array;
Chris@0 92 };
Chris@0 93
Chris@0 94
Chris@0 95 template <typename T>
Chris@0 96 Scavenger<T>::Scavenger(int sec, int defaultObjectListSize) :
Chris@0 97 m_objects(ObjectTimeList(defaultObjectListSize)),
Chris@0 98 m_sec(sec),
Chris@252 99 m_lastExcess(0),
Chris@0 100 m_claimed(0),
Chris@0 101 m_scavenged(0)
Chris@0 102 {
Chris@158 103 }
Chris@158 104
Chris@158 105 template <typename T>
Chris@158 106 Scavenger<T>::~Scavenger()
Chris@158 107 {
Chris@158 108 if (m_scavenged < m_claimed) {
Chris@1429 109 for (size_t i = 0; i < m_objects.size(); ++i) {
Chris@1429 110 ObjectTimePair &pair = m_objects[i];
Chris@1429 111 if (pair.first != 0) {
Chris@1429 112 T *ot = pair.first;
Chris@1429 113 pair.first = 0;
Chris@1429 114 delete ot;
Chris@1429 115 ++m_scavenged;
Chris@1429 116 }
Chris@1429 117 }
Chris@158 118 }
Chris@158 119
Chris@158 120 clearExcess(0);
Chris@0 121 }
Chris@0 122
Chris@0 123 template <typename T>
Chris@0 124 void
Chris@0 125 Scavenger<T>::claim(T *t)
Chris@0 126 {
Chris@0 127 // std::cerr << "Scavenger::claim(" << t << ")" << std::endl;
Chris@0 128
Chris@0 129 struct timeval tv;
Chris@0 130 (void)gettimeofday(&tv, 0);
Chris@1039 131 time_t sec = tv.tv_sec;
Chris@0 132
Chris@0 133 for (size_t i = 0; i < m_objects.size(); ++i) {
Chris@1429 134 ObjectTimePair &pair = m_objects[i];
Chris@1429 135 if (pair.first == 0) {
Chris@1429 136 pair.second = sec;
Chris@1429 137 pair.first = t;
Chris@1429 138 ++m_claimed;
Chris@1429 139 return;
Chris@1429 140 }
Chris@0 141 }
Chris@0 142
Chris@158 143 std::cerr << "WARNING: Scavenger::claim(" << t << "): run out of slots, "
Chris@1429 144 << "using non-RT-safe method" << std::endl;
Chris@158 145 pushExcess(t);
Chris@0 146 }
Chris@0 147
Chris@0 148 template <typename T>
Chris@0 149 void
Chris@14 150 Scavenger<T>::scavenge(bool clearNow)
Chris@0 151 {
Chris@0 152 // std::cerr << "Scavenger::scavenge: scavenged " << m_scavenged << ", claimed " << m_claimed << std::endl;
Chris@0 153
Chris@0 154 if (m_scavenged >= m_claimed) return;
Chris@0 155
Chris@0 156 struct timeval tv;
Chris@0 157 (void)gettimeofday(&tv, 0);
Chris@1039 158 time_t sec = tv.tv_sec;
Chris@0 159
Chris@0 160 for (size_t i = 0; i < m_objects.size(); ++i) {
Chris@1429 161 ObjectTimePair &pair = m_objects[i];
Chris@1429 162 if (clearNow ||
Chris@1429 163 (pair.first != 0 && pair.second + m_sec < sec)) {
Chris@1429 164 T *ot = pair.first;
Chris@1429 165 pair.first = 0;
Chris@1429 166 delete ot;
Chris@1429 167 ++m_scavenged;
Chris@1429 168 }
Chris@0 169 }
Chris@158 170
Chris@158 171 if (sec > m_lastExcess + m_sec) {
Chris@158 172 clearExcess(sec);
Chris@158 173 }
Chris@158 174 }
Chris@158 175
Chris@158 176 template <typename T>
Chris@158 177 void
Chris@158 178 Scavenger<T>::pushExcess(T *t)
Chris@158 179 {
Chris@178 180 m_excessMutex.lock();
Chris@158 181 m_excess.push_back(t);
Chris@158 182 struct timeval tv;
Chris@158 183 (void)gettimeofday(&tv, 0);
Chris@158 184 m_lastExcess = tv.tv_sec;
Chris@178 185 m_excessMutex.unlock();
Chris@158 186 }
Chris@158 187
Chris@158 188 template <typename T>
Chris@158 189 void
Chris@1039 190 Scavenger<T>::clearExcess(time_t sec)
Chris@158 191 {
Chris@178 192 m_excessMutex.lock();
Chris@158 193 for (typename ObjectList::iterator i = m_excess.begin();
Chris@1429 194 i != m_excess.end(); ++i) {
Chris@1429 195 delete *i;
Chris@158 196 }
Chris@158 197 m_excess.clear();
Chris@158 198 m_lastExcess = sec;
Chris@178 199 m_excessMutex.unlock();
Chris@0 200 }
Chris@0 201
Chris@0 202 #endif