annotate transform/ModelTransformer.h @ 1798:13bd41bd8a17

Some work on making Model classes thread-safe in typical use - and documenting this. Some of the implementations are simpler now that EventSeries is thread-safe
author Chris Cannam
date Tue, 01 Oct 2019 11:22:48 +0100
parents 565575463752
children
rev   line source
Chris@320 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@320 2
Chris@320 3 /*
Chris@320 4 Sonic Visualiser
Chris@320 5 An audio file viewer and annotation editor.
Chris@320 6 Centre for Digital Music, Queen Mary, University of London.
Chris@320 7 This file copyright 2006 Chris Cannam.
Chris@320 8
Chris@320 9 This program is free software; you can redistribute it and/or
Chris@320 10 modify it under the terms of the GNU General Public License as
Chris@320 11 published by the Free Software Foundation; either version 2 of the
Chris@320 12 License, or (at your option) any later version. See the file
Chris@320 13 COPYING included with this distribution for more information.
Chris@320 14 */
Chris@320 15
Chris@1367 16 #ifndef SV_MODEL_TRANSFORMER_H
Chris@1367 17 #define SV_MODEL_TRANSFORMER_H
Chris@320 18
Chris@320 19 #include "base/Thread.h"
Chris@320 20
Chris@320 21 #include "data/model/Model.h"
Chris@320 22
Chris@350 23 #include "Transform.h"
Chris@350 24
Chris@320 25 /**
Chris@331 26 * A ModelTransformer turns one data model into another.
Chris@320 27 *
Chris@331 28 * Typically in this application, a ModelTransformer might have a
Chris@320 29 * DenseTimeValueModel as its input (e.g. an audio waveform) and a
Chris@320 30 * SparseOneDimensionalModel (e.g. detected beats) as its output.
Chris@320 31 *
Chris@331 32 * The ModelTransformer typically runs in the background, as a
Chris@331 33 * separate thread populating the output model. The model is
Chris@331 34 * available to the user of the ModelTransformer immediately, but may
Chris@331 35 * be initially empty until the background thread has populated it.
Chris@320 36 */
Chris@331 37 class ModelTransformer : public Thread
Chris@320 38 {
Chris@320 39 public:
Chris@331 40 virtual ~ModelTransformer();
Chris@320 41
Chris@1739 42 typedef std::vector<ModelId> Models;
Chris@849 43
Chris@350 44 class Input {
Chris@350 45 public:
Chris@1739 46 Input(ModelId m) : m_model(m), m_channel(-1) { }
Chris@1739 47 Input(ModelId m, int c) : m_model(m), m_channel(c) { }
Chris@350 48
Chris@1739 49 ModelId getModel() const { return m_model; }
Chris@1739 50 void setModel(ModelId m) { m_model = m; }
Chris@350 51
Chris@350 52 int getChannel() const { return m_channel; }
Chris@350 53 void setChannel(int c) { m_channel = c; }
Chris@350 54
Chris@350 55 protected:
Chris@1739 56 ModelId m_model;
Chris@350 57 int m_channel;
Chris@350 58 };
Chris@350 59
Chris@361 60 /**
Chris@361 61 * Hint to the processing thread that it should give up, for
Chris@1739 62 * example because the process is going to exit or the
Chris@1739 63 * model/document context is being replaced. Caller should still
Chris@1739 64 * wait() to be sure that processing has ended.
Chris@361 65 */
Chris@320 66 void abandon() { m_abandoned = true; }
Chris@320 67
Chris@361 68 /**
Chris@1079 69 * Return true if the processing thread is being or has been
Chris@1079 70 * abandoned, i.e. if abandon() has been called.
Chris@1079 71 */
Chris@1079 72 bool isAbandoned() const { return m_abandoned; }
Chris@1079 73
Chris@1079 74 /**
Chris@361 75 * Return the input model for the transform.
Chris@361 76 */
Chris@1739 77 ModelId getInputModel() { return m_input.getModel(); }
Chris@361 78
Chris@361 79 /**
Chris@361 80 * Return the input channel spec for the transform.
Chris@361 81 */
Chris@350 82 int getInputChannel() { return m_input.getChannel(); }
Chris@350 83
Chris@361 84 /**
Chris@1739 85 * Return the set of output model IDs created by the transform or
Chris@1739 86 * transforms. Returns an empty list if any transform could not be
Chris@1739 87 * initialised; an error message may be available via getMessage()
Chris@1739 88 * in this situation. The returned models have been added to
Chris@1739 89 * ModelById.
Chris@361 90 */
Chris@1211 91 Models getOutputModels() {
Chris@1211 92 awaitOutputModels();
Chris@1211 93 return m_outputs;
Chris@1211 94 }
Chris@361 95
Chris@361 96 /**
Chris@877 97 * Return any additional models that were created during
Chris@877 98 * processing. This might happen if, for example, a transform was
Chris@877 99 * configured to split a multi-bin output into separate single-bin
Chris@877 100 * models as it processed. These should not be queried until after
Chris@877 101 * the transform has completed.
Chris@877 102 */
Chris@877 103 virtual Models getAdditionalOutputModels() { return Models(); }
Chris@877 104
Chris@877 105 /**
Chris@877 106 * Return true if the current transform is one that may produce
Chris@877 107 * additional models (to be retrieved through
Chris@877 108 * getAdditionalOutputModels above).
Chris@877 109 */
Chris@877 110 virtual bool willHaveAdditionalOutputModels() { return false; }
Chris@877 111
Chris@877 112 /**
Chris@361 113 * Return a warning or error message. If getOutputModel returned
Chris@361 114 * a null pointer, this should contain a fatal error message for
Chris@361 115 * the transformer; otherwise it may contain a warning to show to
Chris@361 116 * the user about e.g. suboptimal block size or whatever.
Chris@361 117 */
Chris@361 118 QString getMessage() const { return m_message; }
Chris@361 119
Chris@320 120 protected:
Chris@350 121 ModelTransformer(Input input, const Transform &transform);
Chris@849 122 ModelTransformer(Input input, const Transforms &transforms);
Chris@320 123
Chris@1211 124 virtual void awaitOutputModels() = 0;
Chris@1211 125
Chris@849 126 Transforms m_transforms;
Chris@1739 127 Input m_input;
Chris@1739 128 Models m_outputs;
Chris@320 129 bool m_abandoned;
Chris@361 130 QString m_message;
Chris@320 131 };
Chris@320 132
Chris@320 133 #endif