/[svn]/linuxsampler/trunk/src/engines/InstrumentManagerThread.cpp
ViewVC logotype

Contents of /linuxsampler/trunk/src/engines/InstrumentManagerThread.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1761 - (show annotations) (download)
Fri Aug 29 15:42:06 2008 UTC (15 years, 7 months ago) by iliev
File size: 6743 byte(s)
* fixed a crash which occurs when removing a sampler channel waiting
  to start instrument loading after another channel

1 /***************************************************************************
2 * *
3 * Copyright (C) 2005 - 2007 Christian Schoenebeck *
4 * *
5 * This library is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This library is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this library; if not, write to the Free Software *
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
18 * MA 02111-1307 USA *
19 ***************************************************************************/
20
21 #include "InstrumentManagerThread.h"
22
23 #include "../common/global_private.h"
24
25 namespace LinuxSampler {
26
27 InstrumentManagerThread::InstrumentManagerThread() : Thread(true, false, 0, -4) {
28 eventHandler.pThread = this;
29 }
30
31 InstrumentManagerThread::~InstrumentManagerThread() {
32 }
33
34 /**
35 * @brief Order loading of a new instrument.
36 *
37 * The request will go into a queue waiting to be processed by the
38 * class internal task thread. This method will immediately return and
39 * the instrument will be loaded in the background.
40 *
41 * @param Filename - file name of the instrument
42 * @param uiInstrumentIndex - index of the instrument within the file
43 * @param pEngineChannel - engine channel on which the instrument should be loaded
44 */
45 void InstrumentManagerThread::StartNewLoad(String Filename, uint uiInstrumentIndex, EngineChannel* pEngineChannel) {
46 dmsg(1,("Scheduling '%s' (Index=%d) to be loaded in background (if not loaded yet).\n",Filename.c_str(),uiInstrumentIndex));
47
48 static bool listenerRegistered = false;
49 if (!listenerRegistered) {
50 pEngineChannel->GetSampler()->AddChannelCountListener(&eventHandler);
51 listenerRegistered = true;
52 }
53
54
55 // already tell the engine which instrument to load
56 pEngineChannel->PrepareLoadInstrument(Filename.c_str(), uiInstrumentIndex);
57
58 command_t cmd;
59 cmd.type = command_t::DIRECT_LOAD;
60 cmd.pEngineChannel = pEngineChannel;
61
62 mutex.Lock();
63 queue.push_back(cmd);
64 mutex.Unlock();
65
66 StartThread(); // ensure thread is running
67 conditionJobsLeft.Set(true); // wake up thread
68 }
69
70 /**
71 * @brief Order changing the life-time strategy of an instrument.
72 *
73 * The request will go into a queue waiting to be processed by the
74 * class internal task thread. This method will immediately return and
75 * in case the instrument has to be loaded due to a mode change to
76 * PERSISTENT, it will be loaded in the background.
77 *
78 * @param pManager - InstrumentManager which manages the instrument
79 * @param ID - unique ID of the instrument
80 * @param Mode - life-time strategy to set for this instrument
81 */
82 void InstrumentManagerThread::StartSettingMode(InstrumentManager* pManager, const InstrumentManager::instrument_id_t& ID, InstrumentManager::mode_t Mode) {
83 command_t cmd;
84 cmd.type = command_t::INSTR_MODE;
85 cmd.pManager = pManager;
86 cmd.instrumentId = ID;
87 cmd.mode = Mode;
88
89 mutex.Lock();
90 queue.push_back(cmd);
91 mutex.Unlock();
92
93 StartThread(); // ensure thread is running
94 conditionJobsLeft.Set(true); // wake up thread
95 }
96
97 // Entry point for the task thread.
98 int InstrumentManagerThread::Main() {
99 while (true) {
100
101 #if CONFIG_PTHREAD_TESTCANCEL
102 TestCancel();
103 #endif
104
105 while (!queue.empty()) {
106 command_t cmd;
107
108 // grab a new command from the queue
109 mutex.Lock();
110 cmd = queue.front();
111 queue.pop_front();
112 mutex.Unlock();
113
114 try {
115 switch (cmd.type) {
116 case command_t::DIRECT_LOAD:
117 cmd.pEngineChannel->LoadInstrument();
118 break;
119 case command_t::INSTR_MODE:
120 cmd.pManager->SetMode(cmd.instrumentId, cmd.mode);
121 break;
122 default:
123 std::cerr << "InstrumentManagerThread: unknown command - BUG!\n" << std::flush;
124 }
125 } catch (Exception e) {
126 e.PrintMessage();
127 } catch (...) {
128 std::cerr << "InstrumentManagerThread: some exception occured, could not finish task\n" << std::flush;
129 }
130 }
131
132 // nothing left to do, sleep until new jobs arrive
133 conditionJobsLeft.WaitIf(false);
134 // reset flag
135 conditionJobsLeft.Set(false);
136 // unlock condition object so it can be turned again by other thread
137 conditionJobsLeft.Unlock();
138 }
139 }
140
141 void InstrumentManagerThread::EventHandler::ChannelToBeRemoved(SamplerChannel* pChannel) {
142 /*
143 Removing from the queue an eventual scheduled loading of an instrument
144 to a sampler channel which is going to be removed.
145 */
146 pThread->mutex.Lock();
147 std::list<command_t>::iterator it;
148 for (it = pThread->queue.begin(); it != pThread->queue.end();){
149 if ((*it).type != command_t::DIRECT_LOAD) { ++it; continue; }
150 if ((*it).pEngineChannel == pChannel->GetEngineChannel()) {
151 it = pThread->queue.erase(it);
152 // we don't break here because the same engine channel could
153 // occur more than once in the queue, so don't make optimizations
154 } else {
155 ++it;
156 }
157 }
158 pThread->mutex.Unlock();
159 }
160 } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC